10

I am using a Django CreateView and I wanted to set the success_url to the same view so that when the form is posted, it displays the same page and I can display the created object in addition to the form in case you want to add a new one. However, self.object is None because of this in BaseCreateView:

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

I am concluding that a CreateView is not made to be redisplayed after success?

Michael
  • 8,357
  • 20
  • 58
  • 86
  • You could use a [formset](https://docs.djangoproject.com/en/dev/topics/forms/formsets/) instead so that the user can add numerous objects via the same form before sumbitting. There is a good library that adds class based views for this sort of functionality called [`django-extra-views`](https://github.com/AndrewIngram/django-extra-views) – Timmy O'Mahony Oct 25 '14 at 15:39

3 Answers3

14

I was looking at the wrong place.

I have to override form_valid to not redirect to the URL (return HttpResponseRedirect(self.get_success_url()))

 def form_valid(self, form):
        self.object = form.save()

        # Does not redirect if valid
        #return HttpResponseRedirect(self.get_success_url())

        # Render the template
        # get_context_data populates object in the context 
        # or you also get it with the name you want if you define context_object_name in the class
        return self.render_to_response(self.get_context_data(form=form))
Michael
  • 8,357
  • 20
  • 58
  • 86
2

I don't think you need the object being created to redirect to the same URL of the view. I'd use reverse:

class MyModelCreate(CreateView):
    model = MyModel
    success_url = reverse('path.to.your.create.view')
dukebody
  • 7,025
  • 3
  • 36
  • 61
  • Yes, that is what I do but then in the template I expected `self.object` to have the created object but it is `None` since it is set to None in the post method. – Michael Oct 25 '14 at 15:45
  • 1
    When you redirect your user to the URL of the form after success, the new view won't have any reference to the object just created because it only holds a reference to the object being created. If you want to display the last object created you will have to get hold of it manually, for example with a custom get_success_url method (see [doc](https://github.com/django/django/blob/731f313d604a6cc141f36d8a1ba9a75790c70154/django/views/generic/edit.py#L128) ) – dukebody Oct 25 '14 at 15:59
  • I was actually looking at the wrong place, I actually have to override form_valid. I added the answer to my question. – Michael Oct 25 '14 at 20:41
  • 1
    I think this solution is more neat. In my case I had to override get_success_url() because Django web server was complaining of circular import on startup when the reverse() was directly assigned to success_url. – user3748764 Feb 17 '20 at 15:56
  • @user3748764 To prevent circular import errors you can use [reverse_lazy](https://docs.djangoproject.com/en/stable/ref/urlresolvers/#reverse-lazy). – djvg Sep 06 '22 at 08:12
1

So it's 6 years later and I bumped into this problem while working on my project. In case anyone also faces this problem too in the near future here is a simple and easy fix but might not be recommended but it got the job done for me.

By the way I like using ClassBasedViews.

In your views.py file

class MyMode(CreateView):
    model = my_model
    success_url = '/path-to-webpage/'
     

So what I basically did was to hard-code in the path to the web-page under the success_url and that got the problem solved. This works when you are not planning to change your URLpatterns anytime otherwise you will also have to change the URL in the views.py file too.

Surveyor Jr
  • 346
  • 2
  • 12