簡體   English   中英

Django model 在不應該保存的時候保存

[英]Django model saves when it shouldn't

我正在嘗試在我的 Django 模型上設置自定義驗證規則。 我有以下代碼:
Entity.py

from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.db import models

class Entity(models.Model):
    TYPE_CHOICES = [
        ('asset', 'asset'),
        ('company', 'company')
    ]
    entity_type = models.CharField(max_length=25, choices=TYPE_CHOICES)
    ...

class Asset(Entity):
    ...

class Company(Entity):
    ...

Security.py

from django.core.exceptions import ObjectDoesNotExist, PermissionDenied, ValidationError
from django.db import models
from .Entity import Entity

class Security(models.Model):
    ...
    entities = models.ManyToManyField(Entity)

    def clean(self, *args, **kwargs) -> None:
        try:
            # Check that object has already been saved
            Security.objects.get(name=self.name)
            print("All entities:", self.entities.all())
            if len([e for e in self.entities.all() if e.entity_type == 'company']) > 1:
                raise ValidationError("A security can only be related to one company")
        except ObjectDoesNotExist:
            pass
        return super(Security, self).clean(*args, **kwargs)

    def save(self, *args, **kwargs):
        try:
            self.full_clean()
            return super(Security, self).save(*args, **kwargs)
        except ValidationError:
            raise ValidationError("A security can only be related to one company")

class Bond(Security):
    ...

class Equity(Security):
    ...

我正在嘗試做的是防止Security在其現場entities持有超過 1 家公司時被保存。 entities字段是與Entity的 ManyToMany 關系,因為它可以包含多個Asset對象但只能包含一個Company
這是我的測試文件

class EntityTestCase(TestCase):
    def test_multiple_companies_fail(self):
        b = Bond.objects.get(name='Bond 1')
        c1 = Company.objects.get(name='Company 1')
        c2 = Company.objects.get(name='Company 2')
        a1 = Asset.objects.get(name='Asset 1')
        a2 = Asset.objects.get(name='Asset 2')
        b.entities.add(c1)
        b.save()
        b.entities.add(a1)
        b.entities.add(a2)
        b.save()
        try:
            b.entities.add(c2)
            b.save()
            self.fail("Should not be able to link more than one company to a security")
        except ValidationError:
            b = Bond.objects.get(name='Bond 1')
            # Exception gets caught, but following assert fails with `AssertionError: 2 != 1`.
            self.assertEquals(len([e for e in b.entities.all() if e.entity_type == 'company']), 1)

我嘗試使用 Django shell 並且我有相同的行為。 即使我在save方法中引發異常,記錄也會被保存,這似乎不合邏輯。
有人會知道為什么嗎? 我做錯了什么,如何避免根據條件進行儲蓄?

感謝威廉的評論,我實際上找到了解決方案。
m2m 關系不由save()管理, add(...)可以。 那么訣竅是這個function:

@receiver(m2m_changed, sender=Security.entities.through)
def check_unique_company(sender, instance, **kwargs):
    if len([e for e in instance.entities.all() if e.entity_type == 'company']) > 1:
            raise ValidationError("A security can only be related to one company")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM