I have a FormView that is basically a product page. You can view product details and request the product from a form on that page. I want the page to be set up so that anyone can view the page, but only people that are logged in can request the product. To do this, I added a login_required decorator to the post function in the FormView, but I get the error:
'QueryDict' object has no attribute 'user'
How can I code this view/form so it acts as I described?
View:
class RedeemReward(SingleObjectMixin, FormView):
template_name = 'reward.html'
slug_field = 'reward_slug'
form_class = Redeem_Reward
model = Reward
@method_decorator(login_required)
def post(self, request, *args, **kwargs):
return super(RedeemReward, self).post(request, *args, **kwargs)
def form_valid(self, form):
form_class = self.get_form_class()
form = self.get_form(form_class)
#form = self.get_form(self.get_form_class())
#form.save(self.request.POST)
form.save(self.request.POST)
return super(RedeemReward, self).form_valid(form)
def get_success_url(self):
return reverse('reward_confirmation', args=(self.object.reward_slug, self.object.reward_code))
def dispatch(self, *args, **kwargs):
self.object = self.get_object()
return super(RedeemReward, self).dispatch(*args, **kwargs)
Form:
class Redeem_Reward(forms.Form):
quantity = forms.IntegerField(label=_('Quantity'), error_messages={'invalid':'Must be a valid number'})
reward_name = forms.CharField(max_length=50, widget=forms.HiddenInput(), label=_('Reward Name'), error_messages={'invalid':'Invalid reward'})
def clean_quantity(self):
"""
Validate that the user entered a valid number.
"""
return self.cleaned_data['quantity']
def clean_reward_name(self):
"""
Validate that this reward code exists.
"""
try:
existing_reward = Reward.objects.get(reward_name=self.cleaned_data['reward_name'])
except ObjectDoesNotExist:
raise forms.ValidationError(_("The reward you requested does not exist."))
return self.cleaned_data['reward_name']
def save(self, request, *args, **kwargs):
"""
Save all of the required data.
"""
user = request.user
#user_points = Points.objects.filter(affiliate__id=user.id).annotate(total_points=Sum('points'))
user_points = Affiliate.objects.filter(points__affiliate__id=user.id).annotate(total_points=Sum('points'))
user_points = user_points[0].total_points
error_message = {'lookuperror':'You need to provide a valid quantity',
'insufficient_points':"You don't have enough points for this purchase."}
try:
quantity = self.cleaned_data['quantity']
reward_name = self.cleaned_data['reward_name']
rewards = Reward.objects.get(reward_name=reward_name)
except LookupError:
raise Http404
try:
points_cost = -(rewards.reward_cost * quantity)
except ArithmeticError:
raise Http404
quote_price = -(points_cost)
if user_points >= quote_price:
reward_order = Points.objects.create(affiliate=user, reward=rewards, points=points_cost, from_reward=True, from_offer=False, from_referral=False)
status_cost = Status_Code.objects.create(short_name="Pending", name="The order is currently being reviewed", description="The order is in queue")
redeem_order = Redeem.objects.create(affiliate=user, reward=rewards, status_code=status_code)
redeem_details = Redeem_Details.objects.create(redeem=redeem_order, quantity=quantity, quote_price=quote_price)
return HttpResponseRedirect(reverse('reward_confirmation', args=(redeem_details.redeem_code,)))
else:
return render(request, 'reward.html', {'error_message':error_message['insufficient_points']})