Opened 13 years ago

Last modified 13 years ago

#16714 closed Bug

Can't filter by a related object's field called 'year', 'month' or 'day' — at Version 4

Reported by: Alex Ogier Owned by: nobody
Component: Database layer (models, ORM) Version: 1.3
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Julien Phalip)

UPDATE: The problem was originally reported in the admin but it appears it is rather an issue with the ORM -- see discussion below.

If you have a SmallIntegerField on a model that is related via a foreign key then you can't use that field as an option in list_filter. Doing so gives you the correct distinct options in the list page sidebar, but if you try to select any of them you receive a 302 redirect to /?e=1, as if you had used an unexpected query-string parameter.

Here's a small example to try yourself:

# models.py

from django.db import models

class Rel(models.Model):
    year = models.SmallIntegerField(default=2010)

class Src(models.Model):
    rel = models.ForeignKey(Rel)

# admin.py

from models import Rel, Src
from django.contrib import admin

class RelAdmin(admin.ModelAdmin):
    model = Rel
    list_filter = ('year',)
admin.site.register(Rel, RelAdmin)

class SrcAdmin(admin.ModelAdmin):
    model = Src
    list_filter = ('rel__year',)
admin.site.register(Src, SrcAdmin)

I'm running Django 1.3, MySQL 5.5, on Arch Linux.

Change History (4)

comment:1 by Julien Phalip, 13 years ago

Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

Hmm, the root cause of this seems like a problem not in the admin but deeper down in the ORM:

>>> Src.objects.filter(rel__year=2010)
...
TypeError: Related Field has invalid lookup: year

I would think perhaps the lookup should be 'exact' instead of 'year'. A separate ticket should probably be created for that. I'd like to hear from someone with more ORM-foo than me to confirm.

However, this highlights a regression in the admin, as the development version returns a 500 instead of redirecting with "?e=1".

in reply to:  1 comment:2 by Alex Ogier, 13 years ago

Replying to julien:

I would think perhaps the lookup should be 'exact' instead of 'year'.

That's interesting, because that's not how things work with plain IntegerFields.

comment:3 by Julien Phalip, 13 years ago

Interesting, indeed. I might be missing something fundamental but I'm puzzled as to why TypeErrors are raised in the following:

>>> Rel.objects.filter(year=u'2010')
[<Rel: Rel object>]
>>> Rel.objects.filter(year=2010)
[<Rel: Rel object>]
>>> Rel.objects.filter(year__exact=2010)
[<Rel: Rel object>]
>>> Src.objects.filter(rel__year__exact=2010)
[<Src: Src object>]
>>> Src.objects.filter(rel__year__exact=u'2010')
[<Src: Src object>]
>>> Src.objects.filter(rel__year=2010)
...
TypeError: Related Field has invalid lookup: year
>>> Src.objects.filter(rel__year=u'2010')
...
TypeError: Related Field has invalid lookup: year

comment:4 by Julien Phalip, 13 years ago

Component: contrib.adminDatabase layer (models, ORM)
Description: modified (diff)
Severity: Release blockerNormal
Summary: Can't list_filter across a relationship on a SmallIntegerFieldCan't filter by a related object's field called 'year', 'month' or 'day'

Some further investigation shows that the problem has nothing to do with the type of field (SmallIntegerField, CharField, ...) -- the issue is in fact with the *name* of the field. The same "TypeError: Related Field has invalid lookup: xxxx" exception is raised for any fields named year, month or day on the related model. There is obviously some sort of conflict with the date lookup system, although it seems strange that the RelatedField isn't more smart about it. It's also strange that this issue didn't surface for all those years as the use case is quite trivial...

There's still a regression with the way the admin changelist handles exceptions (the dev version crashes with a 500 instead of redirecting) and I've created a separate ticket for that: #16716.

Let's keep this ticket here to discuss the ORM issue. This is not a regression though, as it already existed at least in 1.3, so I'm removing the 'blocker' flag.

Note: See TracTickets for help on using tickets.
Back to Top