Domanda

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']})
È stato utile?

Soluzione

You're passing self.request.POST to your form's save method, which is set to expect a request as its first argument. Or at least something that has a user attribute. If you pass in self.request instead, you will no longer get that particular error.

It is odd that you're reinstantiating form in your form_valid method, which receives the bound form as an argument.

You're returning HttpResponse objects from your form's custom save method, which is nonstandard. But as long as you're doing that, you should return them from your form_valid method.

In summary, something like this:

def form_valid(self, form):
    return form.save(self.request)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top