Django: Как автозаполнить внешний ключ соответствующим экземпляром класса модели
Работаю над своим первым проектом Django и мог бы воспользоваться некоторой помощью. У меня есть 2 модели (Decisions, Votes), связанные внешним ключом 'decision'. Шаблон vote_list.html показывает пользователю список решений (сгенерированных другими пользователями), которые содержатся в Decisions. Пользователь нажимает на определенное решение и перенаправляется на второй шаблон для голосования по вариантам, относящимся к этому решению. Как мне автоматически заполнить внешний ключ 'decision' в Votes соответствующим экземпляром Decision, чтобы во втором шаблоне, vote_form.html, отображались варианты решения, на которое пользователь нажал? Я предполагаю, что это кодируется в views.py (я прокомментировал попытку ниже, которая не работает), но как это можно сделать? Спасибо!
urls.py
path('vote-list/', views.VoterView.as_view(), name='vote_list'),
path('vote-list/<pk>/vote-form/', views.VoteForm.as_view(), name='vote_form'),
models.py
class Decisions(models.Model):
custom_user = models.ForeignKey(CustomUser,
default=None, null=True,
on_delete=models.SET_NULL)
description = models.CharField(default="",
max_length=100, verbose_name="Decision
Summary")
class Votes(models.Model):
decision = models.ForeignKey(Decisions,
default=None, null=True,
on_delete=models.SET_NULL)
vote = models.CharField(default="", max_length=100,
verbose_name="Your vote")
views.py
class VoteForm(LoginRequiredMixin, CreateView):
model = Votes
form_class = VotingForm
template_name = 'users/vote_form.html'
def post(self, request, *args, **kwargs):
super()
form = self.form_class(data=request.POST)
if form.is_valid():
instance = form.save(commit=False)
# instance.decision = Decisions.description
instance.save()
return redirect('users:vote_list')
forms.py
class VotingForm(forms.ModelForm):
class Meta:
model = Votes
fields = ['vote']
vote_list.html
{% for item in Decisions %}
<tr>
<td>{{ item.description }}</td>
<td><a href="{% url 'users:vote_form' item.id
%}">Vote</a></td>
</tr>
{% endfor %}
vote_form.html
{# trying to display the corresponding
decision description here from vote_list.html # }}
{{ form.vote|as_crispy_field }}
Я думаю, что это может решить вашу проблему:
- Добавьте поле
decisionв форму голосования. В нем будет отображаться опция выбора, для какого решения вам нужно сохранить этот голос. Если вы не хотите разрешать пользователям изменять решение, вы можете пометить поле как отключенное. Смотрите этот вопрос для более подробной информации о том, как это сделать. Другой альтернативой является полное скрытие поля.
class VotingForm(forms.ModelForm):
class Meta:
model = Votes
fields = ['vote', 'decision']
- Добавьте начальное значение
decisionпри инстанцированииVotingForm. Это автоматически установит, какое решение будет выбрано при отображении формы.
class VoteForm(LoginRequiredMixin, CreateView):
model = Votes
form_class = VotingForm
template_name = 'users/vote_form.html'
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update({'initial': {'decision': self.kwargs['pk']}})
return kwargs
def post(self, request, *args, **kwargs):
super() # BTW, no idea why is this here
form = self.form_class(data=request.POST)
if form.is_valid():
form.save(commit=False)
return redirect('users:vote_list')
Кроме того, ваша форма, вероятно, должна отображаться в HTML-шаблоне следующим образом: {% crispy form %}. Таким образом, все определенные поля будут отображаться автоматически.