views:

677

answers:

2

I have a model, OrderedList, which is intended to be a listing of content objects ordered by the user. The OrderedList has several attributes, including a site which it belongs to.

The content objects are attached to it via an OrderedListRow class, which is brought into OrderedList's admin via an inline formset in the admin.

class OrderedList(GenericList):

    objects = models.Manager()
    published = GenericListManager()

class OrderedListRow(models.Model):

    list = models.ForeignKey(OrderedList)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveSmallIntegerField()
    content_object = generic.GenericForeignKey("content_type", "object_id")
    order = models.IntegerField('order', blank = True, null = True)

(OrderedList inherits the site field from the larger GenericList abstract).

Here's my problem; when the user saves the admin form, I want to verify that each content object mapped to by each OrderedListRow belongs to the same site that the OrderedList does (the list can only belong to 1 site; the content objects can belong to multiple).

I can override OrderedList's admin form's clean(), but it doesn't include the inline formset which contains the OrderedListRows, so it can't reach that data. I can override the OrderedListRows' inline formset's clean, but it can't reach the list. I need some way within the context of form validation to reach both the OrderedList's form data and the formset's form data so I can check all the sites of the OrderedListRow's content objects against the site of the OrderedList, and throw a validation error if there's a problem. So far I haven't found a function that the cleaned data for both OrderedRow and the OrderedListRows are contained in.

+3  A: 

In the inline formset, self.instance should refer to the parent object, ie the OrderedList.

Daniel Roseman
+1  A: 

I am dealing with the same issue. And unfortunately I don't think the answer above covers things entirely.

If there are changes in both the inline formset and the admin form, accessing self.instance will not give accurate data, since you will base the validation on the database and then save the formset which overwrites that data you just used to validate things. Basically this makes your validation one save behind.

I suppose the real question here is which gets saved first. After digging int he source code, it seems like the admin site saved the form first. This means that, logically, doing validation on the formset and from there accessing the 'parent' instance should get consistent values.

Silvia Botros
In the end, I created a formset for the OrderedListRow inline and did an override of its clean() function. In it, I was able to pull the site ID by sayingsite_id = self.data.get('site')With 'site' being the name of the site field that the parent OrderedList uses. Essentially, I'm accessing it directly from the form data. Once I had the site ID that was submitted, I could iterate through all the forms of the OrderedListRow formset, and compare their content's site to the OrderedList's site.
KRH