Я пытаюсь расширить учебник по Django для школьного проекта и превратить его в более удобное приложение для голосования.
Я хочу, чтобы пользователи могли создавать опросы и приглашать других зарегистрированных пользователей по электронной почте на адресголосовать на своем опросе.Только приглашенные пользователи будут допущены к голосованию.
My models.py
:
class Poll(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published', auto_now_add=True)
is_active = models.BooleanField(default=True)
activation_date = models.DateTimeField('Activation Date', blank=True, null=True)
expiration_date = models.DateTimeField('Expiration Date', blank=True, null=True)
public_key = models.CharField(max_length=30, blank=True)
hash = models.CharField(max_length=128, blank=True)
timestamp = models.DateTimeField(auto_now=True)
def __str__(self):
return self.question_text
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
class Choice(models.Model):
question = models.ForeignKey(Poll, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
class EligibleVoters(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
poll = models.ForeignKey(Poll, on_delete=models.CASCADE)
email = models.EmailField(null=True)
У меня есть таблица Poll
, которая содержит заголовок опроса и другую информацию, касающуюся опроса.Я также создал отдельную таблицу Choices
(как в учебнике), которая имеет ForeignKey
для таблицы Poll
и содержит варианты опроса.Я подумал, что для того, чтобы пригласить пользователей в качестве подходящих избирателей, мне нужна третья таблица с ForeignKeys
для таблиц Poll
и User
.Итак, я создал один.
Я должен отметить, что я использую встроенную пользовательскую модель.
Вот мой views.py
:
class NewPoll(CreateView):
model = Poll
fields = ['question_text', 'is_active', 'activation_date', 'expiration_date']
success_url = reverse_lazy('voting:index')
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
if self.request.POST:
data['choices'] = ChoiceFormSet(self.request.POST)
# data['eligible_voters_poll'] = EligibleVotersFormSetPoll(self.request.POST)
# data['eligible_voters_user'] = EligibleVotersFormSetUser(self.request.POST)
#data['eligible_voters'] = EligibleVotersFormSet(self.request.POST)
else:
data['choices'] = ChoiceFormSet()
# data['eligible_voters_poll'] = EligibleVotersFormSetPoll()
# data['eligible_voters_user'] = EligibleVotersFormSetUser()
# data['eligible_voters'] = EligibleVotersFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
choices = context['choices']
# eligible_voters_poll = context['eligible_voters_poll']
# eligible_voters_user = context['eligible_voters_user']
#eligible_voters = context['eligible_voters']
with transaction.atomic():
self.object = form.save()
if choices.is_valid():
choices.instance = self.object
choices.save()
# if eligible_voters_poll.is_valid() and eligible_voters_user.is_valid():
# eligible_voters_poll.instance = self.object
# eligible_voters_poll.save()
# eligible_voters_user.instance = self.object
# eligible_voters_user.save()
#if eligible_voters.is_valid():
# eligible_voters.instance = self.object
# eligible_voters.save()
return super().form_valid(form)
Я прокомментировал строки, которые были предыдущимипопытаться заставить это работать.Без закомментированных строк пользователь может создать опрос, а также создать выбор.У меня проблемы с тем, чтобы заставить часть приглашения работать.
Вот мой forms.py
:
class PollForm(ModelForm):
activation_date = forms.DateTimeField(required=False)
expiration_date = forms.DateTimeField(required=False)
class Meta:
model = Poll
fields = ['question_text', 'is_active', 'activation_date', 'expiration_date']
class ChoiceForm(ModelForm):
class Meta:
model = Choice
exclude = ['votes']
ChoiceFormSet = inlineformset_factory(Poll, Choice, form=ChoiceForm, extra=1)
def form_maker(parent2):
class EligibleVotersForm(ModelForm):
# def __init__(self, user, poll, *args, **kwargs):
# self.user = user
# self.poll = poll
# super().__init__(*args, **kwargs)
def save(self, commit=True):
instance = super(EligibleVotersForm, self).save(commit=False)
# instance.parent1 = parent1
instance.parent2 = parent2
if commit:
instance.save()
return instance
class Meta:
model = EligibleVoters
fields = ['email']
return EligibleVotersForm
# EligibleVotersFormSetPoll = inlineformset_factory(Poll, EligibleVoters, form=EligibleVotersForm, extra=1)
# EligibleVotersFormSetUser = inlineformset_factory(User, EligibleVoters, form=EligibleVotersForm, extra=1)
# EligibleVotersFormSet = inlineformset_factory(Poll, EligibleVoters, form=form_maker(User), extra=1)
Здесь я снова прокомментировал строки, которые относятся к моим неудачным попыткам сделатьэто работает.Чем ближе я к работе, тем больше я могу приглашать по электронной почте (не только по зарегистрированным, что мне и нужно) и заполнять таблицу EligibleVoters
электронными письмами, связанными с poll_id
.Столбец user_id
хотя и остался пустым.
Вот мой HTML-файл:
{% extends 'base.html' %}
{% block content %}
{% load static %}
<h2>Poll Creation</h2>
<div class="col-md-4">
<form action='' method="post">
{% csrf_token %}
{{ form.as_p }}
<table class="table">
{{ choices.management_form }}
{% for form in choices.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle 'row1' 'row2' %} formset_row1">
{% for field in form.visible_fields %}
<td>
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<table class="table">
{{ eligible_voters.management_form }}
{% for form in eligible_voters.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle 'row1' 'row2' %} formset_row2">
{% for field in form.visible_fields %}
<td>
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Save"/> <a href="{% url 'voting:index' %}">back to the list</a>
</form>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="{% static 'voting/js/jquery.formset.js' %}"></script>
<script type="text/javascript">
$('.formset_row1').formset({
addText: 'add poll choice',
deleteText: 'remove',
prefix: 'choice_set'
});
$('.formset_row2').formset({
addText: 'add eligible voter',
deleteText: 'remove',
prefix: 'eligiblevoters_set'
});
</script>
{% endblock %}
Любые идеи о том, как заставить его работать, и только он имеет право избирателей, имеющих право голоса, голосовать за те опросы, которые ониприглашены?Я думал, что, возможно, моя EligibleVoters
модель как-то не так, и мне нужно где-то поле ManyToMany
??