Codejoy
Codejoy

Reputation: 3806

How to pass created object in createview right to updateview in django

I have a createview view in my django app:

### Create a Group 
class GroupCreateView(CreateView): # {{{
  model = Group
  form_class = GroupForm
  template_name = 'ipaswdb/group/group_form.html'
  success_url = '/ipaswdb/group/'

  def get_context_data(self, **kwargs):
    ..do stuff..

  def post(self, request, *args, **kwargs):
    if self.request.POST.has_key('submit'):
      form = GroupForm(request.POST)
      if form.is_valid():

        ### Save the group
        self.object = form.save()


        #### Adding a provider forces a default location
        #if form['default_location'].value() == True:

        ### We are forcing the creation of a GroupLocation when a new Group is created 
        gl = GroupLocation(
          group = Group.objects.get(pk=self.object.id),

          doing_business_as = self.object.group_name,
          default_group_location = True,

          mailing_address_line_one = self.object.mailing_address_line_one,
          mailing_address_line_two = "",
          mailing_city = self.object.mailing_city,
          mailing_state = self.object.mailing_state,
          mailing_zip_code = self.object.mailing_zip_code,
          mailing_phone = self.object.mailing_phone,
          mailing_fax = self.object.mailing_fax,

          contact = self.object.group_contact,

          physical_address_line_one = self.object.billing_address_line_one,
          physical_address_line_two = "",
          physical_city = self.object.billing_city,
          physical_state = self.object.billing_state,
          physical_zip_code = self.object.billing_zip_code,
          physical_phone = self.object.billing_phone,
          physical_fax = self.object.billing_fax,

        ) 
        gl.save()
        new_grploc = gl
        self.object.default_location_id = new_grploc.id
        self.object.save()


        new_group_id = self.object.id
        new_grploc_id = new_grploc.id

        ### Now check the list of providers to see what has changed
        print "group_add_provider: ",
        print request.POST.getlist('group_add_provider')

        add_providers = request.POST.getlist('group_add_provider')

        if add_providers:
          for pro in add_providers:
            add_grploc = GroupLocationProvider(
                             grouplocation=GroupLocation.objects.get(pk=new_grploc_id),
                             provider=Provider.objects.get(pk=pro)
                         )
            add_grploc.save()


        ### Now check the list of insurances to see what has changed
        print "group_add_insurance: ",
        print request.POST.getlist('group_add_insurance')

        add_insurances = request.POST.getlist('group_add_insurance')

        if add_insurances:
          for ins in add_insurances:
            add_grpins = GroupInsurance(
                             group=Group.objects.get(pk=new_group_id),
                             insurance=Insurance.objects.get(pk=ins)
                         )
            add_grpins.save()

       #return HttpResponseRedirect(self.get_success_url())  #how it used to work, just fine but would go back to my list of groups
      return HttpResponseRedirect('ipaswdb:group_detail', self.object.pk)  #want it to call my edit view here.

My Url Patterns

app_name = 'ipaswdb'

urlpatterns = [
      url(r'^group/(?P<pk>[0-9]+)/$', GroupUpdateView.as_view(), name='group_detail'),
      url(r'^group/add/$', GroupCreateView.as_view(), name='group_add'), 
      ..etc..

Got an error but I feel I am closer?

DisallowedRedirect at /ipaswdb/group/add/
Unsafe redirect to URL with protocol 'ipaswdb'

I really want to load the page with the created object but as an updateview Anyway to do this from the create view?

Upvotes: 0

Views: 960

Answers (1)

Daniel Hepper
Daniel Hepper

Reputation: 29977

It is highly recommended to return a redirect request from a successful POST request. Otherwise a user might accidentally create multiple objects by reloading the page. Something like this:

from django.shortcuts import redirect

...

return redirect('name-of-update-url', pk=obj.pk)

If you really do not want to use a redirect, it is a bit more involved. Class based views are not meant to be called directly. The as_view method you use in your urls.py creates a wrapper function which instantiates the class and calls dispatch, which selects the right handler method (get/post/...). But you can't use as_view, because you have a POST request, but probably want to call the get method.

So you have to create an instance of your UpdateView and directly call its get method. With a standard UpdateView, can try something like this:

class GroupCreateView(CreateView):
    ...
    def post(self, request, *args, **kwargs):
        ...
        obj = ... # create your object
        update_view = UpdateView()
        update_view.request = self.request
        update_view.args = []
        update_view.kwargs = {'pk': obj.pk}
        return update_view.get(self.request)

If you heavily customized your UpdateView, you might have to adapt this.

My go-to resource how Django's class-based views look under the hood is https://ccbv.co.uk

Upvotes: 1

Related Questions