Django模型设计:具有特定需求的多对多关系

时间:2019-04-24 15:04:25

标签: python django database-design

我正在为django应用程序设计几个新模型,这就是我需要的:

class Bookmaker(models.Model):
  name = models.CharField(max_length=50)
  accepted_countries = ?
  restricted_countries = ?

class Country(models.Model):
  name = models.CharField(max_length=50)
  bookmakers = ?

因此,我需要一个庄家模型和一个国家模型,并且需要将它们联系起来,但是每个庄家都应该有一个接受国家列表和一个被排除国家列表。 国家/地区和博彩公司模型中都有问号,因为我不确定这种关系应该走哪条路。

不确定我走的路是否正确,但我认为我需要一对多对多的关系。而且,这是使用相同国家/地区模型的正确方法(如果有) (这些实例将是不同的实例)在accepted_countries和stricted_countries中?

谢谢。

2 个答案:

答案 0 :(得分:0)

您应使用与related_name的两个多对多关系来将它们分开:

class Bookmaker(models.Model):
    name = models.CharField(max_length=50)
    accepted_countries = models.ManyToManyField(Country, related_name="accepted_for")
    restricted_countries = models.ManyToManyField(Country, related_name="restricted_for")

然后可以将反向关系用作:

bookmakers_for_which_county_is_accepted = Country.objects.values('accepted_for').distinct()
bookmakers_for_which_county_is_restricted = Country.objects.values('restricted_for').distinct()

docs

答案 1 :(得分:0)

您确实确实需要很多:

class Bookmaker(models.Model):
  name = models.CharField(max_length=50)
  accepted_countries = models.ManyToMany('Country',related_name='accepted')
  restricted_countries = models.ManyToMany('Country', related_name= 'restricted')

class Country(models.Model):
  name = models.CharField(max_length=50)
  bookmakers = models.ManyToMany(Bookmaker)

然后,如果您创建一个表格来编辑庄家,您将无法添加名称,接受和限制的国家/地区:

forms.py

class BookmakerForm(models.ModelForm):
    class Meta:
        model = Bookmaker
        fields = ['name', 'accepted_countries', 'restricted_countries']

    #for having a better default display you can change the widget:
    self __init__(self, *args, **kwargs):
        super(BookmakerForm, self).__init__(*args, **kwargs)
        self.fields['accepted_countries'].widget = CheckboxSelectMultiple()
        self.fields['restricted_countries'].widget = CheckboxSelectMultiple()

默认情况下,仅在视图中查看form.is_valid()并保存。 django modelform将为您管理中介步骤。

“国家/地区”的庄家字段使您可以检索与某个国家/地区相关的所有庄家,而不必检查已接受和受限制的(为了方便起见)。

但是您需要将博彩公司添加到该视图上的列表中,例如:

class CreateBookmakerView(CreateView):
    model = Bookmaker
    form_class = BookmakerForm
    success_url = reverse_lazy('your success url name here')

    def form_valid(self,form):
        bookmaker = form.save()
        bookmaker.country_set.add(bookmaker)
        bookmaker.save()
        return HttpResponseRedirect(self.get_success_url())