My personal repository to learn Django from DjangoProject.com
(note: used as a "container" environment for the project)
sudo pip install virtualenv
virtualenv directory/name
To use Python3 instead:
virtualenv -p python3 directory/name
source bin/activate
deactivate
notice how, while activated, python and pip point to the packages defined inside the environment:
With virtualenv
activated, run the following command:
pip install Django
Tutorial Reference: https://docs.djangoproject.com/en/1.11/intro/tutorial01/
django-admin startproject nameOfYourSite
python manage.py runserver
from: https://docs.djangoproject.com/en/1.11/intro/tutorial02/#activating-models
The 3-Step Guide to Model Changes
- change your models (in
models.py
) - run
python manage.py makemigrations
to create migration for those changes - run
python manage.py migrate
to apply those changes to the databases
Rather than calling python
in our virtualenv
, we use
python manage.py shell
manage.py
will set "the DJANGO_SETTINGS_MODULE environment variable, which gives Django the Python import path to your mysite/settings.py file."
"A URLConf
maps URL patterns to views."
See djnago.urls
.
From: Django >> #write-views-that-actually-do-something
(Important) Each view must be responsible for at least 1 of 2 things:
- returning an
HttpResponse
object - raising an HTTP 404 exception
The rest, you can determine...
- read database records
- use Django's template system or a 3rd party's
- generate a PDF, XML, ZIP, etc.
- execute Python libraries
From: Django >> #a-shortcut-render
Motivation: It is very common to perform the following idiom:
from django.http import HttpResponse
from django.template import loader
def view_name(request):
# (1) load the template
template = loader.get_template('app_name/index.html')
# (2) fill the context dictionary
context = {
'context_dictionary': context_object,
}
# (3) return the required HttpResponse
return HttpResponse(template.render(context, request))
Shortcut: Django provides the following as a Shortcut
from django.shortcuts import render
def view_name(request):
# (1) fill the context
context = {'context_dictionary': context_object}
# (2) render loads the response and satisfies the HttpResponse
return render(request, 'app_name/index.html', context)
From: Django >> #a-shortcut-get-object-or-404
Motivation: It is very common to perform the following idiom; in addition, not using the subsequent shortcut couples the view and model layers of Django architecture which is ill-advised:
from django.http import Http404
from django.shortcuts import render
def view_name(request):
# (1) perform a get()
try:
var_name = Object.objects.get(<object_key>)
# (2) if get() is undefined, raise an exception
except Object.DoesNotExist:
raise Http404("<Object> does not exist")
# (3) render a response
return render(request, 'app_name/view_name.html', {'var_name': var_name})
Shortcut: Django provides the following as a Shortcut
from django.shortcuts import get_object_or_404, render
def view_name(request):
# (1) perform the try/except idiom
var_name = get_object_or_404(<object>)
# (2) render a response
return render(request, 'app_name/view_name.html', {'var_name': var_name})
For some of the views defined in the tutorial, the author indicates that Django has generic views that can perform the same action.
Specifically, DetailView
and ListView
can be called by extending the django.views.generic
module.
The following is an example of using these generic views with the conventional naming syntax:
# <app_name>/views.py
from django.views import generic
class IndexView(generic.ListView):
template_name = '<app_name>/<model_name>_<template_name>.html'
# overrides the automatically generated context
context_object_name = '<context_object_name>'
def get_queryset(self):
"""Return the last five published <Objects>."""
return <Object>.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = <model_name>
template_name = '<app_name>/<model_name>_<template_name>.html'
Note: Django will automatically search for a directory called `templates` in each application context.
(Important) Django chooses application templates by order. To prevent confusion, it is convention to "namespace" your templates by "putting those templates inside another directory named for the application itself".
- <application_name>
- ...
templates
- <appliaction_name> (this is namespacing)
- ...
- ...
- <appliaction_name> (this is namespacing)
- ...
(Important) To prevent confusion in URLs, defining the app_name
variable in urls.py
of your Django application is convention:
In your urls.py
file:
# <app_name>/urls.py
from django.conf.urls import url
from . import views
app_name = '<app_name>'
urlpatterns = [
# ...
url(<regexp>, views.<view_name>, name='<view_name>'),
# ...
]
In your templates/<app_name>/<template_name>.html
file:
<!-- <app_name>/templates/<app_name>/<template_name>.html -->
<a href="{% url '<app_name>:<view_name>' %}" />
- Django's testing system will automatically search for any file whose name begins with "test".
- Examples: "tests.py", "test_ui.py"
- Check code coverage to spot untested or dead code
python manage.py test <app_name>
- use a separate
TestCase
for eachmodel
orview
- use a separate test method for each set of conditions you want to test
- use test method names that describe their function
- If you can’t test a piece of code, that code should be refactored or removed
- Selenium
- supported with Django's
LiveServerTestCase
- supported with Django's
coverage.py
(documentation)- Django integration here
django.contrib.staticfiles
>> collects static files from each application to a single location for production serving- similar to what
WebPack
does for NodeJS
- similar to what
- Django automatically searches for static files from a directory named
static
- the directory
static
should follow the same namespacing convention discussed in Templates
In your template file, add the following to the top:
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />
Caution: the {% static %}
template tag in href
generates the absoulte URL of the static .css
file you are importing. Note, that since stylesheets are not generated by Django, relative paths must be used to link static files between each other.
- it's possible to change
STATIC_URL
(used by{% static %}
) to prevent modifying paths in your static files.
- Deploying static files
staticfiles
documentation- how to use
staticfiles
Anytime you change the admin options for a model:
- create a model class
- convention:
class <model_name>Admin(admin.ModelAdmin):
- convention:
- pass it as a subsequent argument to
admin.site.register()
Packaging Tool: setuptools
(documentation)
With virtualenv
activated...
pip install setuptools
- outside the project directory, make a new directory to hold the application
- prepend your app with
django-
to designate the Python package as Django specific
- prepend your app with
- copy the Django app directory from the project directory to the new directory outside the project directory
- create a
README.rst
file - create a
LICENSE
file - create a
setup.py
file
Example content:
import os
from setuptools import find_packages, setup
with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
README = readme.read()
# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
setup(
name='django-polls',
version='0.1',
packages=find_packages(),
include_package_data=True,
license='BSD License', # example license
description='A simple Django app to conduct Web-based polls.',
long_description=README,
url='https://www.example.com/',
author='Your Name',
author_email='[email protected]',
classifiers=[
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: X.Y', # replace "X.Y" as appropriate
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License', # example license
'Operating System :: OS Independent',
'Programming Language :: Python',
# Replace these appropriately if you are stuck on Python 2.
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
)
- make a
docs
directory - create a
MANIFEST.in
file
Example content:
include LICENSE
include README.rst
recursive-include <app_name>/static *
recursive-include <app_name>/templates *
recursive-include docs *
-
Your folder structure should resemble the following:
- <parent_directory>/
- bin/
- django-<app_name>/ <-- this is your new application package
- docs/
- <app_name>/ <-- this is your copied application
- LICENSE
- MANIFEST.in
- README.rst
- setup.py
- include/
- lib/
- <django_project_name>/
- db.sqlite3
- manage.py
- <django_project_name>/
- <app_name>/ <-- copy this!
- <parent_directory>/
-
Build the package from with an activated
virtualenv
in the application directory
python setup.py sdist
- Distribute the generated
.tar.gz
file in the new/django-<app_name>/dist
directory