2014-01-25 70 views
1

我是新的数据库和Django。我对trigers知之甚少。Django manytomany限制

我创建了一个关于学术专家系统的数据库,这里所有的论文都应该有4个主题。如果选择的主题多于其他主题,则应该将警告标记为“主题太多”。一个话题可能被许多论文所拥有。所以这是一种多对多的关系。但我不知道该怎么上限限制为4

我的课是这样的:

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

class Paper(models.Model): 
    expert = models.ForeignKey(Expert) 
    topic = models.ManyToManyField('Topic', related_name='topic+', blank=True) 
    coauthors = models.ManyToManyField('Expert', related_name='coauthors+', blank=True) 
    title = models.CharField(max_length=200) 
    citations = models.ManyToManyField('Paper', related_name='citations+', blank=True) 

    def __str__(self): 
     return self.title 

回答

2

我想你应该提交表单时检查数据。尝试将这个重载的clean方法放入表单中,然后将表单放入您的Paper模型的ModelAdmin定义中。

# admin.py 
from django.contrib import admin 
from django import forms 
from django.core.exceptions import ValidationError 
from .models import Paper 

class PaperForm(forms.ModelForm): 
    class Meta: 
     model = Paper 
    def clean(self): 
     topic = self.cleaned_data.get('topic') 
     if topic.count() > 4: 
      raise ValidationError("To many topics!") 
     return self.cleaned_data 

class PaperAdmin(admin.ModelAdmin): 
    form = PaperForm 

admin.register(Paper, PaperAdmin) 

此外,它不是最好的方式来定义related_name。 related_name应该帮助你从它的关系中回溯到模型。这样做:

# in your model 
topics = models.ManyToManyField('Topic', related_name='papers', blank=True) 

# shell 
paper = Paper.objects.order_by('?')[0] # get random object 
paper.topics.all() # and access it's topics 
topic = Topic.objects.order_by('?')[0] # now get random topic 
topic.papers.all() # and get it's papers using related_name! 

它比topic.topic+.all()好吗?我甚至不确定它是否可以工作。

+0

它的工作,你是对的,在提交过程中检查数据是解决方案。谢谢! – Burak

0

我认为你应该在你的模型上使用clean()方法,但不要在你的窗体上使用。

首先,因为这与你的模型有关,而不是你的表单,因为如果将来你有其他形式,它应该做出相同的控制,从而重复你自己。

的model.clean()方法作为Django docs

表单验证的一部分执行,你可以肯定此外,它是很好的遵循最佳实践(除非你知道更好)和MVC-之一像框架的最佳做法是有fat models