user1919
user1919

Reputation: 3938

get_context_data function doesn't return the 'form'

I have the following Django code (django version 1.11) of a form:

class MyDocumentUpdateView(UpdateView):
    """ We extend UpdateView as we need to pass self.object in context as resource """
    model = MyDocument

    def get_context_data(self, **context):

        context[self.context_object_name] = self.object
        context['resource'] = self.object
        #context['form'] = self.get_form() <-- if I uncomment this it works
        return context

class DocumentUpdateView(MyDocumentUpdateView):
    form_class = MyDocumentForm
    def form_valid(self, form):
        doc = form.save(commit=False)
        doc.owner = self.request.user
        updateMyDocument(doc, form)
        return HttpResponseRedirect(
            reverse(
                'mydocs_detail',
                args=(
                    self.object.slug,
                )))

When I run this code, I get an error:

'str' object has no attribute 'fields'

I realized that this error related with the return of the context variable. For some reason the context dictionary does not include the 'form'. As indicated in the documentation:

get_context_data(**kwargs)¶
Calls get_form() and adds the result to the context data with the name ‘form’.

But in my case the context dictionary does not include the 'form'.

If I use the get_form() def, then everything works:

context['form'] = self.get_form()

But this seems like an overkill to me and I want to dig deeper on why this doesn't work.

Then I have noticed that in my case I use:

def get_context_data(self, **context):

instead of:

def get_context_data(self, **kwargs):

So I defined the context as following:

context = super(DocumentUpdateView, self).get_context_data(**kwargs)

But then I get the following error:

maximum recursion depth exceeded

Upvotes: 1

Views: 543

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477607

So I defined the context as following:

context = super(DocumentUpdateView, self).get_context_data(**kwargs)

You used the wrong class, since you call this at the MyDocumentUpdateView level, it should be super(MyDocumentUpdateView, self).get_context_data(**kwargs). So you should implement this as:

class MyDocumentUpdateView(UpdateView):
    """ We extend UpdateView as we need to pass self.object in context as resource """
    model = MyDocument

    def get_context_data(self, **kwargs):
        context = super(MyDocumentUpdateView, self).get_context_data(**kwargs)
        context['resource'] = self.object
        return context

That being said, the self.object is already added to the context, by default as the name of the model (so here that would be mydocument, and you can specify one on your own by specifying a value for the context_object_name attribute, like:

class MyDocumentUpdateView(UpdateView):
    """ We extend UpdateView as we need to pass self.object in context as resource """
    model = MyDocument
    context_object_name = 'resource'

in that case, the context of course has no longer the object stored under its model name (or any other name).

Upvotes: 1

Related Questions