Why are some records not added to the m2m table?

Why aren't some records being added to the m2m table? If the table already contains a record with a specific topic and system (service can be any), then the next addition of a record with a similar topic and system does not occur.

with transaction.atomic():
    chat_topic = ChatTopics.objects.get(ct_id=chat_topic_id)
    system = Systems.objects.get(sys_id=system_id)
    service = ServiceCatalog.objects.get(sc_id=service_id)

    chat_topic.ct_systems.add(system, through_defaults={"ctm_service": service})

I don't get any errors when run this code.

Expected result: Expected result

Actual result: Actual result

Models:

class Systems(BaseModel):
    sys_id = models.AutoField(primary_key=True)
    sys_name = models.CharField(max_length=256, unique=True, null=False)

    def __str__(self):
        return self.sys_name

    class Meta:
        verbose_name = "Systems"
        verbose_name_plural = "Systems"
        ordering = ['sys_id']
class ServiceCatalog(BaseModel):
    sc_id = models.AutoField(primary_key=True)
    sc_service = models.CharField(max_length=250, unique=True, null=False)

    def __str__(self):
        return self.sc_service

    class Meta:
        verbose_name = "Service catalog"
        verbose_name_plural = "Service catalog"
        ordering = ['sc_id']
class ChatTopics(BaseModel):
    ct_id = models.AutoField(primary_key=True)
    ct_systems = models.ManyToManyField(Systems, blank=True, through="chattopics_m2m")
    ct_chat_id = models.CharField(max_length=20, null=False, blank=False)
    ct_chat_name = models.CharField(max_length=50, null=False, blank=False)
    ct_topic_id = models.CharField(max_length=10, null=True, default=None, blank=True)
    ct_topic_name = models.CharField(max_length=50, null=True, default=None, blank=True)
    
    def __str__(self):
        return f'{self.ct_chat_name} ({self.ct_topic_name})'
    
    class Meta:
        verbose_name = 'Topics'
        verbose_name_plural = 'Topics'
        
        constraints = [
            models.UniqueConstraint(fields=('ct_chat_id', 'ct_topic_id'), nulls_distinct=False, name='chattopics_ct_chat_id_ct_topic_id_unique')
        ]
class ChatTopics_m2m(BaseModel):
    ctm_id = models.AutoField(primary_key=True)
    ctm_chat_topic = models.ForeignKey(ChatTopics, on_delete=models.CASCADE, null=False)
    ctm_system = models.ForeignKey(Systems, on_delete=models.CASCADE, null=False)
    ctm_service = models.ForeignKey(ServiceCatalog, on_delete=models.CASCADE, null=True, blank=True)
    
    class Meta:
        ordering = ['ctm_system']

This is the expected behavior of .add():

Adding a second time is OK, it will not duplicate the relation:

>>> a2.publications.add(p3)

What you probably want to do, which will also boost efficiency is using:

with transaction.atomic():
    ChatTopics_m2m.objects.create(
        system_id=system_id,
        ctm_chat_topic_id=chat_topic_id,
        ctm_service_id=service
    )

and then the atomic transaction can probably get removed, since we do this with one query.

Вернуться на верх