#33209: ManyToManyField.add() doesn't respect a unique constraint in 
intermediate
table
-------------------------------------+-------------------------------------
               Reporter:  okapies    |          Owner:  nobody
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  3.1
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 I added the following `Company` and `Member` models, and `CompanyMember`
 as their intermediate table with a unique constraint including `role`
 field in addition to `through_fields`.

 {{{#!python
 from django.db import models

 class Company(models.Model):
     pass

 class Member(models.Model):
     companies = models.ManyToManyField(Company, through='CompanyMember',
 related_name='members')

 class CompanyMember:
     company = models.ForeignKey(Company, on_delete=models.CASCADE)
     member = models.ForeignKey(Member, on_delete=models.CASCADE)
     role = models.SmallIntegerField()

     class Meta:
         constraints = [
             models.UniqueConstraint(fields=['company', 'member', 'role'],
 name='company_member_role'),
         ]
 }}}

 In this situation, `company.members.add()` fails to add existing member
 with different role.

 {{{#!python
 company = Company.objects.create()
 member = Member.objects.create()

 company.members.add(member, through_defaults={'role': 1})
 assert Company.objects.all().count() == 1

 company.members.add(member, through_defaults={'role': 2})
 assert Company.objects.all().count() == 2  # fails
 }}}

 We need to workaround by adding the relation to the intermediate table
 directly.

 {{{#!python
 company.members.through.objects.create(
     company.members.through(company=company, member=member, role=2)
 )
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33209>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/050.f6a5373de2aa39d4e99e1d890d36ccf5%40djangoproject.com.

Reply via email to