Django

Code

Documentation suggestions

If you've looked for something in the docs, failed to find it, and then worked out the details yourself, add it here so that others might find it. This is a sort-of documentation wishlist, and topics should be removed from here when they're incorporated in official docs or put elsewhere on the wiki.

If you update the model, how do you update the database tables without losing data?

It's easy to destroy and rectreate your tables, but it's a bit more tricky if the database already contains data you wish to preserve. There's some stuff in the FAQ about this, and why there isn't an automatic way to do it.

A concrete example would be nice, though, at least for the simple case of adding an extra field. One way to do it is as follows: When you've added a field to a model, run django-admin.py sql <appname> to see the SQL that Django is expecting, and modify your database using the method you prefer.

If you're using MySQL, you can use a tool like phpMyAdmin and then use mysqldump -d -u user -p database to compare the results for that table and see whether you got it right! There's more than one way to express the same thing in SQL, though, so they might not look identical. In particular, specifications of which fields are indexes or primary keys may be done as part of the line describing that field or may be separate. The following are (roughly) equivalent:

Produced by django-admin.py sql:

CREATE TABLE gb_tasks (
    id mediumint(9) unsigned auto_increment NOT NULL PRIMARY KEY,
    info varchar(255) NOT NULL
);

Produced by mysqldump:

CREATE TABLE gb_tasks (
  id mediumint(9) unsigned NOT NULL auto_increment,
  info varchar(255) NOT NULL default '',
  PRIMARY KEY  (id)
) TYPE=MyISAM;

Alternatively, if you're happy writing your own SQL, you can use ALTER TABLE to modify or add existing fields and use the output of django-admin.py to give you an idea for the modifications you need to make. It might look something like this:

$ mysql -u user1 -ppasswd database

mysql> 
mysql> ALTER TABLE gb_tasks ADD COLUMN notes VARCHAR(255);

or

mysql> ALTER TABLE gb_tasks MODIFY notes LONGTEXT NULL;

The syntax for ALTER TABLE will vary a bit depending on the database package you're using. Backing up anything valuable beforehand is definitely a good idea! In recent versions of MySQL you can back up a complete table using something like:

mysql> CREATE TABLE gb_tasks_backup select * from gb_tasks;

SQL initial data

Information about when 'django-admin.py sqlinitialdata' needs to be used to update things, and how to do that on an already-running system.

  • I added a second user and found that she didn't have permissions to view certain pages despite being a 'staff' user, probably because the model had been updated since the first version.
  • I also found myself getting 'content-type' errors because Django didn't know the appropriate MIME content-type to specify for certain new models.

Both of these were fixed by running django-admin.py sqlinitialdata <appname> and piping the resulting SQL into the database Some of the content it produces already exists in the database, so you either need to erase it first, or edit the SQL before using it, or tell your database to ignore errors if it complains about duplicate data. I did the latter - this may not be generally safe! It worked for me, though, because the tables concerned have UNIQUE KEYs which stop purely duplicate entries:

$ django-admin.py sqlinitialdata <appname> | mysql -f -u <username> -p<passwd> <database>

Template inheritance and block

I have discovered following "features" of template inheritance, they are not very obvious and can be added to django documentation:

  • If template A extends another template then only *block* tags are evaluated in template A
  • Variables that are placed in context (f.e. in custom tag) inside *block* are visible only in this block and discarded outside it (because of Context.push/pop)

Large Tables

This is a bug. MySQL generated tables should use integer for AutoField columns. You can get the patch with ticket #1500

The default id column on a Django table can auto increment through 16,777,215 rows before stopping dead in its' tracks. (At least that is the default behaviour for mySQL.) Need more rows? Install the model that you want to enlarge in the normal manner (manage.py install myapp) and then alter the table with these SQL commands:

ALTER TABLE mytable MODIFY id BIGINT AUTO_INCREMENT NOT NULL;

ALTER TABLE mytable MAX_ROWS = 4294967295;

What is the minimal Django application?

What's the simplest arrangement that utlizes all the main Django components (ORM, view code, templates, admin)? (Because sometimes seeing the simplest form makes the more complicated ones easier to understand.)

I'll take a stab at outlining a minimal Django app that uses the listed features. In this example "app" is what we usually think of as the project directory. I.e. in INSTALLED_APPS it would be listed simply as 'app' (assuming of course that the dir is on your path).

app
    models.py
    settings.py
    templates
        base.html
    urls.py
    views.py

How do I construct releative urls?

Apply the patch from #66 for request.app_root. If you include an app in your urls.py

 (r'^polls/', include('myproject.apps.polls.urls.polls')),

Then request.app_root returns "/polls/". So now the app can do:

    def get_absolute_url(self, request):
        return request.app_root + '%s/' % self.id  #returns "/poll/3/"

Django Cheat Sheet

DjangoCheatSheet : A quick start guide to beginning a project

Prominent Link for 'More Django Resources'

Problem: Users new to django write comment, tag and blog applications themselves since they don't know several nice (bsd-licensed)-solutions exist already. Solution: Add link to http://code.djangoproject.com/wiki/DjangoResources at the bottom of http://djangoproject.com/documentation