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

2

In the mapping of my urls.py I use from common functions to views based on classes.

I want to know the difference of calling the view with or without parentheses, considering that if I have the url(r'^$', base_views.index_view) input, put the parentheses when calling the corresponding function (which in the statement receives only an request object ) throws a TypeError with the following message: index_view () missing 1 required positional argument: 'request' .

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

asked by anonymous 12.02.2015 / 02:42

3 answers

4

Basically a view is a function that receives a response (resquest) and returns a response.

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 in 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 and the urls regular expressions 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 URL 3 - Optional extra arguments.

The url () function follows the following pattern.

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

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

For Class Based Views you will need to execute the as_view method for 'transform' your CBV into a view. CBView.as_view () returns a callable.

response = CBView.as_view()(request)

link link link

    
12.02.2015 / 03:18
2

What's going on 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 to less than expected. Now when you omit the parentheses you're not actually calling the method, you're just creating a bound method, which is equivalent to having you write

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

As you can see, we are not calling the view method - we are just passing a function called the view to the url function.

    
12.02.2015 / 03:09
2

When you associate a URL with a view you are not calling the view function - just stating which function should be called when someone visit that URL. In other words, when doing:

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

You're storing somewhere to index_view . This reference will be at some other time (since no request is being made here) by calling an request argument.

If you try to call this function at this time:

  • No parameters will not work, as it expects a request ;
  • With a request parameter it can work, but then it will return a HttpResponse or similar - and this does not help anything at the time the true requests are made (since it is necessary to know what function to call at that time).
  • In the other case, AuthorViews.AuthorView is an object, not a function. Do not just use it in urls.py , since you need to know which function to call during a request, and that's what as_view is for - it returns an appropriate function to be associated with that URL. This is a function that returns another function . So it needs to be called.

    If you do not call it, Django thinks it is what it is view , so try calling it by passing a request . Since it is already a bound method (because doing AuthorView.as_view it "bound" the function to its object), the implicit parameter self is already set. The second parameter - a HttpRequest - is unexpected, hence it claims to have received one more parameter.

        
    12.02.2015 / 03:23