Django Class Based Views, get_absolute_url not working

后端 未结 5 1425
闹比i
闹比i 2021-02-10 17:57

I bought and am Reading the Book Two Scoops of Django:Best Practices for Django 1.5 and in it has a example of Class based views. After this implementation I get the error afte

5条回答
  •  感情败类
    2021-02-10 18:08

    This exception is produced because self.object = None when attempting to redirect after a valid edit. Since the value of self.object is the result of a form.save() call, the most likely reason for this error is that you have overridden the save() method in NonProfitCreateForm, but forgotten to return the saved object.

    The Form.save() method is expected to return the object that was saved and should not be None.

    Your NonProfitCreateForm could be modified as shown below:

    class NonProfitCreateForm(forms.ModelForm):
        ...
        def save(self, *args, **kwargs):
            kwargs['commit']=False
            obj = super(NonProfitCreateForm, self).save(*args, **kwargs)
            if self.request:
                obj.user = self.request.user
                obj.save()
            return obj #<--- Return saved object to caller.
    

    The first two lines of your save() method will create a model instance from the entered form data. But because commit=False, the object will not be saved to the database. If self.request is not present on your form instance, a the returned object will not have a database primary key, and get_absolute_url will still fail.

    So, you want to ensure that a request parameter is always passed to your form when instantiated. This doesn't happen by default, so you need to arrange your view code to instantiate your form with a request parameter.

    Looking through the code for FormMixin you can see that there is a get_form_kwargs function which determines the arguments to pass to any instantiated form. You need to pass request=self.request, so in your view override get_form_kwargs to add the required parameter, something like this:

    class NonProfitCreateView(LoginRequiredMixin,ActionMixin,CreateView):
        model = NonProfit
        action = "created"
        form_class = NonProfitCreateForm
    
        def get_form_kwargs(self):
            # Ensure the current `request` is provided to NonProfitCreateForm.
            kwargs = super(NonProfitCreateView, self).get_form_kwargs()
            kwargs.update({ 'request': self.request })
            return kwargs
    

    It would probably be a better idea to create a subclass of CreateView with the modified get_form_kwargs function, and have your NonProfitCreateView derive from the subclass.

提交回复
热议问题