Column comparison in Django queries

Question:

I have a following model:

class Car(models.Model):
    make = models.CharField(max_length=40)
    mileage_limit = models.IntegerField()
    mileage = models.IntegerField()

I want to select all cars where mileage is less than mileage_limit, so in SQL it would be something like:

select * from car where mileage < mileage_limit;

Using Q object in Django, I know I can compare columns with any value/object, e.g. if I wanted to get cars that have mileage say less than 100,000 it would be something like:

cars = Car.objects.filter(Q(mileage__lt=100000))

Instead of a fixed value I would like to use the column name (in my case it is mileage_limit). So I would like to be able to do something like:

cars = Car.objects.filter(Q(mileage__lt=mileage_limit))

However this results in an error, since it is expecting a value/object, not a column name. Is there a way to compare two columns using Q object? I feel like it would be a very commonly used feature and there should be an easy way to do this, however couldn’t find anything about it in the documentation.

Note: this is a simplified example, for which the use of Q object might seem to be unnecessary. However the real model has many more columns, and the real query is more complex, that’s why I am using Q. Here in this question I just wanted to figure out specifically how to compare columns using Q.

EDIT

Apparently after release of Django 1.1 it would be possible to do the following:

cars = Car.objects.filter(mileage__lt=F('mileage_limit'))

Still not sure if F is supposed to work together with Q like this:

cars = Car.objects.filter(Q(mileage__lt=F('mileage_limit')))
Asked By: Sergey Golovchenko

||

Answers:

You can’t do this right now without custom SQL. The django devs are working on an F() function that would make it possible: #7210 – F() syntax, design feedback required.

Answered By: Ned Batchelder

Since I had to look this up based on the accepted answer, I wanted to quickly mention that the F() expression has indeed been released and is available for being used in queries.

This is what the Django documentation on F() says about it:

An F() object represents the value of a model field, transformed value of a model field, or annotated column. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.

Instead, Django uses the F() object to generate an SQL expression that describes the required operation at the database level.

The reference for making queries using F() also gives useful examples.

Answered By: ingofreyer
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.