Inlineformset_factory для таблицы с двумя внешними ключами - PullRequest
0 голосов
/ 24 мая 2018

Я пытаюсь расширить использование официального руководства по django, которое создает приложение для голосования.В настоящий момент я пытаюсь разрешить пользователю создать опрос, ввести имя опроса, параметры опроса и пригласить нужных пользователей по электронной почте от уже зарегистрированных пользователей.

my model.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)

my forms.py:

from django.forms import ModelForm, inlineformset_factory
from django import forms
from .models import Poll, Choice, EligibleVoters, PollKeyPart, User


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


ChoiceFormSet = inlineformset_factory(Poll, Choice, form=ChoiceForm, extra=1)


class EligibleVotersForm(ModelForm):
    class Meta:
        model = EligibleVoters
        fields = ['email']


EligibleVotersFormSetPoll = inlineformset_factory(Poll, EligibleVoters, form=EligibleVotersForm, extra=1)
#EligibleVotersFormSetUser = inlineformset_factory(User, EligibleVoters, form=EligibleVotersForm, extra=1)

my 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(NewPoll, self).get_context_data(**kwargs)
        if self.request.POST:
            data['choices'] = ChoiceFormSet(self.request.POST)
            data['eligible_voters_poll'] = EligibleVotersFormSetPoll(self.request.POST)                
        else:
            data['choices'] = ChoiceFormSet()
            data['eligible_voters_poll'] = EligibleVotersFormSetPoll()               
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        choices = context['choices']
        eligible_voters_poll = context['eligible_voters_poll']          
        with transaction.atomic():
            self.object = form.save()
            if choices.is_valid():
                choices.instance = self.object
                choices.save()
            if eligible_voters_poll.is_valid():
                eligible_voters_poll.instance = self.object
                eligible_voters_poll.save()
        return super(NewPoll, self).form_valid(form)

И мой 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_poll.management_form }}

        {% for form in eligible_voters_poll.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 столбец user_id остается пустым, и только поля poll_id и email заняты каждой записью.Почему-то мне нужно связать каждую запись с соответствующей user_id.Каков наилучший способ сделать это?

Я также хочу добавить проверку, в которой вы можете приглашать только зарегистрированных пользователей и создать пару ключей для опроса, используя библиотеку криптографии, которая у меня уже есть, но я не уверен, каксделать это тоже.

...