Opened 18 years ago

Closed 18 years ago

Last modified 18 years ago

#2297 closed defect (invalid)

ForeignKey and *_set accessor method broke

Reported by: matthewharrison@… Owned by: Adrian Holovaty
Component: Database layer (models, ORM) Version:
Severity: normal Keywords: ForeignKey _set
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I revved to v3278 and my app broke. In my view I adjust some fields of the model.

My model looks something like this

class Foo(models.Model):
    name = models.CharField(maxlength=30)

class Bar(model.Model):
    foo = models.ForeignKey(Foo)
    data = models.CharField(maxlength=30)

later on I iterate over my bars and try and get my foos from them. ie

for foo in bar.foo_set.all():
    #do something with foo

I now get an attribute error when trying to do this:

AttributeError at /fooapp/
'Bar' object has no attribute 'foo_set'
Request Method: 	GET
Request URL: 	http://localhost:8000/fooapp/
Exception Type: 	AttributeError
Exception Value: 	'Bar' object has no attribute 'foo_set' 

Just wondering if there was a change that broke then _set functionality recently

I apologize for how vague this is. I have another model that has a foreign key and code similar to the above still works with that. I've briefly diffed the sources didn't chance on anything that looked to cause this change....

Change History (5)

comment:1 by anonymous, 18 years ago

Resolution: invalid
Status: newclosed

OK, this is going to sound confusing, because you are overloading the "foo" and "bar" words way more than can be healthy, but here goes...

foo_set refers to the reverse side of the relation from Foo back to Bar. If you want to refer to the relation in a Bar object, just use bar.foo, it's a simple attribute. If you want to iterate over all the things that refer to a particular Foo -- call him fred -- then

for b in fred.foo_set.all():
   ...

All documented here: http://www.djangoproject.com/documentation/db_api/#backward

comment:2 by Malcolm Tredinnick, 18 years ago

Stupid not logged in status. That was me in the last comment, for the record.

comment:3 by James Bennett, 18 years ago

And just to clarify it conceptually, this goes back to foreign keys being a one-to-many relationship. To take an example from the official tutorial, you have Polls and Choices. A Choice only ever belongs to one Poll, so you access that as choice.poll. But a Poll has many Choices, so you access them via poll.choice_set.

comment:4 by matt, 18 years ago

Resolution: invalid
Status: closedreopened

I'm sorry, I messed up my foos and bars. Let me try again. (Not using
foo nor bar). Yes, that example was wrong, but here's a simpler version of the code that is failing. (Yes I've read the tutorial)

I have a Component object, a Version object and a Data object (that
holds additional data about the version object). They look like
this::

class Component(models.Model):
   name = models.CharField(maxlenth=30)
   ...

class Version(models.Model):
   component = models.ForeignKey(Component)
   version = models.CharField(maxlength=30)
   ...

class Data(models.Model):
   meta_data = models.CharField(maxlength=30)
   version = models.ForeignKey(Version)

Now given a component, I want to get all the version instances and
alll the data associated with it. So I do something like this:

for version in component_instance.version_set.all():
   for data in version.data_set.all():
       #adjust meta_data on data

Here's the error

AttributeError at /myapp/
'Version' object has no attribute 'data_set'
Request Method:         GET
Request URL:    http://localhost:8000/myapp/
Exception Type:         AttributeError
Exception Value:        'Version' object has no attribute 'data_set'
Exception Location:     /home/matt/.views.py in _add_metadata, line 293

So this is the weird thing. Accessing _set.all() works on the
component_instance, but fails on the next line... Is _set.all() no
longer returning instances? Again, this worked before updating svn.

comment:5 by matt, 18 years ago

Resolution: invalid
Status: reopenedclosed

I'm closing this since I appear to be a complete idiot. I guess I had a typo somewhere, which I somehow fixed and somehow now it's working...

Sorry for barking up the wrong tree...

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