Django 模型 - 至少多对多之一
Posted
技术标签:
【中文标题】Django 模型 - 至少多对多之一【英文标题】:Django models - at least one in many to many 【发布时间】:2012-03-24 12:46:41 【问题描述】:如何确保至少设置了一个多对多关系?
例如:如果我有一个 listing
模型,它的 image 字段与 images
具有多对多关系。如何确保至少设置了一张图片
额外问题:如果最小值不是一个怎么办?最大值呢?
【问题讨论】:
确保是什么意思?除非有所需数量的图像,否则阻止保存? 是的,确保至少存在一个(如果可能的话,还有一个最大值) 您需要它来过滤列表或其他地方吗?过滤时,您可以使用注释并按结果编号过滤。 根据 [this answer][1] 这是不可能的。 [1]:***.com/questions/10480322/… 【参考方案1】:您可以实现一个函数来检查Listing
实例是否至少有一个图像实例,并将该函数连接到Listing
模型的pre_save signal
会是这样的,(假设您使用的是 django 1.3)
from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import Listing
...
@receiver(pre_save, sender=Listing)
def check_image_requirement(sender, instance, **kwargs):
if instance.images.count() == 0:
raise your_own_exception("Listing is required to have at least one image")
您需要在哪里实现 your_own_exception
以下补充是对 PO 进一步问题的回应
实现Listing.clean()
是实现相同验证规则的另一种方法。事实上,这是语义上正确的方法,因为Model.clean()
用于自定义模型验证。但是采用这种方法会不太方便 - 要触发clean()
,您必须手动调用full_clean()
(如果您不使用模型表单),或者手动调用is_valid()
(使用模型表单时),对在调用列表实例的save()
之前。 Reference
另一方面,使用pre_save
信号方法,您可以确定无论何时您在实例上调用save()
,验证规则始终应用于Listing
实例。
选择一个而不是另一个不是对或错,而只是一个设计决定。这两种方法都可以实现您的需求,并将业务/领域逻辑(即您的验证规则)保留在模型层中。
【讨论】:
我对 phython/django 还是很陌生。 pre_save 是否在字段验证之前运行(例如在确保整数字段为整数或外键约束匹配之前)?为什么 pre_save 而不是 clean()?使用 clean() 时,我是覆盖字段验证还是扩展它?感谢您的帮助! @RS7 - 不用担心。每个人都在这里学习,包括我自己。为了回答您的进一步问题,我已添加到我的答案中。 谢谢,信息量很大——最后一个问题:如果listing
模型有许多由image
模型表示的图像怎么办。如果我正确理解了这些文档,而不是多字段 images
,我会创建一个单独的模型,是吗?所以要检查是否满足最低要求,我会以同样的方式访问它吗? self.image.count()
如果我在 clean()
做?
@RS7 - 视情况而定。如果您只需要一个简单的多对多关系(即无需记录有关关联的其他属性),那么您只需要一个ManyToManyField
。假设您决定在关联上设置到期日期(即附加属性),那么您将需要一个ManyToManyField
,以及一个表示关联/关系的附加模型。我强烈推荐你去this section。第一段基本上重申了我刚才解释的内容。
@RS7 - 是的,self.image.count()
仍然适用于 clean()
以上是关于Django 模型 - 至少多对多之一的主要内容,如果未能解决你的问题,请参考以下文章