【问题标题】:Only allow filling one field or the other in Django model and admin只允许在 Django 模型和管理员中填写一个或另一个字段
【发布时间】:2020-02-13 19:28:56
【问题描述】:

我有一个用于 Group 的简单 Django 模型,其中包含 Contacts 列表。每个组必须选择任一主要联系人 ForeignKey所有联系人 BooleanField,但不能同时选择两者,也不能没有。

class Group(models.Model):
    contacts = models.ManyToManyField(Contact)
    contact_primary = models.ForeignKey(Contact, related_name="contact_primary", null=True)
    all_contacts = models.BooleanField(null=True)

我如何确保:

  1. 除非设置了contact_primaryall_contacts(但不能同时设置),否则无法保存模型。我想那是通过实现Group.save() 方法?还是应该是Group.clean() 方法??

  2. 在 Django Admin 中,要么在选择一个字段时禁用另一个字段,要么至少提供一个有意义的错误消息,如果两者都设置或没有设置并且管理员尝试保存它?

谢谢!

【问题讨论】:

    标签: django django-admin


    【解决方案1】:

    最简单的方法是覆盖模型的save() 方法:

    class Group(models.Model):
        contacts = models.ManyToManyField(Contact)
        contact_primary = models.ForeignKey(Contact, related_name="contact_primary", blank=True, null=True)
        all_contacts = models.BooleanField(blank=True, null=True)
    
        def save(self, *args, **kwargs):
            if self.contact_primary is not None and self.all_contacts is not None:
                raise Exception("some error message here")  
            if self.contact_primary is None and self.all_contacts is None:
                raise Exception("some other error message here")  
    
            return super().save()
    

    请注意,我在您的模型字段中添加了 blank=True。如果您想通过管理员或表单插入空列,这是必要的。

    更新

    如果您想提升 ValidationError,您必须从模型的 clean() 方法提升它。否则,您将给客户端一个 500 错误,而不是错误消息。

    【讨论】:

    • 实际上我现在做了同样的事情,但在clean() 方法和提高ValidationError() 这似乎也适用于管理界面。请随时更新您的答案,我会接受。
    • @KeepLearning 唯一的缺点是,如果您最终以某种方式将模型保存在管理员/表单之外,那么clean 将不适用。跨度>
    • 啊,好点子。也许在 clean() 和 save() 中都这样做?或者再次从safe() 拨打clean() 以防万一?
    • @KeepLearning 为什么要从clean 调用它?您可以从您的 save 方法中提出 ValidationError。使用save 时唯一会被忽略的情况是,如果您运行bulk_insert,在这种情况下,您需要在clean 中捕获它。
    • 当我在 Admin 中从 save() 引发 ValidationError 时,我会得到一个带有 Backtrace 的调试页面。当我从clean() 提出它时,我会收到一个漂亮的红色消息框。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 2018-03-12
    • 1970-01-01
    相关资源
    最近更新 更多