3

I have a django model that looks like this:

class MyModel(Model):
    name = CharField(...)
    version = IntegerField(...)
    other_stuff = ...

    unique_together = ('name', 'version')

I want to be able to query for all of the most recent versions of each name, but omitting all older versions for any given name.

Is this possible with Django models? If so, what would that look like?

pojo
  • 5,892
  • 9
  • 35
  • 47
Chris R
  • 17,546
  • 23
  • 105
  • 172

2 Answers2

4

I'm not sure you can do that right away just with the aggregation features of the Django ORM. Anyway, I think this structure is screaming a modeling like this:

class MyModel(Model):
    name = CharField(...)
    some_stuff = ...

class Version(Model):
    number = IntegerField(...)
    my_model = ForeignKey(MyModel, ...)
    other_stuff = ...

So you could do this to get the newest version of every MyModel:

>>> from django.db.models import Max
>>> MyModel.objects.annotate(highest_version = Max('version__number'))
Chewie
  • 7,095
  • 5
  • 29
  • 36
  • What would that look like for my use case? Can you show me how I would A) List all models at their latest versions, B) get a specific model at any version, and C) where this "annotate" thing would be done? – Chris R Feb 02 '12 at 15:22
1

I believe you need to group by name, then select on each group. Never used this myself, but this question may offer some insights on how to do it.

Update: it seems I got the code right, but while it should work for your specific case I don't know yet how to get the other fields in the same query (suppose you wanted not only the version numbers but the other stuff too - this solution won't work):

from django.db.models import Max
MyModel.objects.values('name').annotate(Max('version'))

# Will return something like:
# [{'name':'a', 'version__max':3}, {'name':'b', 'version__max':2}, ...]

If you're using Django 1.4 and PostgreSQL, you might be able to do that using the distinct method:

MyModel.objects.order_by('name', '-version').distinct('name')
Community
  • 1
  • 1
mgibsonbr
  • 21,755
  • 7
  • 70
  • 112