django
- Overview
- URLS and Views
- Templates
- Models
- Templates Revisited
- Miscellaneous
Overview
- Django is a framework designed to make common web development tasks fast and easy.
- It follows the MVC architectural pattern
URLS and Views
Starting a project
- Start a test project
django-admin.py startproject test_project
cd test_project
python manage.py startapp test_app1
URLS and VIEWS
- Below is a sample url regex for home page view:
-
URLS: url(r'^test_app1/', include('test_project.test_app1.urls')), test_app1/URLS: url(r'^/?$', 'test_app1.views.home', name='home'),
- Below is the controller view for home page :
from django.shortcuts import HttpResponse, render_to_response def home(request): return HttpResponse("Home Page!") # return render_to_response('test_app1/home.html', {'developer_name':'vivek'})
TEMPLATES
- Templates are the actual views in MVC framework.
- A template is simply a text file
- A template contains variables , which get replaced with values when the template is evaluated, and tags , which control the logic of the template
-
Any text surrounded by a pair of braces (e.g., {{ person_name }} ) is a variable . This means “insert the value of the variable with the given name.”
-
Any text that’s surrounded by curly braces and percent signs (e.g., {% if is_experienced %} ) is a template tag .
Templates
- Lets create a template for home page
-
mkdir -p templates/test_app1 <html> <body> This page is developed by {{ developer_name }}! </body> </html>
MODELS
- A model is the single, definitive source of information about your data
- It contains the essential fields and behaviors of the data you’re storing
- Each model is a Python class that subclasses django.db.models.Model.
- Add DB credentials to settings.py
- Create model
class Developer(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
experience = models.IntegerField()
python manage.py syncdb
from test_app1 import models
models.Developer(name='vivek', experience=3).save()
TEMPLATES REVISTED
A website has many common features that spread across various pages or the whole website. In-order to avoid template duplication, django provides the following template inheritance logic: The first step is to define a base template – a skeleton of your page that child templates will later fill in.
<html lang="en"> <head><title>{% block title %}{% endblock %}</title> </head> <body> <h1>My first site</h1> {% block content %}{% endblock %} {% block footer %} <hr> <p>Thanks for visiting my site.</p> {% endblock %} </body> </html>
CHILD TEMPLATE
{% extends "base.html" %}
{% block title %}Home Page{% endblock %}
{% block content %}
<p>>This page is developed by {{ developer_name }}!</p>
{% endblock %}
- This tag allows you to include the contents of another template.
{% include "inclusions/disclaimer.html" %}
- Inclusion Template:
mkdir -p templates/inclusions
disclaimer.html:
<p>©Global Analytics</p>
TEMPLATE TAGS
- Add model logic to controller:
-
from django.shortcuts import HttpResponse, render_to_response from test_app1.models import Developer def home(request): developers = Developer.objects.all() return render_to_response('test_app1/home.html', {'developers':developers})
<table>
<tr>
<th>Developer Name</th>
<th>Designation</th>
</tr>
{% for developer in developers %}
<tr>
<td>{{ developer.name }}</td>
<td>
{% if developer.experience > 2 %}
Senior Developer
{% else %}
Developer
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<p>This page is developed by {{ developers.0.name }}!</p>
- You can even create custom template tags
Middlewares
- On occasion, you’ll need to run a piece of code on each and every request that Django handles. This code might need to modify the request before the view handles it, it might need to log information about the request for debugging purposes, and so forth
- Various django middlewares:
- process_request() is called on each request, before Django decides which view to execute.
- process_view() is called just before Django calls the view
- process_template_response() is called before context from view is rendered on the template
- process_response() is called on all responses before they’re returned to the browser.
- process_exception is called on all exceptions raised from view. It wont be called when no exception is raised.
- To activate a middleware component, add it to the MIDDLEWARE_CLASSES tuple in your settings module.
MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', )
Middlewares
- test_middleware.py:
-
import uuid class TestMiddleware(object): def process_request(self, request): unique_id = request.COOKIES.get(\ 'unique_id', str(uuid.uuid4())) request.__setattr__('unique_id', unique_id)
- views.py:
-
return render_to_response('test_app1/home.html', \ {'developers':developers, 'unique_id':request.unique_id})
- home.html:
-
<p>Your unique id is: {{ unique_id }}</p>
Context Processors
Context processors allows us to add common variables to the context dictionary before getting passed to the template create a context_processors.py file in the Django project folder:
def extra_context(request):
"""
Add variables that you would like accessed across all pages.
"""
context_extras = {}
context_extras['unique_id'] = request.unique_id
return context_extras
- And on the settings file under TEMPLATE_CONTEXT_PROCESSORS added:
'test_project.context_processors.extra_context'
from django.template import RequestContext
return render_to_response('test_app1/home.html', {'developers':developers}, context_instance=RequestContext(request))
Class Based Views
from test_app1.views import AddDeveloper
url(r'^add/?$', AddDeveloper.as_view(), name='add'),
views:
class AddDeveloper(View):
def get(self, *args, **kwargs):
return render_to_response('test_app1/add.html', {}, context_instance=RequestContext(self.request))
def post(self, *args, **kwargs):
print self.request.POST
if self.is_valid():
Developer(name=self.request.POST['developer_name'], experience=self.request.POST['experience']).save()
return HttpResponseRedirect("/test_app1/")
else:
return render_to_response('test_app1/add.html', {'errors':self.errors}, context_instance=RequestContext(self.request))
def is_valid(self):
self.errors = {}
if not self.request.POST.get('developer_name'):
self.errors['developer_name'] = 'Please enter developer name'
if not self.request.POST.get('experience'):
self.errors['experience'] = 'Please select your experience'
return False if self.errors else True
Add developer Template
<style> .error { color: red;} </style>
<form method="post" > {% csrf_token %} <label>Dev Name</label> {% if errors.developer_name %} <span class="error">{{ errors.developer_name }}</span> {% endif %}
<input type="text" name="developer_name" /> <br> <br> <label>Experience</label> {% if errors.experience %} <span class="error">{{ errors.experience }}</span> {% endif %}
<select name="experience"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> <input type="submit" value="submit" name="submit" /> </form>
Forms
- Django provides a form library to avoid the previous issues
-
create forms.py inside the application
-
from django import forms EXPERIENCE = ( ('1','1',), ('2','2',), ('3','3',), ) class DeveloperForm(forms.Form): name = forms.CharField(required=True, label='Developer Name') experience = forms.ChoiceField(choices=EXPERIENCE, widget=forms.Select(attrs={'data-field': '1'}), required=True)
- Now lets write the controller logic:
class AddDeveloper(View): def get(self, *args, **kwargs): form = DeveloperForm() return render_to_response('test_app1/add.html', {'form':form}, context_instance=RequestContext(self.request)) def post(self, *args, **kwargs): form = DeveloperForm(self.request.POST) if form.is_valid(): Developer(name=self.request.POST['developer_name'], experience=self.request.POST['experience']).save() return HttpResponseRedirect("/test_app1/") else: return render_to_response('test_app1/add.html', {'form':form}, context_instance=RequestContext(self.request))
- Now the template:
<style>
.error {
color: red;
}
</style>
<form method="post" >
{% csrf_token %}
<span class="error">{{form.name.errors.as_text }}</span><br/>
{{ form.name.label }}
{{ form.name }}
<br>
<br>
{{ form.experience.label }}
{{ form.experience }}
<br>
<br>
<input type="submit" value="submit" name="submit" />
</form>
- You can also add custom validations
def clean_name(self):
name = self.cleaned_data['name']
num_words = len(name.split())
if num_words < 2:
raise forms.ValidationError("Enter first & last name")
return name
Do's & Dont's
- Do not write all patterns in main urls
- Do not write the whole logic in your views
- Try using class based views
- Always catch exceptions
# BAD! def ua_display_bad(request): ua = request.META['HTTP_USER_AGENT'] # Might raise KeyError! return HttpResponse("Your browser is %s" % ua) # GOOD (VERSION 1) def ua_display_good1(request):
#OR ua = request.META.get('HTTP_USER_AGENT', 'unknown')
try: ua = request.META['HTTP_USER_AGENT'] except KeyError: ua = 'unknown' return HttpResponse("Your browser is %s" % ua)
-
Explore more on generic CBV's, custom template tags, model managers, mixins & forms
Django Basics
By vivek soundrapandi
Django Basics
A practical session on django with basics to advanced concepts
- 4,953