Code

Opened 4 years ago

Closed 4 years ago

#13611 closed (wontfix)

get_next_by_FOO allows nulls

Reported by: CarlFK Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

http://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_next_by_FOO

says

"For every DateField and DateTimeField that does not have null=True, the object will have get_next_by_FOO()"

which is correct given this line of code:

if not self.null:

http://code.djangoproject.com/browser/django/trunk/django/db/models/fields/__init__.py#L630

I have a need for this to work on a nullable field, so I removed the restriction. The code change is fairly trivial, documenting the resulting behavior was the hard part, but after some lengthy IRC debates that included looking at what the sql97 spec on how nulls were handled by order_by, we came to a consensus.

Docs: remove “that does not have null=True” add: "There are 2 groups of rows that can be iterated over using .get_next/previous: those with values and those with nulls. Going beyond the edge of either set raises DoesNotExist." That is all that needs to be documented. This does not explain how nulls and non nulls are related: they aren't. Which doesn't explain anything. Here are my thoughts: If the application developer wants the first null to come after the last value, they will have to code that in their app. Or vice-versa. The app developer should be given the choice to treat the 2 sets as one continuum or not, and be given the choice of nulls coming before or after the values.

How I use it:

    try:
        prev_episode = episode.get_previous_by_start(state=episode.state)
    except Episode.DoesNotExist:
        # at edge of the set of nulls or values.  
        # In this app, *nulls come before values*.
        if episode.start is not None:
            # we are at the first value, try to go to the last null
            try:
                prev_episode = Episode.objects.filter(start__isnull=True).order_by('id').reverse()[0]
            except Episode.DoesNotExist:
                # There are no nulls
                prev_episode = None
        else:
            # there is no privious null, we have nowhere to go.
            prev_episode = None

There is a similar block for next_episode=episode.get_next which can be seen in my app: http://github.com/CarlFK/veyepar/blob/master/dj/main/views.py#L366

Attachments (1)

carls_cool_next_by_nullable_FOO.diff (4.2 KB) - added by CarlFK 4 years ago.

Download all attachments as: .zip

Change History (2)

Changed 4 years ago by CarlFK

comment:1 Changed 4 years ago by russellm

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to wontfix
  • Status changed from new to closed

You say "we" discussed this on IRC, but you don't say who "we" are. I don't find the behavior you describe to be obvious or non-surprising. It's also something you can add to your own models if you happen to need or want the behavior as you describe it.

Marking wontfix; please open a discussion on django-dev if you are especially passionate about this.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.