2005-07-15 23:57:46 +08:00
|
|
|
==================
|
|
|
|
Django at a glance
|
|
|
|
==================
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
Because Django was developed in a fast-paced newsroom environment, it was
|
2021-07-23 14:48:16 +08:00
|
|
|
designed to make common web development tasks fast and easy. Here's an informal
|
|
|
|
overview of how to write a database-driven web app with Django.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
The goal of this document is to give you enough technical specifics to
|
|
|
|
understand how Django works, but this isn't intended to be a tutorial or
|
2008-08-24 06:25:40 +08:00
|
|
|
reference -- but we've got both! When you're ready to start a project, you can
|
2010-08-20 03:27:44 +08:00
|
|
|
:doc:`start with the tutorial </intro/tutorial01>` or :doc:`dive right into more
|
|
|
|
detailed documentation </topics/index>`.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
Design your model
|
|
|
|
=================
|
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
Although you can use Django without a database, it comes with an
|
2013-05-20 00:06:35 +08:00
|
|
|
`object-relational mapper`_ in which you describe your database layout in Python
|
2006-05-02 09:31:56 +08:00
|
|
|
code.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2015-08-08 18:02:32 +08:00
|
|
|
.. _object-relational mapper: https://en.wikipedia.org/wiki/Object-relational_mapping
|
2013-05-20 00:06:35 +08:00
|
|
|
|
2010-08-20 03:27:44 +08:00
|
|
|
The :doc:`data-model syntax </topics/db/models>` offers many rich ways of
|
2013-12-31 01:15:49 +08:00
|
|
|
representing your models -- so far, it's been solving many years' worth of
|
2014-09-06 19:31:36 +08:00
|
|
|
database-schema problems. Here's a quick example:
|
|
|
|
|
2018-09-11 01:00:34 +08:00
|
|
|
.. code-block:: python
|
2022-05-31 13:40:54 +08:00
|
|
|
:caption: ``mysite/news/models.py``
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2013-05-20 00:06:35 +08:00
|
|
|
from django.db import models
|
2013-05-18 19:34:29 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
class Reporter(models.Model):
|
2007-08-05 13:14:46 +08:00
|
|
|
full_name = models.CharField(max_length=70)
|
2006-05-02 09:31:56 +08:00
|
|
|
|
2017-01-19 00:51:29 +08:00
|
|
|
def __str__(self):
|
2005-07-15 23:31:20 +08:00
|
|
|
return self.full_name
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
class Article(models.Model):
|
2012-09-08 23:00:04 +08:00
|
|
|
pub_date = models.DateField()
|
2007-08-05 13:14:46 +08:00
|
|
|
headline = models.CharField(max_length=200)
|
2008-07-30 18:08:12 +08:00
|
|
|
content = models.TextField()
|
2015-07-22 22:43:21 +08:00
|
|
|
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2017-01-19 00:51:29 +08:00
|
|
|
def __str__(self):
|
2005-07-15 23:31:20 +08:00
|
|
|
return self.headline
|
|
|
|
|
|
|
|
Install it
|
|
|
|
==========
|
|
|
|
|
2019-07-14 03:01:07 +08:00
|
|
|
Next, run the Django command-line utilities to create the database tables
|
2008-08-24 06:25:40 +08:00
|
|
|
automatically:
|
|
|
|
|
2018-01-21 01:38:48 +08:00
|
|
|
.. console::
|
2006-05-02 09:31:56 +08:00
|
|
|
|
2019-07-14 03:01:07 +08:00
|
|
|
$ python manage.py makemigrations
|
2013-09-18 22:35:41 +08:00
|
|
|
$ python manage.py migrate
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2019-07-14 03:01:07 +08:00
|
|
|
The :djadmin:`makemigrations` command looks at all your available models and
|
|
|
|
creates migrations for whichever tables don't already exist. :djadmin:`migrate`
|
|
|
|
runs the migrations and creates tables in your database, as well as optionally
|
|
|
|
providing :doc:`much richer schema control </topics/migrations>`.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
Enjoy the free API
|
|
|
|
==================
|
|
|
|
|
2013-05-20 00:06:35 +08:00
|
|
|
With that, you've got a free, and rich, :doc:`Python API </topics/db/queries>`
|
|
|
|
to access your data. The API is created on the fly, no code generation
|
2019-12-23 21:47:13 +08:00
|
|
|
necessary::
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2010-10-19 08:10:22 +08:00
|
|
|
# Import the models we created from our "news" app
|
2018-05-13 01:37:42 +08:00
|
|
|
>>> from news.models import Article, Reporter
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# No reporters are in the system yet.
|
2006-05-02 09:31:56 +08:00
|
|
|
>>> Reporter.objects.all()
|
2015-10-06 07:07:34 +08:00
|
|
|
<QuerySet []>
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Create a new Reporter.
|
2006-05-02 09:31:56 +08:00
|
|
|
>>> r = Reporter(full_name='John Smith')
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Save the object into the database. You have to call save() explicitly.
|
|
|
|
>>> r.save()
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Now it has an ID.
|
|
|
|
>>> r.id
|
|
|
|
1
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Now the new reporter is in the database.
|
2006-05-02 09:31:56 +08:00
|
|
|
>>> Reporter.objects.all()
|
2015-10-06 07:07:34 +08:00
|
|
|
<QuerySet [<Reporter: John Smith>]>
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Fields are represented as attributes on the Python object.
|
|
|
|
>>> r.full_name
|
|
|
|
'John Smith'
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
# Django provides a rich database lookup API.
|
|
|
|
>>> Reporter.objects.get(id=1)
|
2008-08-28 21:40:20 +08:00
|
|
|
<Reporter: John Smith>
|
2006-05-02 09:31:56 +08:00
|
|
|
>>> Reporter.objects.get(full_name__startswith='John')
|
2008-08-28 21:40:20 +08:00
|
|
|
<Reporter: John Smith>
|
2006-05-02 09:31:56 +08:00
|
|
|
>>> Reporter.objects.get(full_name__contains='mith')
|
2008-08-28 21:40:20 +08:00
|
|
|
<Reporter: John Smith>
|
2006-05-02 09:31:56 +08:00
|
|
|
>>> Reporter.objects.get(id=2)
|
2005-07-15 23:31:20 +08:00
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
2014-04-16 20:35:17 +08:00
|
|
|
DoesNotExist: Reporter matching query does not exist.
|
2005-07-27 00:11:43 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Create an article.
|
2012-09-08 23:00:04 +08:00
|
|
|
>>> from datetime import date
|
|
|
|
>>> a = Article(pub_date=date.today(), headline='Django is cool',
|
2008-07-30 18:08:12 +08:00
|
|
|
... content='Yeah.', reporter=r)
|
2005-07-15 23:31:20 +08:00
|
|
|
>>> a.save()
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Now the article is in the database.
|
2006-05-02 09:31:56 +08:00
|
|
|
>>> Article.objects.all()
|
2015-10-06 07:07:34 +08:00
|
|
|
<QuerySet [<Article: Django is cool>]>
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Article objects get API access to related Reporter objects.
|
2006-05-02 09:31:56 +08:00
|
|
|
>>> r = a.reporter
|
2005-07-15 23:31:20 +08:00
|
|
|
>>> r.full_name
|
|
|
|
'John Smith'
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# And vice versa: Reporter objects get API access to Article objects.
|
2006-05-02 09:31:56 +08:00
|
|
|
>>> r.article_set.all()
|
2015-10-06 07:07:34 +08:00
|
|
|
<QuerySet [<Article: Django is cool>]>
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
# The API follows relationships as far as you need, performing efficient
|
|
|
|
# JOINs for you behind the scenes.
|
|
|
|
# This finds all articles by a reporter whose name starts with "John".
|
2013-12-31 01:15:49 +08:00
|
|
|
>>> Article.objects.filter(reporter__full_name__startswith='John')
|
2015-10-06 07:07:34 +08:00
|
|
|
<QuerySet [<Article: Django is cool>]>
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Change an object by altering its attributes and calling save().
|
|
|
|
>>> r.full_name = 'Billy Goat'
|
|
|
|
>>> r.save()
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
# Delete an object with delete().
|
|
|
|
>>> r.delete()
|
|
|
|
|
2007-08-07 10:33:11 +08:00
|
|
|
A dynamic admin interface: it's not just scaffolding -- it's the whole house
|
2005-07-15 23:31:20 +08:00
|
|
|
============================================================================
|
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
Once your models are defined, Django can automatically create a professional,
|
2013-05-20 00:06:35 +08:00
|
|
|
production ready :doc:`administrative interface </ref/contrib/admin/index>` --
|
2019-06-17 22:54:55 +08:00
|
|
|
a website that lets authenticated users add, change and delete objects. The
|
|
|
|
only step required is to register your model in the admin site:
|
2008-08-26 15:11:14 +08:00
|
|
|
|
2018-09-11 01:00:34 +08:00
|
|
|
.. code-block:: python
|
2022-05-31 13:40:54 +08:00
|
|
|
:caption: ``mysite/news/models.py``
|
2008-08-26 15:11:14 +08:00
|
|
|
|
|
|
|
from django.db import models
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
class Article(models.Model):
|
2012-09-08 23:00:04 +08:00
|
|
|
pub_date = models.DateField()
|
2007-08-05 13:14:46 +08:00
|
|
|
headline = models.CharField(max_length=200)
|
2008-07-30 18:08:12 +08:00
|
|
|
content = models.TextField()
|
2015-07-22 22:43:21 +08:00
|
|
|
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
|
2009-06-18 21:32:12 +08:00
|
|
|
|
2018-09-11 01:00:34 +08:00
|
|
|
.. code-block:: python
|
2022-05-31 13:40:54 +08:00
|
|
|
:caption: ``mysite/news/admin.py``
|
2008-08-26 15:11:14 +08:00
|
|
|
|
|
|
|
from django.contrib import admin
|
|
|
|
|
2014-09-06 19:31:36 +08:00
|
|
|
from . import models
|
|
|
|
|
2008-08-26 15:11:14 +08:00
|
|
|
admin.site.register(models.Article)
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
The philosophy here is that your site is edited by a staff, or a client, or
|
|
|
|
maybe just you -- and you don't want to have to deal with creating backend
|
2019-06-17 22:54:55 +08:00
|
|
|
interfaces only to manage content.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
One typical workflow in creating Django apps is to create models and get the
|
|
|
|
admin sites up and running as fast as possible, so your staff (or clients) can
|
|
|
|
start populating data. Then, develop the way data is presented to the public.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
Design your URLs
|
2005-07-16 04:53:17 +08:00
|
|
|
================
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2021-07-23 14:48:16 +08:00
|
|
|
A clean, elegant URL scheme is an important detail in a high-quality web
|
2006-05-02 09:31:56 +08:00
|
|
|
application. Django encourages beautiful URL design and doesn't put any cruft
|
|
|
|
in URLs, like ``.php`` or ``.asp``.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2010-08-20 03:27:44 +08:00
|
|
|
To design URLs for an app, you create a Python module called a :doc:`URLconf
|
2019-06-17 22:54:55 +08:00
|
|
|
</topics/http/urls>`. A table of contents for your app, it contains a mapping
|
|
|
|
between URL patterns and Python callback functions. URLconfs also serve to
|
|
|
|
decouple URLs from Python code.
|
2006-05-02 09:31:56 +08:00
|
|
|
|
2006-08-24 11:37:34 +08:00
|
|
|
Here's what a URLconf might look like for the ``Reporter``/``Article``
|
2014-09-06 19:31:36 +08:00
|
|
|
example above:
|
|
|
|
|
2018-09-11 01:00:34 +08:00
|
|
|
.. code-block:: python
|
2022-05-31 13:40:54 +08:00
|
|
|
:caption: ``mysite/news/urls.py``
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2016-10-21 01:29:04 +08:00
|
|
|
from django.urls import path
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2014-08-12 22:54:42 +08:00
|
|
|
from . import views
|
|
|
|
|
2014-04-02 08:46:34 +08:00
|
|
|
urlpatterns = [
|
2016-10-21 01:29:04 +08:00
|
|
|
path('articles/<int:year>/', views.year_archive),
|
|
|
|
path('articles/<int:year>/<int:month>/', views.month_archive),
|
|
|
|
path('articles/<int:year>/<int:month>/<int:pk>/', views.article_detail),
|
2014-04-02 08:46:34 +08:00
|
|
|
]
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2016-10-21 01:29:04 +08:00
|
|
|
The code above maps URL paths to Python callback functions ("views"). The path
|
|
|
|
strings use parameter tags to "capture" values from the URLs. When a user
|
|
|
|
requests a page, Django runs through each path, in order, and stops at the
|
|
|
|
first one that matches the requested URL. (If none of them matches, Django
|
|
|
|
calls a special-case 404 view.) This is blazingly fast, because the paths are
|
|
|
|
compiled into regular expressions at load time.
|
2013-05-20 00:06:35 +08:00
|
|
|
|
2016-10-21 01:29:04 +08:00
|
|
|
Once one of the URL patterns matches, Django calls the given view, which is a
|
|
|
|
Python function. Each view gets passed a request object -- which contains
|
|
|
|
request metadata -- and the values captured in the pattern.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
For example, if a user requested the URL "/articles/2005/05/39323/", Django
|
2010-10-19 08:10:22 +08:00
|
|
|
would call the function ``news.views.article_detail(request,
|
2016-10-21 01:29:04 +08:00
|
|
|
year=2005, month=5, pk=39323)``.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
Write your views
|
|
|
|
================
|
|
|
|
|
|
|
|
Each view is responsible for doing one of two things: Returning an
|
2008-08-24 06:25:40 +08:00
|
|
|
:class:`~django.http.HttpResponse` object containing the content for the
|
|
|
|
requested page, or raising an exception such as :class:`~django.http.Http404`.
|
|
|
|
The rest is up to you.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
Generally, a view retrieves data according to the parameters, loads a template
|
|
|
|
and renders the template with the retrieved data. Here's an example view for
|
2014-09-06 19:31:36 +08:00
|
|
|
``year_archive`` from above:
|
|
|
|
|
2018-09-11 01:00:34 +08:00
|
|
|
.. code-block:: python
|
2022-05-31 13:40:54 +08:00
|
|
|
:caption: ``mysite/news/views.py``
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2013-12-31 01:15:49 +08:00
|
|
|
from django.shortcuts import render
|
2013-05-18 19:34:29 +08:00
|
|
|
|
2014-09-06 19:31:36 +08:00
|
|
|
from .models import Article
|
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
def year_archive(request, year):
|
|
|
|
a_list = Article.objects.filter(pub_date__year=year)
|
2013-12-31 01:15:49 +08:00
|
|
|
context = {'year': year, 'article_list': a_list}
|
|
|
|
return render(request, 'news/year_archive.html', context)
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2010-08-20 03:27:44 +08:00
|
|
|
This example uses Django's :doc:`template system </topics/templates>`, which has
|
2008-08-24 06:25:40 +08:00
|
|
|
several powerful features but strives to stay simple enough for non-programmers
|
|
|
|
to use.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
Design your templates
|
|
|
|
=====================
|
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
The code above loads the ``news/year_archive.html`` template.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
Django has a template search path, which allows you to minimize redundancy among
|
|
|
|
templates. In your Django settings, you specify a list of directories to check
|
2014-12-18 05:51:42 +08:00
|
|
|
for templates with :setting:`DIRS <TEMPLATES-DIRS>`. If a template doesn't exist
|
|
|
|
in the first directory, it checks the second, and so on.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2012-02-25 06:53:48 +08:00
|
|
|
Let's say the ``news/year_archive.html`` template was found. Here's what that
|
2008-08-24 06:25:40 +08:00
|
|
|
might look like:
|
|
|
|
|
2018-09-11 01:00:34 +08:00
|
|
|
.. code-block:: html+django
|
2022-05-31 13:40:54 +08:00
|
|
|
:caption: ``mysite/news/templates/news/year_archive.html``
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
{% extends "base.html" %}
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2006-05-09 05:59:37 +08:00
|
|
|
{% block title %}Articles for {{ year }}{% endblock %}
|
2005-07-16 10:40:24 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
{% block content %}
|
2006-05-09 05:59:37 +08:00
|
|
|
<h1>Articles for {{ year }}</h1>
|
|
|
|
|
|
|
|
{% for article in article_list %}
|
2009-06-18 21:32:12 +08:00
|
|
|
<p>{{ article.headline }}</p>
|
|
|
|
<p>By {{ article.reporter.full_name }}</p>
|
|
|
|
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
|
2006-05-09 05:59:37 +08:00
|
|
|
{% endfor %}
|
2005-07-15 23:31:20 +08:00
|
|
|
{% endblock %}
|
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
Variables are surrounded by double-curly braces. ``{{ article.headline }}``
|
|
|
|
means "Output the value of the article's headline attribute." But dots aren't
|
2013-12-31 01:15:49 +08:00
|
|
|
used only for attribute lookup. They also can do dictionary-key lookup, index
|
2006-05-09 23:31:03 +08:00
|
|
|
lookup and function calls.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
Note ``{{ article.pub_date|date:"F j, Y" }}`` uses a Unix-style "pipe" (the "|"
|
|
|
|
character). This is called a template filter, and it's a way to filter the value
|
|
|
|
of a variable. In this case, the date filter formats a Python datetime object in
|
2012-12-13 21:20:47 +08:00
|
|
|
the given format (as found in PHP's date function).
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2013-05-20 00:06:35 +08:00
|
|
|
You can chain together as many filters as you'd like. You can write :ref:`custom
|
|
|
|
template filters <howto-writing-custom-template-filters>`. You can write
|
|
|
|
:doc:`custom template tags </howto/custom-template-tags>`, which run custom
|
|
|
|
Python code behind the scenes.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2013-12-31 01:15:49 +08:00
|
|
|
Finally, Django uses the concept of "template inheritance". That's what the
|
2006-05-02 09:31:56 +08:00
|
|
|
``{% extends "base.html" %}`` does. It means "First load the template called
|
|
|
|
'base', which has defined a bunch of blocks, and fill the blocks with the
|
|
|
|
following blocks." In short, that lets you dramatically cut down on redundancy
|
2007-08-07 10:33:11 +08:00
|
|
|
in templates: each template has to define only what's unique to that template.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2013-02-23 23:35:22 +08:00
|
|
|
Here's what the "base.html" template, including the use of :doc:`static files
|
2013-03-08 03:15:39 +08:00
|
|
|
</howto/static-files/index>`, might look like:
|
2008-08-24 06:25:40 +08:00
|
|
|
|
2018-09-11 01:00:34 +08:00
|
|
|
.. code-block:: html+django
|
2022-05-31 13:40:54 +08:00
|
|
|
:caption: ``mysite/templates/base.html``
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2015-11-07 19:24:38 +08:00
|
|
|
{% load static %}
|
2005-07-15 23:31:20 +08:00
|
|
|
<html>
|
|
|
|
<head>
|
2005-07-17 05:17:58 +08:00
|
|
|
<title>{% block title %}{% endblock %}</title>
|
2005-07-15 23:31:20 +08:00
|
|
|
</head>
|
|
|
|
<body>
|
2020-11-02 17:34:24 +08:00
|
|
|
<img src="{% static 'images/sitelogo.png' %}" alt="Logo">
|
2005-07-15 23:31:20 +08:00
|
|
|
{% block content %}{% endblock %}
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
|
|
|
|
Simplistically, it defines the look-and-feel of the site (with the site's logo),
|
2019-06-17 22:54:55 +08:00
|
|
|
and provides "holes" for child templates to fill. This means that a site redesign
|
|
|
|
can be done by changing a single file -- the base template.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
It also lets you create multiple versions of a site, with different base
|
|
|
|
templates, while reusing child templates. Django's creators have used this
|
2019-06-17 22:54:55 +08:00
|
|
|
technique to create strikingly different mobile versions of sites by only
|
2013-12-31 01:15:49 +08:00
|
|
|
creating a new base template.
|
2006-05-02 09:31:56 +08:00
|
|
|
|
2005-07-15 23:31:20 +08:00
|
|
|
Note that you don't have to use Django's template system if you prefer another
|
|
|
|
system. While Django's template system is particularly well-integrated with
|
|
|
|
Django's model layer, nothing forces you to use it. For that matter, you don't
|
2006-05-02 09:31:56 +08:00
|
|
|
have to use Django's database API, either. You can use another database
|
|
|
|
abstraction layer, you can read XML files, you can read files off disk, or
|
|
|
|
anything you want. Each piece of Django -- models, views, templates -- is
|
|
|
|
decoupled from the next.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
|
|
|
This is just the surface
|
|
|
|
========================
|
|
|
|
|
|
|
|
This has been only a quick overview of Django's functionality. Some more useful
|
|
|
|
features:
|
|
|
|
|
2011-10-14 08:12:01 +08:00
|
|
|
* A :doc:`caching framework </topics/cache>` that integrates with memcached
|
|
|
|
or other backends.
|
2008-08-24 06:25:40 +08:00
|
|
|
|
2019-06-17 22:54:55 +08:00
|
|
|
* A :doc:`syndication framework </ref/contrib/syndication>` that lets you
|
|
|
|
create RSS and Atom feeds by writing a small Python class.
|
2008-08-24 06:25:40 +08:00
|
|
|
|
2019-04-13 23:11:01 +08:00
|
|
|
* More attractive automatically-generated admin features -- this overview
|
|
|
|
barely scratched the surface.
|
2005-07-15 23:31:20 +08:00
|
|
|
|
2019-06-17 22:54:55 +08:00
|
|
|
The next steps are for you to `download Django`_, read :doc:`the tutorial
|
|
|
|
</intro/tutorial01>` and join `the community`_. Thanks for your interest!
|
2005-07-20 01:20:37 +08:00
|
|
|
|
2012-03-14 01:53:31 +08:00
|
|
|
.. _download Django: https://www.djangoproject.com/download/
|
|
|
|
.. _the community: https://www.djangoproject.com/community/
|