Opened 16 years ago

Closed 16 years ago

Last modified 11 years ago

#8070 closed Uncategorized (fixed)

related objects passed to model init are not cached/accessible

Reported by: Gary Wilson Owned by: Gary Wilson
Component: Core (Other) Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Models:

from django.db import models

class Color(models.Model):
    name = models.CharField(max_length=10)

class Knight(models.Model):
    favorite = models.ForeignKey(Color)

Neither saved or unsaved related objects get cached:

# Unsaved object.
>>> k = Knight(favorite=Color())
>>> hasattr(k, '_favorite_cache')
False

# Saved object.
>>> k = Knight(favorite=Color.objects.create(name='blue'))
>>> hasattr(k, '_favorite_cache')
False

# But assignment with saved or unsaved objects does cache correctly.
>>> k = Knight()
>>> k.favorite = Color()
>>> hasattr(k, '_favorite_cache')
True
>>> k = Knight()
>>> k.favorite = Color.objects.create(name='blue')
>>> hasattr(k, '_favorite_cache')
True

Also, in the saved related object case above, we do an extra query to refetch the object by id.

There's also a problem when trying to access the field when it was passed an unsaved object in the init:

# Unsaved object.
>>> k = Knight(favorite=Color())
>>> k.favorite
Traceback (most recent call last):
...
DoesNotExist

# Saved object.
>>> k = Knight(favorite=Color.objects.create(name='blue'))
>>> k.favorite
<Color: blue>

The attached patch does both:

  • Caches saved or unsaved related object passed to the Model init.
  • Allows unsaved related objects to be accessed when they were passed to the Model init.

Attachments (2)

8070.patch (5.4 KB ) - added by Gary Wilson 16 years ago.
8070.2.patch (6.4 KB ) - added by Gary Wilson 16 years ago.
corrected a comment

Download all attachments as: .zip

Change History (7)

by Gary Wilson, 16 years ago

Attachment: 8070.patch added

by Gary Wilson, 16 years ago

Attachment: 8070.2.patch added

corrected a comment

comment:1 by Gary Wilson, 16 years ago

Owner: changed from nobody to Gary Wilson
Status: newassigned
Triage Stage: UnreviewedReady for checkin

Someone else care to review?

comment:2 by Gary Wilson, 16 years ago

Patch note: #6886 made the type checking happen on assignment, so we don't need to do the checking in the init anymore as long as you are setting using the attribute named by field.name.

comment:3 by Gary Wilson, 16 years ago

Resolution: fixed
Status: assignedclosed

(In [8185]) Fixed #8070 -- Cache related objects passed to Model init as keyword arguments. Also:

  • Model init no longer performs a database query to refetch the related objects it is passed.
  • Model init now caches unsaved related objects correctly, too. (Previously, accessing the field would raise DoesNotExist error for null=False fields.)
  • Added tests for assigning None to null=True ForeignKey fields (refs #6886).

comment:4 by Jacob, 13 years ago

milestone: 1.0

Milestone 1.0 deleted

comment:5 by Aymeric Augustin, 11 years ago

Easy pickings: unset
Severity: Normal
Type: Uncategorized
UI/UX: unset

Allows unsaved related objects to be accessed when they were passed to the Model init.

Django accepted this but the relation wasn't saved, see #10811. I'm going to remove the test for that bug-prone behavior.

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