#python #django #database-design
#python #django #проектирование базы данных
Вопрос:
Я нахожусь в процессе разработки пары новых моделей для моего приложения 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 = ?
Итак, мне нужна модель букмекера и модель страны, и они должны быть связаны, НО у каждого букмекера должен быть список стран, которые принимаются, и список стран, которые исключены.
Вопросительные знаки находятся как в моделях Country, так и в моделях букмекера, поскольку я не уверен, в какую сторону следует устанавливать отношение.
Не уверен, что я на правильном пути, но я думаю, что мне нужна пара отношений «многие ко многим».. И какой правильный способ (если таковой имеется) использовать одну и ту же модель страны (это будут разные экземпляры) как в accepted_countries, так и в restricted_countries?
Спасибо.
Комментарии:
1. Являются ли
restricted_countries
иaccepted_countries
списки исчерпывающими? Если это так, вам нужно будет отслеживать только один из них, а затем вычислять другой на основе того, какие страны отсутствуют.2. Какова цель
bookmakers
поля вCountry
модели? В дополнение к принятым / ограниченным странам,Bookmaker
нужно ли каким-либо другим образом связывать a с одной страной или несколькими странами? Если нет, нет необходимости включать поле букмекеров в модель страны.3. Привет @jimijimjim Да, вы правы, нет необходимости включать букмекерские конторы в модель страны; Я написал это только для того, чтобы подчеркнуть, что я не знал, в какую сторону идет отношение… Что касается исчерпывающей информации о списках, если страна принята, она не может быть ограничена наоборот, но если у меня нет информации о конкретной стране, которая может не входить ни в одну из двух.
Ответ №1:
Вы должны использовать два отношения «многие ко многим» с 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()
Комментарии:
1. Спасибо, я думаю, что попробую этот подход.
Ответ №2:
Вам действительно нужно несколько «многие ко многим»:
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 выполнит промежуточный шаг за вас.
Поле букмекерские конторы в Country позволяет вам получить все букмекерские конторы, связанные со страной, без необходимости проверять как принятые, так и ограниченные (это больше для удобства).
Но вам нужно будет добавить букмекера в этот список на вашем представлении, например:
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())