views:

1999

answers:

2

I'm currently coding a site in Django (because you can never learn too many frameworks!), and am wondering if there's a way to auto-increment an object with respect to a related object. So for instance, say I have an Entry model and an EntryVersion model:

Entry
- title
- slug

EntryVersion
- entry (foreign key)
- version_number
- content

I want to auto-increment version_number with respect to the entry foreign key (so that an entry might have several versions, starting at one and moving upwards by one). It won't be a true auto-increment, though, because it won't be unique in the database (there might be many entry versions with version_number = 1; just only one for a given Entry).

I know that I could roll my own admin and just handle this there, but was wondering if there were any way to have the Django admin automatically increase the version number by one whenever a new entry version is saved.


Edit: specific code that I used (corrected to only set version number on first save)

Tiago's answer was right, but in the interest of future StackOverflow users with similar dilemmas, here's the specific code that I used:

def save(self, force_insert=False, force_update=False):
    # Only modify number if creating for the first time (is default 0)
    if self.version_number == 0:
        # Grab the highest current index (if it exists)
        try:
            recent = EntryVersion.objects.filter(entry__exact=self.entry).order_by('-version_number')[0]
            self.version_number = recent.version_number + 1
        except IndexError:
            self.version_number = 1
    # Call the "real" save() method
    super(EntryVersion, self).save(force_insert, force_update)

The order_by w/ index trick is one I gleaned from the Django documentation here:

http://docs.djangoproject.com/en/dev/topics/db/queries/#id4

Note that you must have default=0 defined on your version_number field for this to work.

There may be a better way, but this seems to be working exactly the way I needed; hopefully others will also find it useful.

A: 

I'm not sure I 100% grok your use case. Could you just do this in the Entry's save method?

Andy Hume
Apparently so; have I exposed my Django newbie-ness enough yet? :-)
One Crayon
+2  A: 

Hi,

You can do this:

def save(self, force_insert=False, force_update=False):
    #if self.id is None:
    self.version_number += 1

    super(EntryVersion, self).save(force_insert, force_update) # Call the "real" save() method.

which comes directly from here:

http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods

Tiago
Thanks! Obviously I'll need to add a bit more logic than just incrementing the version_number (since it presumably won't default to the last version number), but I think that's definitely the direction I need to head in; thanks also for the link, I didn't notice that in the docs.
One Crayon
I did something like this in one project, but I ended up puting the logic inside the view, as that was simpler and there were only one method that can created my object.
Tiago
I might end up migrating to the view, but I specifically wanted to be able to have this Just Work in the admin right now (since I'm in the very early testing stages and don't have any editing views setup yet). Thanks again!
One Crayon