我有一些看起来像这样的Django模型(这不是我的确切代码,但是具有相同结构的更简单的例子):
class Player(models.Model):
# Some fields here.
pass
class Team(models.Model):
players = models.ManyToManyField(Player, through='TeamPlayer')
class TeamPlayer(models.Model):
team = models.ForeignKey(Team)
player = models.ForeignKey(Player)
some_other_field = models.BooleanField()
我正在使用through
机制,因为我的链接表上有额外的列。
我的管理类看起来像这样(注意我使用内联管理员添加玩家):
class TeamPlayerInline(admin.TabularInline):
model = TeamPlayer
max_num = 11
extra = 11
class TeamAdmin(admin.ModelAdmin):
inlines = [TeamPlayerInline]
admin.site.register(Team, TeamAdmin)
问题:我的问题是,在我的管理员中,我想确认一个团队只有11名玩家。任何更少的都应该导致错误。我怎么能这样做?
这些是我尝试过的东西以及它们不起作用的原因:
验证clean
模型的Team
方法中的玩家数量。这不起作用,因为玩家还没有被保存,所以对于一个新对象总是没有玩家。
验证clean_players
使用的ModelForm
TeamAdmin
方法中的数字。永远不会调用此方法。其他非ManyToMany字段的类似方法也会被调用。
验证上述clean
的{{1}}方法中的数字。调用此方法,但ModelForm
字典没有self.cleaned_data
的条目。
我有什么想法可以实现这种类型的验证?我不是一个Django专家,所以不要以为我必须完成一切应该是显而易见的事情。
答案 0 :(得分:4)
您需要在TeamPlayerInline上设置formset
。并覆盖该表单集中的clean方法。例如:
from django.forms.models import BaseInlineFormSet
class TeamPlayerFormset(BaseInlineFormSet):
def clean(self):
"""Check that exactly 11 players are entered."""
super(TeamPlayerFormset, self).clean()
if any(self.errors):
return
count = 0
for cleaned_data in self.cleaned_data:
if cleaned_data and not cleaned_data.get('DELETE', False):
count += 1
if count != 11:
raise forms.ValidationError('You must enter 11 team players.')
class TeamPlayerInline(admin.TabularInline):
model = TeamPlayer
max_num = 11
extra = 11
formset = TeamPlayerFormset
class TeamAdmin(admin.ModelAdmin):
inlines = [TeamPlayerInline]