Opened 12 years ago

Closed 11 years ago

#7203 closed (fixed)

Admin error if an edit_inline=True object has a ForeignKey to some other object which has a unique_together specification

Reported by: Scott Moonen <smoonen@…> Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


Here's a reduced example:

class Organization(models.Model) :

class User(models.Model) :
  organization = models.ForeignKey(Organization)
  username = models.SlugField(max_length = 30)
  class Meta :
    unique_together = ('organization', 'username')

class OrganizationService :
  organization = models.ForeignKey(Organization)
  service = models.SlugField(max_length = 30)
  class Meta :
    unique_together = ('organization', 'service')

class ServiceUser :
  user = models.ForeignKey(User, edit_inline = models.TABULAR)
  organization_service = models.ForeignKey(OrganizationService)
  class Meta :
    unique_together = ('organization_service', 'user')

So, ServiceUser is related to User and is edited inline there. ServiceUser is also related to OrganizationService. So, when we go to edit User in the admin interface, it builds the following get_follow list:

{'username': True, 'myapp:serviceuser': {'organization_service': True, 'id': True, 'user': False}, 'organization': True, 'id': True}

The problem is that the inner dictionary has 'organization_service' set to True. This results in our trying to extend the User ChangeManipulator with the unique_together validator for OrganizationService. That fails:

AttributeError at /myapp/user/6/
'ChangeManipulator' object has no attribute 'isUniqueorganization_service_user'

The 'organization_service' follow indicator is set to True because RelatedObject.get_follow is smart enough to force the edit_inline ForeignKey to have False for follow, however it doesn't set follow for other ForeignKey relations in the edit_inline object to False:

over[] = False

I'm not sure what the right way is to fix this. I almost think that Options.get_follow needs a new parameter to indicate whether all ForeignKey relationships (not only the one that has edit_inline set) should be forced to False. Or, alternatively, we could create an alternative function to Options.get_follow with this behavior. We can then force this behavior in the call from RelatedObject.get_follow, but keep the existing behavior in the call from AutomaticManipulator. I'm not sure if that would create broader problems, though.

This bug is a little more problematic than average, since I can't find an easy workaround apart from removing the edit_inline = True specification.

Change History (2)

comment:1 Changed 12 years ago by Scott Moonen <smoonen@…>

Alternative workaround is to comment out the unique_together specification (and rely on DB validation rather than Django validation).

comment:2 Changed 11 years ago by smoonen@…

Resolution: fixed
Status: newclosed

As expected, this works fine now that the newforms-admin branch has landed. From what I read on the mailing lists, I understand that form-level validation of constraints like the unique_together has yet to happen in NFA; for now things will be validated only at the database level. But that's not of great concern to me; admin object editing is now possible without having to comment out the constraint altogether.

Closing this ticket as resolved.

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