简体   繁体   中英

Django Models design: many-to-many relationship with specific needs

I am in the process of designing a couple of new models for my django app and this is what I need:

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 = ?

So I need a model Bookmaker and a model Country and they need to be related, BUT every bookmaker should have a list of countries that are accepted and a list of countries that are excluded. The question marks are both in the Country and in the Bookmaker models as I'm not sure which way the relation should go.

Not sure if I'm on the right path, but I'm thinking that I need a couple of many-to-many relationships.. And, which is the right way (if any) to use the same Country model (those will be different instances) in both accepted_countries and restricted_countries?

Thanks.

You should use two many to many relations with related_name to separate them:

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")

You can then use the reverse relation as:

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

You need indeed some many to many:

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)

Then if you create a form to edit a bookmaker you will be abble to add the name, the accepted and restricted countries:

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()

In the view by default if you just need to check if form.is_valid() and save. django modelform will manage the intermediary step for you.

The bookmakers field in Country allows you to retrieve all the bookmaker associated to a country without having to check in both accepted and restricted (it's more for convenience).

But you will need to add the bookmaker to that list on you view like:

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())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM