首页 > 解决方案 > 如何修复 Django Duplicate key form 无效和保存?

问题描述

这是我的views.py文件,我收到了这条消息

DETAIL:  Key (member_id, match_id)=(4, 20) already exists.

但是看到 Valid 正在打印,所以很明显该is_valid()方法没有捕获这个重复的键。

def update_batter_form(request, match_id, batting_id):
    """Edit existing batter form view."""

    obj = Batting.objects.get(pk=batting_id)
    form = BattingForm(instance=obj)
    batting_list_bn = Batting.objects.order_by('batter_number') \
        .filter(match_id=match_id)
    match = Match.objects.get(pk=match_id)
    if request.method == 'POST':
        print("Printing POST")
        form = BattingForm(request.POST, instance=obj)
        print(obj)
        if form.is_valid():
            print("Valid")
            form.save()
            return redirect('/club/match/'+match_id+'/batter/'+batting_id)
        else:
            print(form.errors)
            return redirect('/club/match/' + match_id + '/batter/' + batting_id)

    context = {
        'form': form,
        'batting_list_bn': batting_list_bn,
        'match': match
    }

    return render(request, 'club/batter_update.html', context)

编辑击球模型和形式

class Batting(models.Model):
    """Batting performances within a match."""

    member = models.ForeignKey(Member, on_delete=models.CASCADE, default='')
    batter_number = models.IntegerField(
        blank=False, default=1, validators=[MaxValueValidator(11), MinValueValidator(1)]
    )
    fours = models.IntegerField(
        blank=True, null=True, default=0, validators=[MaxValueValidator(300), MinValueValidator(0)]
    )
    sixes = models.IntegerField(
        blank=True, null=True, default=0, validators=[MaxValueValidator(300), MinValueValidator(0)]
    )
    runs = models.IntegerField(
        blank=True, null=True, default=0, validators=[MaxValueValidator(1000), MinValueValidator(0)]
    )
    mode_of_dismissal = models.ForeignKey(Wicket, on_delete=models.CASCADE, default='')
    out_by = models.ForeignKey(
        OppositionNames, on_delete=models.CASCADE, default='', blank=True, null=True
    )
    match = models.ForeignKey(Match, on_delete=models.CASCADE, default='')

    class Meta:
        """Meta class."""

        unique_together = (("batter_number", "match",), ("member", "match",),)

    def __str__(self):
        return str('{0} {1} scored {2} runs'
                   .format(self.member, self.match.date, self.runs)
                   )

class BattingForm(forms.ModelForm):

    class Meta:
        model = Batting
        exclude = ('match',)

我是怎么发现这个问题的?

标签: pythondjangodjango-forms

解决方案


在您的表格中,您已设置exclude如下exclude = ('match',):当我们从表单中排除一个字段时,表单也会从它执行的验证中排除它,这仅在表单可用于创建此模型的实例的情况下是合乎逻辑的。

由于您需要该字段match作为验证的一部分,因此最好的方法是match在表单上简单地创建一个禁用和隐藏的字段。这将导致该字段以禁用和隐藏属性呈现。此外,即使用户篡改了该字段,它也会被忽略以支持该字段的初始值:

class BattingForm(forms.ModelForm):
    match = forms.ModelChoiceField(
        queryset=Match.objects.all(),
        widget=forms.HiddenInput(),
        disabled=True
    )
    
    class Meta:
        model = Batting
        fields = '__all__'

推荐阅读