[Answered ]-Persist Django FormView Data

1👍

The view is an object right, so you just assign your values to instance variables, i e “to self” (this is thread-safe). Like this:

class ReviewCreate(FormView):
    template_name = 'food/item_add_review.html'
    form_class = ReviewForm

    @method_decorator(login_required)  # Use a class level mixin instead
    def get_context_data(self, **kwargs):
        return super(
            ReviewCreate, 
            self
        ).get_context_data(
            item=self.review_item,
            **kwargs
        )

    def lookup_review_item(self):
        self.item_modelname = self.kwargs.get('model')
        item_model = apps.get_model('food', self.item_modelname)
        self.review_item = get_object_or_404(
            item_model, 
            pk=self.kwargs.get('pk')
        )

    def dispatch(self, request, *args, **kwargs):
        # lookup performed here to be set for both GET and POST
        self.lookup_review_item()
        return super(ReviewCreate, self).dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        r = form.save(commit=False)
        r.content_object=self.review_item
        r.save()
        return super(ReviewCreate, self).form_valid(form)

    def get_success_url(self):
        return reverse(
            'pkitem', 
            kwargs = {
                'pk': self.review_item.id, 
                'model': self.item_modelname
            },
        )

1👍

The default form_valid() method for FormView redirects to the success url and reinitializes the form. You can make the form data persist by overriding form_valid():

def form_valid(self, form):
    return super(YourFormView, self).get(form)

This will redirect to your success url with a (bounded) form having the posted data. The form is added to the context so you can use the data in your template or in your view as you wish.

(Django version 1.11.7)

0👍

The get_context_data should always return the context dictionary. It doesn’t make sense to use the login_required decorator with it, because that means it might return a redirect response instead.

It would be better decorate the dispatch method instead. In your dispatch, you can set attributes on the instance.

class ReviewCreate(FormView):

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        self.item_modelname = self.kwargs.get('model')
        self.item_model = apps.get_model('food',item_modelname)
        self.review_item = get_object_or_404(item_model,pk=self.kwargs.get('pk'))
        return super(ReviewCreate, self).dispatch(request, *args, **kwargs)

Then, in your other methods, you can access the attributes, for example:

    def get_context_data(self, **kwargs):
        context = super(ReviewCreate, self).get_context_data(**kwargs)
        context['item'] = self.review_item
        return context

Leave a comment