Opened 7 years ago

Closed 7 years ago

#9144 closed (duplicate)

Bug with formsets validation in admin with models with m2m through other model

Reported by: msaelices Owned by: nobody
Component: contrib.admin Version: master
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Is very difficult to reproduce. In my case I only can reproduce in production server (apache). It depends on default db ordering if you don't put a ordering = ('id',) in Model.

These are my models:

# models.py
class Team(models.Model):
    name = models.CharField(_('name'), max_length=200,
                            help_text=_('Enter name'))
    members = models.ManyToManyField(User, verbose_name=_('members'),
                                    related_name=_('teams'), through='Membership')

class Membership(models.Model):
    user = models.ForeignKey(User)
    group = models.ForeignKey(Group)
    team = models.ForeignKey(Team)
    date_joined = models.DateField(default=date.today)

# admin.py
class MembershipInline(admin.TabularInline):
    model = Membership

class TeamAdmin(admin.ModelAdmin):
    inlines = [
        MembershipInline,
    ]
admin.site.register(Team, TeamAdmin)

Problem appears when you try to change admin form with to inlines Membership in a Team.

I attached a capture of error.

The validation error is this (i have to use pdb in contrib.admin.options.change_view, because validation error doesnt appears on web page):

formsets[0].errors
[{'id': [u'Membership with this None already exists.']}, {}, {}, {}, {}]

I think None is another simple labeling issue, but is not the case. The error appearing depends on DB configuration, because the ordering in formsets depends on exact DB engine and version. Further investigation show me that the problem was in uniqueness checkin for inline itself. In one configuration, the ID in form match with ID in database, but in production server not.

I get fixed the issue on my project changing Membership model like this:

class Membership(models.Model):
    user = models.ForeignKey(User)
    group = models.ForeignKey(Group)
    team = models.ForeignKey(Team)
    date_joined = models.DateField(default=date.today)

    class Meta:
        ordering = ('id',)

Now, the ordering is fixed to ID and works well in both configurations. I think a quick fix was define a default ordering if you don't define any order in inlines creation. It's a little hacky, of course.

Attachments (1)

error_with_inlines_in_admin.png (48.0 KB) - added by msaelices 7 years ago.

Download all attachments as: .zip

Change History (2)

Changed 7 years ago by msaelices

comment:1 Changed 7 years ago by kmtracey

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

Sounds like #9076.

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