views:

562

answers:

3

Hi folks,

Does anyone knows how to load initial data for auth.User using sql fixtures? For my models, I just got have a < modelname >.sql file in a folder named sql that syncdb does it's job beautifully. But I have no clue how to do it for the auth.User model. I've googled it, but with no success.

Thanks in advance,

Aldo

+1  A: 

You are looking for loaddata:

manage.py loadata path/to/your/fixtureFile

But I think the command can only deal with files in XML, YAML, Python or JSON format (see here). To create such appropriate files, have a look at the dumpdata method.

Felix Kling
I know but, is there a way to automate that, just like normal fixtures are called in syncdb?
aldux
@aldux: Afaik not
Felix Kling
+1  A: 

An option is to import your auth.User SQL manually and subsequently dump it out to a standard Django fixture (name it initial_data if you want syncdb to find it). You can generally put this file into any app's fixtures dir since the fixtured data will all be keyed with the proper app_label. Or you can create an empty/dummy app and place it there.

Another option is to override the syncdb command and apply the fixture in a manner as you see fit.

I concur with Felix that there is no non-trivial natural hook in Django for populating contrib apps with SQL.

Brian Luft
+2  A: 

Hi folks,

Thanks for your answers. I've found the solution that works for me, and for coincidence was one of Brian's suggestion. Here it is:

Firs I disconnected the signal that created the Super User after syncdb, for I have my super user in my auth_user fixture:

models.py:

from django.db.models import signals
from django.contrib.auth.management import create_superuser
from django.contrib.auth import models as auth_app


signals.post_syncdb.disconnect(
    create_superuser,
    sender=auth_app,
    dispatch_uid = "django.contrib.auth.management.create_superuser")

Then I created a signal to be called after syncdb:

< myproject >/< myapp >/management/_init_.py

"""
Loads fixtures for files in sql/<modelname>.sql
"""
from django.db.models import get_models, signals
from django.conf import settings 
import <myproject>.<myapp>.models as auth_app

def load_fixtures(app, **kwargs):
    import MySQLdb
    db=MySQLdb.connect(host=settings.DATABASE_HOST or "localhost", \
       user=settings.DATABASE_USER,
    passwd=settings.DATABASE_PASSWORD, port=int(settings.DATABASE_PORT or 3306))

    cursor = db.cursor()

    try:
        print "Loading fixtures to %s from file %s." % (settings.DATABASE_NAME, \
            settings.FIXTURES_FILE)
        f = open(settings.FIXTURES_FILE, 'r')
        cursor.execute("use %s;" % settings.DATABASE_NAME)
        for line in f:
            if line.startswith("INSERT"):
                try:
                    cursor.execute(line)
                except Exception, strerror:
                    print "Error on loading fixture:"
                    print "-- ", strerror
                    print "-- ", line

        print "Fixtures loaded"

    except AttributeError:
        print "FIXTURES_FILE not found in settings. Please set the FIXTURES_FILE in \
            your settings.py" 

    cursor.close()
    db.commit()
    db.close()

signals.post_syncdb.connect(load_fixtures, sender=auth_app, \
    dispatch_uid = "<myproject>.<myapp>.management.load_fixtures")

And in my settings.py I added FIXTURES_FILE with the path to my .sql file with the sql dump.

One thing that I still haven't found is how to fire this signal only after the tables are created, and not everytime syncdb is fired. A temporary work around for this is use INSERT IGNORE INTO in my sql command.

I know this solution is far from perfect, and critics/improvements/opinions are very welcome!

Regards,

Aldo

aldux