Django:如何覆盖unique_together错误消息?

fykwrbwg  于 2023-05-30  发布在  Go
关注(0)|答案(7)|浏览(188)

在模型的 meta类中,我定义了unique_together。我有一个基于这个模型的ModelForm。当我在这个ModelForm上调用is_valid时,如果unique_together验证失败,将自动引发错误。那就好
现在我的问题是我对默认的unique_together错误消息不满意。我想覆盖它。我该怎么做?对于一个与字段相关的错误,我可以通过在字段参数上设置error_messages来轻松实现。但是unique_together是一个非字段错误。如何覆盖非字段错误消息?

6gpjuf90

6gpjuf901#

你可以从Django 1.7开始做这个

from django.forms import ModelForm
from django.core.exceptions import NON_FIELD_ERRORS

class ArticleForm(ModelForm):
    class Meta:
        error_messages = {
            NON_FIELD_ERRORS: {
                'unique_together': "%(model_name)s's %(field_labels)s are not unique.",
            }
        }
mec1mxoz

mec1mxoz2#

更新2016/10/20:请参阅下面jifeng-yin对Django >= 1. 7的更好的回答

覆盖这些错误消息的最好方法可能是覆盖模型上的unique_error_message方法。Django在验证过程中遇到唯一性问题时调用此方法来获取错误消息。
你可以只处理你想要的特定情况,让Django像往常一样处理所有其他情况:

def unique_error_message(self, model_class, unique_check):
    if model_class == type(self) and unique_check == ('field1', 'field2'):
        return 'My custom error message'
    else:
        return super(Project, self).unique_error_message(model_class, unique_check)
5w9g7ksd

5w9g7ksd3#

对于DRF序列化程序,可以使用以下命令

from rest_framework import serializers

class SomeSerializer(serializers.ModelSerializer):

    class Meta:
        model = Some
        validators = [
            serializers.UniqueTogetherValidator(
                queryset=model.objects.all(),
                fields=('field1', 'field2'),
                message="Some custom message."
            )
        ]

这是原始的source

5lwkijsr

5lwkijsr4#

快速检查后,似乎unique_together验证错误被硬编码在django.db.models.Model.unique_error_message中:

def unique_error_message(self, model_class, unique_check):
    opts = model_class._meta
    model_name = capfirst(opts.verbose_name)

    # A unique field
    if len(unique_check) == 1:
        field_name = unique_check[0]
        field_label = capfirst(opts.get_field(field_name).verbose_name)
        # Insert the error into the error dict, very sneaky
        return _(u"%(model_name)s with this %(field_label)s already exists.") %  {
            'model_name': unicode(model_name),
            'field_label': unicode(field_label)
        }
    # unique_together
    else:
        field_labels = map(lambda f: capfirst(opts.get_field(f).verbose_name), unique_check)
        field_labels = get_text_list(field_labels, _('and'))
        return _(u"%(model_name)s with this %(field_label)s already exists.") %  {
            'model_name': unicode(model_name),
            'field_label': unicode(field_labels)
        }

因此,也许您应该尝试从您的模型中重写此方法,以插入您自己的消息!?
然而,我没有尝试过,这似乎是一个相当残酷的解决方案!但如果你没有更好的选择你可以试试...

lrl1mhuk

lrl1mhuk5#

**注意:**自从这个答案以来,Django发生了很多变化。所以最好检查一下其他答案。。

如果sebpiq是真的(因为我不检查源代码),那么有一个可能的解决方案,你可以做,但它是困难的方式…
您可以在表单中定义验证规则,如下所述
你可以看到多个字段验证的例子,所以通过使用这个方法,你可以在标准的django unique check执行之前定义一个unique together check。
或者最糟糕的一个,您可以在尝试保存对象之前在视图中进行验证。

esyap4oy

esyap4oy6#

更好的解决方案是使用validate_unique引发ValidationError来替换错误消息:

class ModelName(models.Model):
    ...

    class Meta:
        unique_together = ['field_1', 'field_2']
    
    def validate_unique(self, *args, **kwargs):
        super().validate_unique(*args, **kwargs)

        if ModelName.objects.filter(field_1=self.field_1, field_2=self.field_2).exists():
            raise ValidationError(
                ...
            )

正在验证对象
正在验证对象
验证模型涉及四个步骤:
1.验证模型字段- Model.clean_fields()
1.将模型作为一个整体进行验证- Model.clean()
1.验证字段唯一性- Model.validate_unique()
1.验证约束- Model.validate_constraints()
所有四个步骤都是在调用模型的full_clean()方法时执行的。
当您使用ModelForm时,对is_valid()的调用将对表单中包含的所有字段执行这些验证步骤。有关详细信息,请参阅ModelForm文档。如果您打算自己处理验证错误,或者您已经从ModelForm中排除了需要验证的字段,那么您应该只需要调用模型的full_clean()方法。

6ljaweal

6ljaweal7#

你可以看看在你的模型中覆盖django/db/models/base.py:Model._perform_unique_checks()。
在这种方法中,您可以获得“原始”错误:

errors = super(MyModel, self)._perform_unique_checks(unique_checks)

--然后向上修改并返回。

相关问题