编程语言
首页 > 编程语言> > python-在Django管理中验证ManyToManyField项的数量(带有中间模型)

python-在Django管理中验证ManyToManyField项的数量(带有中间模型)

作者:互联网

我有一些看起来像这样的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()

我使用直通机制,因为链接表上有多余的列.

我的管理类看起来像这样(请注意,我正在使用嵌入式管理来添加播放器):

class TeamPlayerInline(admin.TabularInline):
    model = TeamPlayer
    max_num = 11
    extra = 11

class TeamAdmin(admin.ModelAdmin):
    inlines = [TeamPlayerInline]

admin.site.register(Team, TeamAdmin)

问题:我的问题是,在我的管理员中,我想验证一个团队中是否有11名球员.少了将导致错误.我怎样才能做到这一点?

这些是我尝试过的事情以及它们不起作用的原因:

>以团队模型的清洁方法验证球员人数.这是行不通的,因为尚未保存播放器,因此对于一个新对象,播放器始终为零.
>验证TeamAdmin使用的ModelForm的clean_players方法中的数字.此方法永远不会被调用.确实会调用其他非ManyToMany字段的类似方法.
>用上述ModelForm的clean方法验证编号.该方法被调用,但是self.cleaned_data词典中没有“玩家”条目.

有什么想法可以实现这种验证吗?我远不是Django专家,所以不要以为我已经做了所有显而易见的事情.

解决方法:

您需要在TeamPlayerInline上设置表单集.并重写该表单集中的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]

标签:validation,django-forms,django-admin,python,django
来源: https://codeday.me/bug/20191030/1967572.html