This is my views.py
file and Im getting this message
DETAIL: Key (member_id, match_id)=(4, 20) already exists.
However is see that Valid is printing so its obvious the is_valid()
method doesnt catch this duplicate key.
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)
EDIT Batting model and form
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',)
How is it I catch this issue?
Advertisement
Answer
In your form you have set exclude
as follows: exclude = ('match',)
. When we exclude a field from the form, the form also excludes it from the validation it performs, which is only logical in the case that the form may be used to create this model’s instances.
Since you need the field match
to be part of the validation the best method is to simply make match
a disabled and hidden field on the form. This will cause the field to be rendered with the disabled and hidden attributes. Also even if the user tampers with the field it will be ignored in favor of the initial value of the field:
class BattingForm(forms.ModelForm): match = forms.ModelChoiceField( queryset=Match.objects.all(), widget=forms.HiddenInput(), disabled=True ) class Meta: model = Batting fields = '__all__'