Django Basics
Table of Contents
Install
Install Manually
- Download the latest release from our download page.
- Untar the downloaded file
-
Locate the site-packages directory. To find your system’s site-packages location, execute the following:
python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" echo ABSPATH-TO-DJANGO > SITE-PACKAGES-DIR/django.pth
-
Install
ln -s WORKING-DIR/django-trunk/django/bin/django-admin.py /usr/local/bin/
apt-get
sudo apt-get install python-django
pip
Ubuntu 16.04
sudo apt-get install python-pip
sudo pip install Django==1.8.15
RHEL 7.2
yum install epel-release
yum install python-pip
sudo pip install Django
Writing App
A application will consists of two parts:
- a public site
- an admin site
Create Project
django-admin startproject calc
cd calc
# starting development server at http://0.0.0.0:8000/
python manage.py runserver
python manage.py runserver 0.0.0.0:8080
The development server automatically reloads Python code for each request as needed.
calc/
manage.py
calc/
__init__.py
settings.py
urls.py
wsgi.py
Database Setup
calc/settings.py
- ENGINE
- django.db.backends.sqlite3
- django.db.backends.mysql
- NAME: the name of your database
- os.path.join(BASE_DIR, ‘db.sqlite3’)
CREATE DATABASE database_name;
- USER
- PASSWORD
- HOST
- TIME_ZONE
Some of apps make use of at least one database table, so we need to create the tables in the database before we can use them. To do that, run the following command:
python manage.py migrate
Create App
python manage.py startapp vm
Models
vm/models.py
class Task(models.Model):
tid = models.IntegerField(default = 0)
desc = models.CharField(max_length = 255)
Activate Models
calc/settings.py
INSTALLED_APPS = (
...
'vm',
)
python manage.py makemigrations vm
# sqlmigrate command takes migration names and returns their SQL
python manage.py sqlmigrate vm 0001
# apply changes to the database
python manage.py migrate
# python manage.py shell
from vm.models import Task
task = Task(desc = 'first task')
task.save()
task.id
Admin
python manage.py createsuperuser
vm/admin.py
from .models import Task
admin.site.register(Task)
class TaskAdmin(admin.ModelAdmin):
fields = ['desc']
admin.site.register(Task, TaskAdmin)
Views
vm/views.py
from django.http import HTTPResponse
from django.template import loader
from django.shortcuts import render, get_object_or_404
from .models import Task
def index(request):
tasks = Task.objects.all()
template = loader.get_template('vm/index.html')
context = {
'tasks': tasks,
}
return render(request, 'vm/index.html', {'tasks': tasks})
def task(request, task_id):
task = get_object_or_404(Task, id = task_id)
return HttpResponse(task)
from django.views.generic import View
class TaskView(View):
def get(self, request, *args, **kwargs):
# <view logic>
return HttpResponse('result')
def post(self, request, *args, **kwargs):
# <view logic>
return HttpResponseRedirect('/success/')
vm/urls.py
from django.conf.urls import url
from . import views
from django.contrib.auth.decorators import login_required
urlpatterns = [
url(r'^$', views.index, name = 'index'),
url(r'^(?P<task_id>[0-9]+)/$', login_required(views.TaskVew.as_view), name = 'task'),
]
calc/urls.py
urlpatterns = [
url(r'^vm/', include('vm.urls')),
...
]
calc/settings.py
TEMPLATES = [
{
DIRS': [os.path.join(BASE_DIR, 'templates')],
...
vm/template/vm/index.html
% if tasks %
<ul>
% for task in tasks %
<li><a href='% url "vm:task" task.id%'>. </a></li>
% endfor %
</ul>
% else %
<p>No tasks available right now.</p>
% endif %
Function-based generic views
Eearly on it was recognized that there were common idioms and patterns found in view development. Function-based generic views were introduced to abstract these patterns and ease view development for the common cases.
they covered the simple cases well, there was no way to extend or customize them beyond some simple configuration options, limiting thier usefulness in many real-world applications.
Class-based Views
- organization of code related to specific HTTP methods (GET, POST, etc) can be addressed by separate methods instead of conditional braching
- object oriented techniques such as mixins (multiple inheritance) can be used to factor code into reusable components
more extensible and flexible than their function-based counterparts.
URL Namespace
calc/urls.py
urlpatterns = [
url(r'^vm/', include('vm.urls', namespace = 'vm')),
...
]
Tests
Why
- Tests will save you time
- Tests don’t just identify problems, they prevent them
- Tests make your code more attractive
- Tests help teams work together
TestCase
- a separate TestClass for each model or view
- a separate test method for each set of conditions you want to test
- test method names that describe their function
Running Tests
python manage.py test [vm]
Deploy
Django follows the WSGI spec (PEP 3333), which allows it to run on a variety of server platforms.
Static Files
python manage.py collectstatic
Apache with mod_wsgi
mod_wsgi can operate in two modes:
- an embedded mode
- in embedded mode, mod_wsgi is similar to mod_perl, it embeds Python within Apache and loads Python code into memory when the server starts.
- Code stays in memory throughout the life of an Apache process, which leads to significant performance gains over other server arrangements.
- a daemon mode
- In daemon mode, mod_wsgi spawns an independent daemon process that handles requests.
- The daemon process can run as a different user that the Web server, possibly leading to improved security, and the daemon process can be restarted without restarting the entire Apache Web server, possibly making refreshing your codebase more seamless.
Before going on, make sure you have Apache installed, with the mod_wsgi module activated.
Nginx with uWSGI
# web_uwsgi.ini
[uwsgi]
# Django-related settings
socket = :8000
# the base dir (full path)
chdir = /var/www/blog
# Django's wsgi file
module = web.wsgi
# process-related settings
master = true
# maximum number of worker processes
processes = 4
# with appropriate permissions
chmod-socket = 644
# clear env on exit
vacuum = true
# nginx.conf
http {
server {
listen 80;
server_name blog.oxnz.github.io;
charset UTF-8;
access_log /var/log/nginx/blog_access.log
error_log /var/log/nginx/blog_error.log
client_max_body_size 10M;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8000;
uwsgi_read_timeout 2;
}
location /static {
expires 30d;
autoindex on;
add_header Cache-Control private;
alias /var/www/blog/static;
}
}
}