Django FormView Not Saving
Asked Answered
B

3

10

My form isn't saving the models that I need it to. My form:

class RewardForm(forms.Form):
    quantity = forms.IntegerField(max_value=10, min_value=1, label=_('quantity'), initial=1)
    reward = forms.CharField(max_length=50, label=_('reward'))
    reward_denomination = forms.ModelChoiceField(queryset=Reward_Denomination.objects.all(), widget=forms.RadioSelect)

    def clean_reward(self):
        data = self.cleaned_data.get('reward')
        try:
            reward = Reward.objects.get(reward_name=data)
        except ObjectDoesNotExist:
            raise forms.ValidationError(_('Reward does not exist'), code='invalid')
        return data

    def clean_reward_denomination(self):
        data = self.cleaned_data.get('reward_denomination')
        try:
            denomination = Reward_Denomination.objects.get(denomination=data)
        except ObjectDoesNotExist:
            raise forms.ValidationError(_('Denomination does not exist'), code='invalid')
        return data

    def save(self, request, commit=True):
        user = request.user
        data = self.cleaned_data

        'try:
            post_reward = data['reward']
            post_denomination = data['reward_denomination']
            quantity = data['quantity']
        except LookupError:
            raise Http404

        reward = Reward.objects.get(reward_name=post_reward)
        denomination = Reward_Denomination.objects.get(denomination=post_denomination)
        user_points = Points.objects.filter(affiliate__id=user.id).aggregate(total_points=Sum('points'))
        user_points = user_points['total_points']

        try:
            total_cost = (quantity * denomination.cost)
        except ArithmeticError:
            raise Http404

        quote_price = -total_cost

        if user_points >= total_cost:
                reward_order = Points.objects.create(affiliate=user, points=quote_price, from_reward=True, from_offer=False)
                status_coded = 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, status_code=status_coded, quantity=quantity, reward=reward, price=total_cost)

        return reward_order

My Views:

class Reward_Detail(DetailView):
    model = Reward
    slug_field = 'reward_slug'
    context_object_name = 'reward'
    template_name = 'omninectar/reward.html'


#Detail Stuff

class RedeemReward(SingleObjectMixin, FormView):
    template_name = 'omninectar/reward.html'
    slug_field = 'reward_slug'
    form_class = RewardForm
    model = Reward

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(RedeemReward, self).post(request, *args, **kwargs)

    def get_success_url(self):
        return reverse('omni:reward_confirmation')

class RewardBeautify(View):
    def get(self, request, *args, **kwargs):
        view = Reward_Detail.as_view()
        return view(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        view = RedeemReward.as_view()
        return view(request, *args, **kwargs)

So I initially thought that the FormView would handle the form processing (validate, and, if valid, run form.save(), etc). I'm following the FormView, SingleObjectMixin example on the Django website. I don't receive any errors when I try and submit the form, but no objects are created either. I've tried defining a form_valid method that runs the save method, I've tried putting it inside the post method in the formview, etc. Can anyone spot the error/errors? Thanks!

Batfish answered 31/12, 2013 at 6:16 Comment(2)
Well try to put import pdb; pdb.set_trace into your method save of your form, then call this method from form_valid. This way you can see how whether or not the error comes from the method of your formHolystone
One Big problem is, that save method returns nothing if your last condition fails. Because the variable is not set before that condition and is only set in that condition. That is one error i can spot. Another minor detail is raising 404 on arithmetical error. 404 means that page is missing and should not be used when something else fails. Also, for clarity's sake, since you are wrapping other potential errors into try/except, you might want to use get_object_or_404 in all the places where you are using Model.objects.getWheen
H
24

I'm new to view classes too and I had almost the same problem with Django 1.6.

You should add

def form_valid(self, form):
    form.save()
    return super(RedeemReward, self).form_valid(form)

method overriding to your RedeemReward class. This worked for me.

If you look to Django source code, you will see that there is no form saving in FormView class inheritance chain.

Harlem answered 6/8, 2014 at 6:18 Comment(0)
S
3

I am not sure if this will help or not, but I had issues finding code showing how to save the data from a FormView model. This is what I came up with. I hope it helps and you can apply it to your code.

forms.py

class JobCreateForm(forms.Form):
    title = forms.CharField(label='Job Title', max_length=500)
    number = forms.IntegerField(label='Job Number: ')
    comps = forms.ModelMultipleChoiceField(label='Comparable Sales',      
    required=False, queryset=m.ComparableSale.objects.all())
    details = forms.CharField(label='Job Details:', max_length=200,     
    required=False, widget=forms.Textarea(attrs={'rows':6, 'cols':20}))

Views.py

class JobCreateView(generic.FormView):
    template_name = 'form_templates/createjob_form.html'
    form_class = f.JobCreateForm
    model = models.Job
    success_url = '/'

    def form_valid(self, form):
        comps = form.cleaned_data['comps']
        title = form.cleaned_data['title']
        number = form.cleaned_data['number']
        details = form.cleaned_data['details']
        job = models.Job(title=title, number=number, details=details)
        job.save()
        print(comps)
        if comps != []:
            job.comps.add(*comps)
        return super(JobCreateView, self).form_valid(form)
Sadesadella answered 11/5, 2016 at 14:28 Comment(0)
C
0

You can write your own ModelFormView using the mixins provided by Django (specifically, the ModelFormMixin). Then your form will be saved on a successful post.

from django.views.generic.base import TemplateResponseMixin
from django.views.generic.edit import ModelFormMixin, ProcessFormView


class BaseModelFormView(ModelFormMixin, ProcessFormView):
    pass


class ModelFormView(TemplateResponseMixin, BaseModelFormView):
    pass
Conation answered 29/12, 2014 at 17:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.