Django Class Based Views, get_absolute_url not working

后端 未结 5 1370
闹比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.

    0 讨论(0)
  • 2021-02-10 18:09

    You can override your class-based view's get_success_url function. Like this:

    def get_success_url(self):
        return reverse("NonProfit", kwargs={"slug": self.object.slug})  
    
    0 讨论(0)
  • 2021-02-10 18:13

    Solved the problem after reading the first sentence of Austin Phillips:

        def form_valid(self, form):
            article = form.save(commit=False)
            article.author = self.request.user
            self.object = article.save()
            return super().form_valid(form)
    

    the point is the save article.save()'s result back to self.object

    0 讨论(0)
  • 2021-02-10 18:19

    When you use reverse, use the name of the url pattern you wish to reverse.

    You wish to redirect to this url:

    url(
        regex=r'^NonProfit/(?P<slug>[-\w\d]+)/',
        view=NonProfitDetailView.as_view(),
        name='NonProfit'
        )
    

    Therefore your get_absolute_url method should be:

    def get_absolute_url(self):
        return reverse("NonProfit", kwargs={"slug": self.slug})  
    
    0 讨论(0)
  • 2021-02-10 18:28

    Try to remove the @permalink decorator from your get_absolute_url method. It cannot work together with reverse.

    Also, the Django documentation states the following:

    The permalink decorator is no longer recommended. You should use reverse() in the body of your get_absolute_url method instead.

    0 讨论(0)
提交回复
热议问题