Reputation: 65
Trying to solve this for a week now. How do I filter my model to display only the data assigned to the specific logged-in user? My views.py code below is not working---it's not telling forms.py what it needs to do to accomplish this. I get the error 'ForwardManyToOneDescriptor' object has no attribute 'option1'.
It does filter effectively in the template---but I need to use the RadioSelect widget (defined in forms.py) in order to display specific choices that the specific logged-in user must choose from (and I don't think I can---or should---code that in the template).
views.py
class VoteView(LoginRequiredMixin, CreateView):
model = Result
form_class = VotingForm
template_name = 'users/vote_form.html'
def get_context_data(self,
**kwargs):
context =
super().get_context_data
(**kwargs)
context['Result'] =
Result.objects.all()
context['user_specific'] =
Result.objects.filter
(custom_user=self.request.user)
return context
def get_form_kwargs(self):
kwargs=super().
get_form_kwargs()
kwargs.update({'results':
Result.objects.
filter(custom_user=
self.request.user)})
return kwargs
* Added following post method, but
get " KeyError 'results' " error
def post(self, request, *args,
**kwargs):
form = self.form_class(data=request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.custom_user =
self.kwargs
instance.save()
return redirect('users:home')
def get_success_url(self):
return reverse('users:home')
forms.py
class VotingForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
choices = [('1', Result.decision.option1),
('2', Result.decision.option2)]
self.fields['vote'] = forms.ChoiceField(choices=choices, label="Choices", widget=forms.RadioSelect())
class Meta:
model = Result
fields = ['decision', 'vote']
models.py (if needed)
class Result(models.Model):
custom_user = models.ForeignKey(CustomUser)
decision = models.ForeignKey(Decision) * Decision
contains
decisions and
their choices
(like 'option1', 'option2')
vote = models.CharField()
vote_eligible = models.BooleanField(default=False)
vote_form.html
<form method="post">
{% csrf_token %}
{% for item in user_specific %}
{% if item.vote_eligible ==True %}
<div class="field-bold">
Decision
</div>
<p>{{ item.decision }}</p>
<div class="field-bold">
{{ form.vote|as_crispy_field }}
</div>
<div class="btn-container">
<div class="btn-grp">
<input type="submit"
class="btn btn-submit"
value="Vote"/>
<a href="{% url
'users:home' %}"
class="btn
btn-cancel">Cancel</a>
</div>
</div>
{% endif %}
{% endfor %}
{% if not user_specific %}
<p>There are currently no
decisions awaiting your vote.
</p>
{% endif %}
</form>
Upvotes: 2
Views: 1040
Reputation: 1879
Your problem is in this line:
choices = [('1', Result.decision.option1),
('2', Result.decision.option2)]
What you're doing here is setting choices according to model fields. You're not using their values. Their values are tied to particular instance of the Result
model.
Usually, this problem requires that you know which instances of the Result
model will be used for the options. I normally pass it in the form kwargs like this:
def __init__(self, *args, **kwargs):
results = kwargs.pop('results')
super().__init__(*args, **kwargs)
# Now we're using a model INSTANCE, not the model itself
# Also, you don't need to use the number for a key value. Makes
# it a bit easier.
choices = []
for result in results.all():
choices.append((result.decision.option1, result.decision.option1))
choices.append((result.decision.option2, result.decision.option2))
self.fields['vote'] = forms.ChoiceField(choices=choices, label="Choices", widget=forms.RadioSelect())
Then in the views.py add get_form_kwargs
to initialize the kwargs for your form:
def get_form_kwargs():
kwargs = super().get_form_kwargs()
kwargs.update({'results': Result.objects.filter(custom_user=self.request.user)})
return kwargs
Upvotes: 1