Какова лучшая схема базы данных для опросов? Действительно ли связь "один ко многим" хороша для этого? Я думаю о наличии двух таблиц:
poll_questions
int id
varchar body
datetime created_at
datetime updated_at
poll_answers
int id
varchar body
int votes default 0
int question_id (foreign key to poll_questions.id)
datetime created_at
datetime updated_at
Тогда также была бы третья таблица для отслеживания, кто голосовал за ответ, таким образом, пользователи в состоянии голосовать только однажды:
poll_voting_history
int id
int question_id (foreign key to poll_questions.id)
int answer_id (foreign key to poll_answers.id)
int user_id (foreign key to the id in the users table)
datetime created_at
datetime updated_at
Каковы Ваши мысли? Я думаю об этом право?
Вы запускаете его на локальном компьютере, и PHPing подключится к производственному серверу и развернет веб-сайт.:)
-121--4716325- Я думаю, вам придется добавить здесь новый ModelMultipleChoeyField
в PizzaForm
и вручную связать это поле формы с полем модели, так как Джанго не сделает этого автоматически для вас.
Следующий фрагмент может быть полезен:
class PizzaForm(forms.ModelForm):
class Meta:
model = Pizza
# Representing the many to many related field in Pizza
toppings = forms.ModelMultipleChoiceField(queryset=Topping.objects.all())
# Overriding __init__ here allows us to provide initial
# data for 'toppings' field
def __init__(self, *args, **kwargs):
# Only in case we build the form from an instance
# (otherwise, 'toppings' list should be empty)
if kwargs.get('instance'):
# We get the 'initial' keyword argument or initialize it
# as a dict if it didn't exist.
initial = kwargs.setdefault('initial', {})
# The widget for a ModelMultipleChoiceField expects
# a list of primary key for the selected data.
initial['toppings'] = [t.pk for t in kwargs['instance'].topping_set.all()]
forms.ModelForm.__init__(self, *args, **kwargs)
# Overriding save allows us to process the value of 'toppings' field
def save(self, commit=True):
# Get the unsave Pizza instance
instance = forms.ModelForm.save(self, False)
# Prepare a 'save_m2m' method for the form,
old_save_m2m = self.save_m2m
def save_m2m():
old_save_m2m()
# This is where we actually link the pizza with toppings
instance.topping_set.clear()
instance.topping_set.add(*self.cleaned_data['toppings'])
self.save_m2m = save_m2m
# Do we need to save all changes now?
if commit:
instance.save()
self.save_m2m()
return instance
Эту PizzaForm
можно использовать везде, даже у администратора:
# yourapp/admin.py
from django.contrib.admin import site, ModelAdmin
from yourapp.models import Pizza
from yourapp.forms import PizzaForm
class PizzaAdmin(ModelAdmin):
form = PizzaForm
site.register(Pizza, PizzaAdmin)
Метод save ()
может быть слишком подробным, но его можно упростить, если не требуется поддерживать ситуацию commit = False
, то он будет таким:
def save(self):
instance = forms.ModelForm.save(self)
instance.topping_set.clear()
instance.topping_set.add(*self.cleaned_data['toppings'])
return instance
-121--891898- Схема выглядит хорошо, и да, вам также необходимо отслеживать голоса пользователей .
Примечание: столбец «голосов» в таблице poll_answers не необходимо. Голоса можно определить, запросив таблицу Poll_voting_history.