Function based views in Django

(Comments)

A clear tutorial on getting started with views in Django. Most of the code we see today is class based which makes it difficult for beginners to learn. This tutorial might help them.

Code for this tutorial is available at github.

Lets create a project first and setup urls (skip this section if you are already aware of this setup).

#Create a fresh virtual environment
mkvirtualenv env (On creating, env will be activated automatically. Activate it if you navigate to a new tab.)

#Install Django 1.6.7
pip install Django==1.6.7

#Go to your favourite directory and create a new project
django-admin.py startproject project_template

#Important step. Perform all the operations in this directory. When I say 'project_template' directory in future, it points to the directory present inside this, i.e,. project_directory/project_directory.
cd project_template

Lets create a sample app 'app1'.

python manage.py startapp app1

Add 'app1' to installed apps and syncdb

python manage.py syncdb

Lets include app1.urls in the main urls.py.
Open project_template/urls.py and add this line:

    url(r'^app1/', include('app1.urls')),

Full code in project_template/urls.py

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',   
     url(r'^admin/', include(admin.site.urls)),
     url(r'^app1/', include('app1.urls')),
)

Views:

Create a new file app1/urls.py and add below line.

 #Basic urls structure for an app in a Django project

 from django.conf.urls import patterns, include, url

 urlpatterns = patterns('app1.views',
     url(r'^http_response/$', 'http_response', name='http_response'),
 )

Lets create a view, open app1/views.py and add below code:

from django.shortcuts import render
from django.http import HttpResponse

def http_response(request):
    return HttpResponse("This is a simple response !")

Run the server and open http://localhost:8000/app1/http_response and you will see a simple text as output:

This is a simple response !

We usually dont generate html/text in the views. We use templates.
Create a directory "templates" in the current directory.

mkdir app1/templates/app1

Put all the templates related to the app 'app1' in the above created directory. appname/templates is the default directory that django searches for the templates.

Lets create another view that uses template.

app1/views.py

def simple_template(request):
    return render(request, "app1/simple_template.html", {})

Add this line to app1/urls.py

url(r'^simple_template/$', 'simple_template', name='simple_template'),

Create a template app1/templates/simple_template.html with something like below:

<!DOCTYPE html>
<html>
<head>
    <title>A simple template</title>
</head>
<body>

    <h1>This response is rendered using a simple template.</h1>

</body>
</html>

Then go to http://localhost:8000/app1/simple_template and you can see a simple h1 tag with the above text.

We can also pass context variables to the template. Lets say we want to display the list of all users.

Add a new url in app1/urls.py

    url(r'^users/$', 'users', name='users'),

Then create a view in app1/views.py

from django.contrib.auth.models import User

def users(request):
    users = User.objects.all()
    context = {
        'users': users
    }
    return render(request, "app1/users.html", context)

Create a template app1/templates/app1/users.html with below html:

<!DOCTYPE html>
<html>
<head>
    <title>List of all users</title>
</head>
<body>
    <h1>List of all users</h1>

    {% for user in users %}
        <div class='user'> {{ user.username }} </div>
    {% endfor %}

</body>
</html>

Whats going on?

We created a dictionary named context and passed that context to the template.
In the template we have looped all the users and just printed their usernames.
A string of html is generated from the template with list of all the users and that html is sent as a response i.e. is shown on the webpage.

JSON Response

Lets create a new url in app1/urls.py

url(r'^json_response/', 'json_response', name='json_response'),

Lets write a view in app1/views.py

import json

def json_response(request):
    users = User.objects.all()
    res = {
        'users': {}
    }
    for user in users:
        res['users'][user.username] = {
            'id': user.id,
            'first_name': user.first_name,
            'last_name': user.last_name,
            'username': user.username
        }

    json_res = json.dumps(res)
    return HttpResponse(json_res, mimetype="application/json")

Response

Generally, the browser shows it as a plain string as below:

{"users": {"tim": {"username": "tim", "first_name": "Tim", "last_name": "Tom", "id": 2}, "bob": {"username": "bob", "first_name": "Jim", "last_name": "Bob", "id": 3}, "bhaskar": {"username": "bhaskar", "first_name": "Bhaskar", "last_name": "Rao", "id": 1}}}

But you can make JSON look better and readable in a browser by using extensions. I use JSON Formatter, a useful chrome app. You can find more such apps in chrome webstore.

{
    "users": {
        "tim": {
            "username": "tim",
            "first_name": "Tim",
            "last_name": "Tom",
            "id": 2
        },
        "bob": {
            "username": "bob",
            "first_name": "Jim",
            "last_name": "Bob",
            "id": 3
        },
        "bhaskar": {
            "username": "bhaskar",
            "first_name": "Bhaskar",
            "last_name": "Rao",
            "id": 1
        }
    }
}

What's going on?

We retrieved all the users, created a dictionary and used python standard library JSON(JavaScript Object Notation) to convert dictionary to JSON. We changed the mimetype to application/json so the response is sent as a JSON object instead of sending it as a string.

Comments

Recent Posts

Archive

2021
2020
2019
2018
2017
2016
2015
2014

Tags

Authors

Feeds

RSS / Atom