具有独特字段的 Django UpdateView

Django UpdateView with unique fields

有没有办法在更新视图中更新唯一字段? 我有一个具有 nameage 字段的模型,但是当我尝试更新 age 甚至不更改 name 的值时,它 returns数据库中已存在该名称的错误

models.py

class MyModel(models.Model)
  name = models.CharField(max_length=200, unique=True)
  age = models.IntegerField()

views.py

class MyModelUpdateView(UpdateView):
    def get(self):
        self.object = self.get_object()
        my_model = self.object

        form = MyModelForm(instance=my_model)

        return self.render_to_response(
            self.get_context_data(pk=my_model.pk, form=form)
        )

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()

        my_model = self.object

        form = MyModelForm(data=request.POST, instance=my_model)

        if form.is_valid():
            form.save()

            return some_url

        return self.render_to_response(
            self.get_context_data(pk=my_model.pk, form=form)
        )

forms.py

class MyModelForm(forms.ModelForm):

    class Meta:
        model = MyModel
        fields = (
            'name',
            'age',
        )

    def clean(self):
        cleaned_data = super().clean()

        if MyModel.objects.filter(
            active=True, name=cleaned_data.get('name')
        ).exists():
            raise forms.ValidationError('MyModel already exists.')

        return cleaned_data

我在这里错过了什么?谢谢。

由于您更新了一个模型,并且您没有更改 name,当然已经存在具有该名称的记录:那个 特定记录。因此,您应该将检查代码更改为:

class MyModelForm(forms.ModelForm):

    def clean(self, *args, **kwargs):
        cleaned_data = super().clean(*args, **kwargs)
        if MyModel.objects.<b>exclude(pk=self.instance.pk)</b>.filter(
            active=True, name=cleaned_data.get('name')
        ).exists():
            raise forms.ValidationError('MyModel already exists.')
        return cleaned_data

    class Meta:
        model = MyModel
        fields = ('name', 'age')

不要改变UpdateView的样板逻辑,您可以通过以下方式轻松实现:

class MyModelUpdateView(UpdateView):
    <b>form_class = MyModelForm</b>
    success_url = <i>'some url'</i>

也就是说,如果您已经字段设置为unique=True,那么就没有必要自己实施检查了。在这里,您似乎已经 拥有 一个 unique=True 约束:

class MyModel(models.Model)
  name = models.CharField(max_length=200, <b>unique=True</b>)
  age = models.IntegerField()

在那种情况下,您可以简单地让 ModelForm 完成工作,那么您的表单如下所示:

class MyModelForm(forms.ModelForm):

    class Meta:
        model = MyModel
        fields = ('name', 'age')

只有当您想要更复杂的唯一性(例如 active=True?),并且您不能(轻松地)表示它时,您才应该进行自己的验证。