Reputation: 65
Working on my first Django project and could use some help. I have 2 models (Decisions, Votes) linked by the foreign key called 'decision'. The template, vote_list.html, shows the user a list of decisions (generated by other users) that are contained in Decisions. The user taps a particular decision and is re-directed to a second template to vote on options pertaining to that decision. How do I autopopulate the foreign key 'decision' in Votes with the corresponding instance of Decision so that the second template, vote_form.html, displays the options for the decision they tapped on? I assume it's coded in views.py (I commented an attempt below that doesn't work), but how might it be done? Thank you!
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 }}
Upvotes: 1
Views: 476
Reputation: 1879
I think this might solve your problem:
decision
field in the voting form. This will display an option to select for which decision you need to save this Vote for.
If you don't want to allow users to change the Decision, you can mark the field as disabled. See this issue for more details on how to do that. Another alternative is to completely hide the field.class VotingForm(forms.ModelForm):
class Meta:
model = Votes
fields = ['vote', 'decision']
decision
when instantiating the VotingForm
. This will automatically set which decision is selected when displaying the form.class VoteForm(LoginRequiredMixin, CreateView):
model = Votes
form_class = VotingForm
template_name = 'users/vote_form.html'
# Use this to pass 'pk' to your context in the template
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({'pk': self.kwargs['pk'})
return context
def get_initial(self):
initial = super().get_initial()
initial.update({'decision': self.kwargs['pk']})
return initial
def get_success_url():
# Import reverse from django.urls
return reverse('users:vote_list')
Also, your form should probably be displayed like this in the HTML template: {% crispy form %}
. This way all defined fields from the VotingForm
class are rendered automatically.
<form method="post" action="{% url 'users:vote_form' pk %}">
{% crispy form %}
</form>
Upvotes: 1