Django 1.7:如何使 ManyToManyField 成为必需的?

Django 1.7: how to make ManyToManyField required?

我有一个包含 ManyToManyField 的 Django 模型。我需要要求用户在此字段中 select 至少一个 M2M 值。

我尝试将 blank=False 设置为 M2M 字段,但没有帮助。

class Skill(models.Model):
    name = models.CharField(max_length=200)

class PersonSkills(models.Model):
    person = models.ForeignKey('Person')
    skill = models.ForeignKey('Skill')

class Person(models.Model):
    name = models.CharField(max_length=200)
    skills = models.ManyToManyField('Skill', through='PersonSkills')

p = Person(name='Bob')
p.save()
# success, but I expect that this should throw ValidationError, because I didn't select at least one Skill for this person

我可以使用自定义 Form 定义或 Person 模型的覆盖 save() 方法来解决这种情况。

是否可以在没有至少一个 Skill selected 和设置 ManyToManyField 选项的情况下阻止创建 Person?或者我需要创建自定义逻辑来处理这种情况?谢谢。

我用Django 1.7Python 3.4


更新1.如何创建ModelForm来控制M2M?因为在 cleaned_data 中,我只有为 Person 表单传递的字段,而没有作为 M2M 字段传递的数据。我尝试在管理站点中创建对象并控制 Skills selected。我通过 inline 输入 Skill

# admin.py
class PersonSkillsInline(admin.TabularInline):
    model = Person.skills.through
    extra = 2

class PersonAdmin(admin.ModelAdmin):
    inlines = [PersonSkillsInline]

admin.site.register(Person, PersonAdmin)

在数据库级别...不,那是不可能的。对此的任何强制执行都必须来自您的应用程序逻辑。

原因是每一个m2m关系在m2m关系的两边都有一个外键的记录。 SQL 不能强制存在关系的引用端,只能强制存在关系的引用端。

此外,您也不能在模型中强制执行它,因为必须先创建并保存 Person,然后才能分配任何多对多关系。

您唯一的选择是在表单或视图中强制执行它。

InlineModelAdmin 中,这可以通过指定 min_num (1.7+) 轻松完成:

class PersonSkillsInline(admin.TabularInline):
    model = Person.skills.through
    min_num = 1
    extra = 2