What’s the difference when calling a function with parentheses and without in.py urls with Django 1.7?

Asked

Viewed 1,207 times

3

In mapping my.py urls I use from common functions to class-based views.

I want to know the difference between calling the view with or without parentheses, given that if I have the input url(r'^$', base_views.index_view), place parentheses when calling the corresponding function (which in the declaration receives only one object request) spear one Typeerror with the following message: index_view() Missing 1 required positional argument: 'request'.

Already at the entrance url(r'^authors/$', AuthorViews.AuthorView.as_view), when I remove the parentheses it throws the same error quoted above with the message: as_view() takes 1 positional argument but 2 Were Given.

I understand that the problem is that when calling one of the functions, the arguments of it are not supplied as in the statement, but, I do not understand how the function url of Django passes these parameters nor why the parentheses make a difference.

3 answers

5


Basically a "view" is a function that takes a request (resquest) and returns a response (re-sponse).

from django.http import HttpResponse
import datetime

def index_view(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

Views are then mapped to Django’s Urlconf. Example below:

from django.conf.urls import patterns, url

from . import views

urlpatterns = patterns('',
    url(r'^$', views.index_view, name='principal'),
    url(r'^autores/$', views.AuthorView.as_view(), name='autores')
    ...
)

Django matches the url the user accesses to regular expressions of the urls in Urlconf, running the "view" that is mapped accordingly.

For this "view" the following arguments are passed: 1 - An instance of Httprequest. 2 - Arguments coming from the URL 3 - Optional extra arguments.

The url() function follows the following pattern.

url(regex, view, kwargs=None, name=None, prefix='')

Django will make the "view" call and pass the arguments correctly. Soon you must pass the callable and not the function call. "index_view" (callable) is different from "index_view(request)".

Regarding Class Based Views you will need to run the as_view method for 'transform' your CBV into a view. Cbview.as_view() returns a callable.

response = CBView.as_view()(request)

https://docs.djangoproject.com/en/1.7/topics/http/urls/#how-Django-processes-a-request https://docs.djangoproject.com/en/1.7/ref/urls/#url https://docs.djangoproject.com/en/1.7/ref/class-based-views/base/#Django.views.Generic.base.View.as_view

  • 1

    It all makes sense now. Had not connected me that the as_view returned a callable, so that’s why we have to execute it: to receive an object the url function will call and send the parameters to it.

3

What’s happening there inside the url function code is something like this:

def url(regex, view):
    request = make_request()
    view(request)

The view parameter is a function that receives a request. The url function passes the request to the view function.

When you call the view method without parameters you get the error you mentioned because you are passing a parameter less than expected. Whereas when you omit the parentheses you’re not actually calling the method, you’re just creating a "bound method", which is equivalent to you having written

url(r'^$', (lambda req: base_views.index_view(req))

As you can see, we’re not calling the view method - we’re just passing to the url function a function that calls the view.

3

When you associate a URL to a view you are not calling the function of view - only indicating which function should be called when someone visits that URL. In other words, when doing:

url(r'^$', base_views.index_view)

Are you storing, somewhere, a reference to index_view. This reference will be at some other time (because here no request is being made) calling passing as argument one request.

If you try to call this function at this time:

  1. Without parameters it won’t work because she’s expecting a request;
  2. With a type parameter request it may work, but then it will return a HttpResponse or similar - and this does not help at all when the true requests are made (because it is necessary to know what function to call at that time).

In the other case, AuthorViews.AuthorView is an object, not a function. It is not enough to use itself in urls.py, because you need to know what function to call during a request, and that’s what the as_view - it returns an appropriate function to be associated with that URL. It is a function that returns another function. That’s why you need to be called.

If you don’t call, Django thinks she is that it is the view, then try calling her by passing a request. As she is already one bound method (because in doing AuthorView.as_view it "connected" the function to its object), the implicit parameter self is already set. The second parameter - a HttpRequest - is unexpected, hence he claims to have received an additional parameter.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.