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

时间:2015-03-03 19:45:11

标签: python django web

我有一个带有ManyToManyField的Django模型。我需要要求用户在此字段中选择至少一个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定义或使用save()模型的覆盖Person方法解决此问题。

是否可以阻止创建Person而不选择至少一个Skill,并设置ManyToManyField个选项?或者我需要创建自定义逻辑来处理这种情况?感谢。

我使用Django 1.7Python 3.4


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

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

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

admin.site.register(Person, PersonAdmin)

1 个答案:

答案 0 :(得分:8)

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

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

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

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

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

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