Question

So I have a model MyModel with a ForeignKey field fkfield. And i need to do something like this (simplified):

MyModel.objects.values_list('id', 'fkfield').order_by('fkfield')

For example I want to groupby them further by fkfield so I need my objects to be sorted by this field. And the only thing I will use later is fkfield_id. I mean I dont need any data from related model.

But django performs a join sql query (as described in docs) and uses related model's ordering. The same happens if i explicitly try to order by id:

MyModel.objects.values_list('id', 'fkfield').order_by('fkfield__id')

and I get:

SELECT `mymodel`.`id`, 
       `mymodel`.`fkfield_id` 
  FROM `mymodel` 
       LEFT OUTER JOIN `related_table` 
            ON ( `mymodel`.`fkfield_id` = `related_table`.`id` ) 
ORDER BY 
       `related_table`.`id` ASC

What i really expect is:

SELECT `id`, 
       `fkfield_id` 
  FROM `mymodel` 
ORDER BY 
       `fkfield_id` ASC

But I can't find a way to do it. .order_by('fkfield_id') raises exception that says that there is no such a field.

I managed to get things work using extra but I can't understand why such a simple and obvious behaviour can't be used without hacks. Or maybe i missed smth?

UPDATE: models.py

class Producer(models.Model):
    name = models.CharField(max_length=100)

    class Meta:
        ordering = ('name',)

class Collection(models.Model):
    name = models.CharField(max_length=100)
    producer = models.ForeignKey('Producer')

    class Meta:
        ordering = ('name',)

print Collection.objects.values_list('producer', 'id').order_by('producer').query
>>> SELECT `catalog_collection`.`producer_id`, `catalog_collection`.`id`
>>> FROM `catalog_collection`
>>> INNER JOIN `catalog_producer` ON
>>> (`catalog_collection`.`producer_id` = `catalog_producer`.`id`)
>>> ORDER BY `catalog_producer`.`name` ASC

No correct solution

OTHER TIPS

Try

.order_by('fkfield')

My query is

Post.objects.values('author', 'id').order_by('author')

as sql:

SELECT "blogs_post"."author_id", 
       "blogs_post"."id" 
FROM "blogs_post" 
ORDER BY "blogs_post"."author_id" ASC

UPDATE

Kind of messy solution:

MyModel.objects.extra(select={'fkfield_id': 'fkfield_id'})\
       .values_list('id', 'fkfield_id')\
       .order_by('fkfield_id')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top