[2.1.x] Refs #20910 -- Replaced snippet directive with code-block.

Backport of c49ea6f591 from master
This commit is contained in:
Curtis Maloney 2018-09-11 03:00:34 +10:00 committed by Tim Graham
parent 2b2474b75d
commit 1853e2dbf2
32 changed files with 234 additions and 375 deletions

View File

@ -6,14 +6,13 @@ import os
import re import re
from docutils import nodes from docutils import nodes
from docutils.parsers.rst import Directive, directives from docutils.parsers.rst import Directive
from docutils.statemachine import ViewList from docutils.statemachine import ViewList
from sphinx import addnodes from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.directives import CodeBlock from sphinx.directives import CodeBlock
from sphinx.domains.std import Cmdoption from sphinx.domains.std import Cmdoption
from sphinx.util.console import bold from sphinx.util.console import bold
from sphinx.util.nodes import set_source_info
from sphinx.writers.html import HTMLTranslator from sphinx.writers.html import HTMLTranslator
# RE for option descriptions without a '--' prefix # RE for option descriptions without a '--' prefix
@ -53,17 +52,6 @@ def setup(app):
app.add_directive('versionadded', VersionDirective) app.add_directive('versionadded', VersionDirective)
app.add_directive('versionchanged', VersionDirective) app.add_directive('versionchanged', VersionDirective)
app.add_builder(DjangoStandaloneHTMLBuilder) app.add_builder(DjangoStandaloneHTMLBuilder)
# register the snippet directive
app.add_directive('snippet', SnippetWithFilename)
# register a node for snippet directive so that the xml parser
# knows how to handle the enter/exit parsing event
app.add_node(snippet_with_filename,
html=(visit_snippet, depart_snippet_literal),
latex=(visit_snippet_latex, depart_snippet_latex),
man=(visit_snippet_literal, depart_snippet_literal),
text=(visit_snippet_literal, depart_snippet_literal),
texinfo=(visit_snippet_literal, depart_snippet_literal))
app.set_translator('djangohtml', DjangoHTMLTranslator) app.set_translator('djangohtml', DjangoHTMLTranslator)
app.set_translator('json', DjangoHTMLTranslator) app.set_translator('json', DjangoHTMLTranslator)
app.add_node( app.add_node(
@ -79,133 +67,6 @@ def setup(app):
return {'parallel_read_safe': True} return {'parallel_read_safe': True}
class snippet_with_filename(nodes.literal_block):
"""
Subclass the literal_block to override the visit/depart event handlers
"""
pass
def visit_snippet_literal(self, node):
"""
default literal block handler
"""
self.visit_literal_block(node)
def depart_snippet_literal(self, node):
"""
default literal block handler
"""
self.depart_literal_block(node)
def visit_snippet(self, node):
"""
HTML document generator visit handler
"""
lang = self.highlightlang
linenos = node.rawsource.count('\n') >= self.highlightlinenothreshold - 1
fname = node['filename']
highlight_args = node.get('highlight_args', {})
if 'language' in node:
# code-block directives
lang = node['language']
highlight_args['force'] = True
if 'linenos' in node:
linenos = node['linenos']
def warner(msg):
self.builder.warn(msg, (self.builder.current_docname, node.line))
highlighted = self.highlighter.highlight_block(node.rawsource, lang,
warn=warner,
linenos=linenos,
**highlight_args)
starttag = self.starttag(node, 'div', suffix='',
CLASS='highlight-%s snippet' % lang)
self.body.append(starttag)
self.body.append('<div class="snippet-filename">%s</div>\n''' % (fname,))
self.body.append(highlighted)
self.body.append('</div>\n')
raise nodes.SkipNode
def visit_snippet_latex(self, node):
"""
Latex document generator visit handler
"""
code = node.rawsource.rstrip('\n')
lang = self.hlsettingstack[-1][0]
linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
fname = node['filename']
highlight_args = node.get('highlight_args', {})
if 'language' in node:
# code-block directives
lang = node['language']
highlight_args['force'] = True
if 'linenos' in node:
linenos = node['linenos']
def warner(msg):
self.builder.warn(msg, (self.curfilestack[-1], node.line))
hlcode = self.highlighter.highlight_block(code, lang, warn=warner,
linenos=linenos,
**highlight_args)
self.body.append(
'\n{\\colorbox[rgb]{0.9,0.9,0.9}'
'{\\makebox[\\textwidth][l]'
'{\\small\\texttt{%s}}}}\n' % (
# Some filenames have '_', which is special in latex.
fname.replace('_', r'\_'),
)
)
if self.table:
hlcode = hlcode.replace('\\begin{Verbatim}',
'\\begin{OriginalVerbatim}')
self.table.has_problematic = True
self.table.has_verbatim = True
hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim}
hlcode = hlcode.rstrip() + '\n'
self.body.append('\n' + hlcode + '\\end{%sVerbatim}\n' %
(self.table and 'Original' or ''))
# Prevent rawsource from appearing in output a second time.
raise nodes.SkipNode
def depart_snippet_latex(self, node):
"""
Latex document generator depart handler.
"""
pass
class SnippetWithFilename(Directive):
"""
The 'snippet' directive that allows to add the filename (optional)
of a code snippet in the document. This is modeled after CodeBlock.
"""
has_content = True
optional_arguments = 1
option_spec = {'filename': directives.unchanged_required}
def run(self):
code = '\n'.join(self.content)
literal = snippet_with_filename(code, code)
if self.arguments:
literal['language'] = self.arguments[0]
literal['filename'] = self.options['filename']
set_source_info(self, literal)
return [literal]
class VersionDirective(Directive): class VersionDirective(Directive):
has_content = True has_content = True
required_arguments = 1 required_arguments = 1

View File

@ -29,15 +29,14 @@ pre {
} }
/* Header for some code blocks. */ /* Header for some code blocks. */
.snippet-filename { .code-block-caption {
background-color: #393939; background-color: #393939;
color: white; color: white;
margin: 0; margin: 0;
padding: 0.5em; padding: 0.5em;
font: bold 90% monospace; font: bold 90% monospace;
} }
.snippet-filename + .highlight > pre, .literal-block-wrapper pre {
.snippet-filename + pre {
margin-top: 0; margin-top: 0;
} }

View File

@ -101,9 +101,8 @@ pre { font-size:small; background:#E0FFB8; border:1px solid #94da3a; border-widt
dt .literal, table .literal { background:none; } dt .literal, table .literal { background:none; }
#bd a.reference { text-decoration: none; } #bd a.reference { text-decoration: none; }
#bd a.reference tt.literal { border-bottom: 1px #234f32 dotted; } #bd a.reference tt.literal { border-bottom: 1px #234f32 dotted; }
div.snippet-filename { color: white; background-color: #234F32; margin: 0; padding: 2px 5px; width: 100%; font-family: monospace; font-size: small; line-height: 1.3em; } div.code-block-caption { color: white; background-color: #234F32; margin: 0; padding: 2px 5px; width: 100%; font-family: monospace; font-size: small; line-height: 1.3em; }
div.snippet-filename + div.highlight > pre { margin-top: 0; } div.literal-block-wrapper pre { margin-top: 0; }
div.snippet-filename + pre { margin-top: 0; }
/* Restore colors of pygments hyperlinked code */ /* Restore colors of pygments hyperlinked code */
#bd .highlight .k a:link, #bd .highlight .k a:visited { color: #000000; text-decoration: none; border-bottom: 1px dotted #000000; } #bd .highlight .k a:link, #bd .highlight .k a:visited { color: #000000; text-decoration: none; border-bottom: 1px dotted #000000; }

View File

@ -58,7 +58,7 @@ look like in JSON:
And here's that same fixture as YAML: And here's that same fixture as YAML:
.. code-block:: none .. code-block:: yaml
- model: myapp.person - model: myapp.person
pk: 1 pk: 1

View File

@ -39,8 +39,8 @@ attribute::
You can also provide hints that will be passed to the :meth:`allow_migrate()` You can also provide hints that will be passed to the :meth:`allow_migrate()`
method of database routers as ``**hints``: method of database routers as ``**hints``:
.. snippet:: .. code-block:: python
:filename: myapp/dbrouters.py :caption: myapp/dbrouters.py
class MyRouter: class MyRouter:
@ -97,8 +97,8 @@ the respective field according to your needs.
of the three new files) to the last migration, change ``AddField`` to of the three new files) to the last migration, change ``AddField`` to
``AlterField``, and add imports of ``uuid`` and ``models``. For example: ``AlterField``, and add imports of ``uuid`` and ``models``. For example:
.. snippet:: .. code-block:: python
:filename: 0006_remove_uuid_null.py :caption: 0006_remove_uuid_null.py
# Generated by Django A.B on YYYY-MM-DD HH:MM # Generated by Django A.B on YYYY-MM-DD HH:MM
from django.db import migrations, models from django.db import migrations, models
@ -121,8 +121,8 @@ the respective field according to your needs.
* Edit the first migration file. The generated migration class should look * Edit the first migration file. The generated migration class should look
similar to this: similar to this:
.. snippet:: .. code-block:: python
:filename: 0004_add_uuid_field.py :caption: 0004_add_uuid_field.py
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -148,8 +148,8 @@ the respective field according to your needs.
unique value (UUID in the example) for each existing row. Also add an import unique value (UUID in the example) for each existing row. Also add an import
of ``uuid``. For example: of ``uuid``. For example:
.. snippet:: .. code-block:: python
:filename: 0005_populate_uuid_values.py :caption: 0005_populate_uuid_values.py
# Generated by Django A.B on YYYY-MM-DD HH:MM # Generated by Django A.B on YYYY-MM-DD HH:MM
from django.db import migrations from django.db import migrations
@ -279,8 +279,8 @@ project anywhere without first installing and then uninstalling the old app.
Here's a sample migration: Here's a sample migration:
.. snippet:: .. code-block:: python
:filename: myapp/migrations/0124_move_old_app_to_new_app.py :caption: myapp/migrations/0124_move_old_app_to_new_app.py
from django.apps import apps as global_apps from django.apps import apps as global_apps
from django.db import migrations from django.db import migrations

View File

@ -123,8 +123,8 @@ Imports
For example (comments are for explanatory purposes only): For example (comments are for explanatory purposes only):
.. snippet:: .. code-block:: python
:filename: django/contrib/admin/example.py :caption: django/contrib/admin/example.py
# future # future
from __future__ import unicode_literals from __future__ import unicode_literals

View File

@ -446,8 +446,8 @@ Since this pattern involves a lot of boilerplate, Django provides the
:func:`~django.test.utils.isolate_apps` instances are correctly :func:`~django.test.utils.isolate_apps` instances are correctly
installed, you should pass the set of targeted ``app_label`` as arguments: installed, you should pass the set of targeted ``app_label`` as arguments:
.. snippet:: .. code-block:: python
:filename: tests/app_label/tests.py :caption: tests/app_label/tests.py
from django.db import models from django.db import models
from django.test import SimpleTestCase from django.test import SimpleTestCase

View File

@ -62,8 +62,8 @@ You'll need a few things before getting started:
* Access to Django's record on PyPI. Create a file with your credentials: * Access to Django's record on PyPI. Create a file with your credentials:
.. snippet:: .. code-block:: ini
:filename: ~/.pypirc :caption: ~/.pypirc
[pypi] [pypi]
username:YourUsername username:YourUsername

View File

@ -25,8 +25,8 @@ The :doc:`data-model syntax </topics/db/models>` offers many rich ways of
representing your models -- so far, it's been solving many years' worth of representing your models -- so far, it's been solving many years' worth of
database-schema problems. Here's a quick example: database-schema problems. Here's a quick example:
.. snippet:: .. code-block:: python
:filename: mysite/news/models.py :caption: mysite/news/models.py
from django.db import models from django.db import models
@ -145,8 +145,8 @@ production ready :doc:`administrative interface </ref/contrib/admin/index>` --
a website that lets authenticated users add, change and delete objects. It's a website that lets authenticated users add, change and delete objects. It's
as easy as registering your model in the admin site: as easy as registering your model in the admin site:
.. snippet:: .. code-block:: python
:filename: mysite/news/models.py :caption: mysite/news/models.py
from django.db import models from django.db import models
@ -156,8 +156,8 @@ as easy as registering your model in the admin site:
content = models.TextField() content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE) reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
.. snippet:: .. code-block:: python
:filename: mysite/news/admin.py :caption: mysite/news/admin.py
from django.contrib import admin from django.contrib import admin
@ -188,8 +188,8 @@ to decouple URLs from Python code.
Here's what a URLconf might look like for the ``Reporter``/``Article`` Here's what a URLconf might look like for the ``Reporter``/``Article``
example above: example above:
.. snippet:: .. code-block:: python
:filename: mysite/news/urls.py :caption: mysite/news/urls.py
from django.urls import path from django.urls import path
@ -228,8 +228,8 @@ 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 and renders the template with the retrieved data. Here's an example view for
``year_archive`` from above: ``year_archive`` from above:
.. snippet:: .. code-block:: python
:filename: mysite/news/views.py :caption: mysite/news/views.py
from django.shortcuts import render from django.shortcuts import render
@ -257,8 +257,8 @@ in the first directory, it checks the second, and so on.
Let's say the ``news/year_archive.html`` template was found. Here's what that Let's say the ``news/year_archive.html`` template was found. Here's what that
might look like: might look like:
.. snippet:: html+django .. code-block:: html+django
:filename: mysite/news/templates/news/year_archive.html :caption: mysite/news/templates/news/year_archive.html
{% extends "base.html" %} {% extends "base.html" %}
@ -298,8 +298,8 @@ in templates: each template has to define only what's unique to that template.
Here's what the "base.html" template, including the use of :doc:`static files Here's what the "base.html" template, including the use of :doc:`static files
</howto/static-files/index>`, might look like: </howto/static-files/index>`, might look like:
.. snippet:: html+django .. code-block:: html+django
:filename: mysite/templates/base.html :caption: mysite/templates/base.html
{% load static %} {% load static %}
<html> <html>

View File

@ -141,8 +141,8 @@ this. For a small app like polls, this process isn't too difficult.
3. Create a file ``django-polls/README.rst`` with the following contents: 3. Create a file ``django-polls/README.rst`` with the following contents:
.. snippet:: .. code-block:: rst
:filename: django-polls/README.rst :caption: django-polls/README.rst
===== =====
Polls Polls
@ -188,8 +188,8 @@ this. For a small app like polls, this process isn't too difficult.
explanation. Create a file ``django-polls/setup.py`` with the following explanation. Create a file ``django-polls/setup.py`` with the following
contents: contents:
.. snippet:: .. code-block:: python
:filename: django-polls/setup.py :caption: django-polls/setup.py
import os import os
from setuptools import find_packages, setup from setuptools import find_packages, setup
@ -233,8 +233,8 @@ this. For a small app like polls, this process isn't too difficult.
file, create a file ``django-polls/MANIFEST.in`` with the following file, create a file ``django-polls/MANIFEST.in`` with the following
contents: contents:
.. snippet:: .. code-block:: text
:filename: django-polls/MANIFEST.in :caption: django-polls/MANIFEST.in
include LICENSE include LICENSE
include README.rst include README.rst

View File

@ -243,8 +243,8 @@ Write your first view
Let's write the first view. Open the file ``polls/views.py`` Let's write the first view. Open the file ``polls/views.py``
and put the following Python code in it: and put the following Python code in it:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.http import HttpResponse from django.http import HttpResponse
@ -271,8 +271,8 @@ Your app directory should now look like::
In the ``polls/urls.py`` file include the following code: In the ``polls/urls.py`` file include the following code:
.. snippet:: .. code-block:: python
:filename: polls/urls.py :caption: polls/urls.py
from django.urls import path from django.urls import path
@ -286,8 +286,8 @@ The next step is to point the root URLconf at the ``polls.urls`` module. In
``mysite/urls.py``, add an import for ``django.urls.include`` and insert an ``mysite/urls.py``, add an import for ``django.urls.include`` and insert an
:func:`~django.urls.include` in the ``urlpatterns`` list, so you have: :func:`~django.urls.include` in the ``urlpatterns`` list, so you have:
.. snippet:: .. code-block:: python
:filename: mysite/urls.py :caption: mysite/urls.py
from django.contrib import admin from django.contrib import admin
from django.urls import include, path from django.urls import include, path

View File

@ -135,8 +135,8 @@ with a ``Question``.
These concepts are represented by simple Python classes. Edit the These concepts are represented by simple Python classes. Edit the
:file:`polls/models.py` file so it looks like this: :file:`polls/models.py` file so it looks like this:
.. snippet:: .. code-block:: python
:filename: polls/models.py :caption: polls/models.py
from django.db import models from django.db import models
@ -211,8 +211,8 @@ is ``'polls.apps.PollsConfig'``. Edit the :file:`mysite/settings.py` file and
add that dotted path to the :setting:`INSTALLED_APPS` setting. It'll look like add that dotted path to the :setting:`INSTALLED_APPS` setting. It'll look like
this: this:
.. snippet:: .. code-block:: python
:filename: mysite/settings.py :caption: mysite/settings.py
INSTALLED_APPS = [ INSTALLED_APPS = [
'polls.apps.PollsConfig', 'polls.apps.PollsConfig',
@ -423,8 +423,8 @@ representation of this object. Let's fix that by editing the ``Question`` model
:meth:`~django.db.models.Model.__str__` method to both ``Question`` and :meth:`~django.db.models.Model.__str__` method to both ``Question`` and
``Choice``: ``Choice``:
.. snippet:: .. code-block:: python
:filename: polls/models.py :caption: polls/models.py
from django.db import models from django.db import models
@ -446,8 +446,8 @@ automatically-generated admin.
Note these are normal Python methods. Let's add a custom method, just for Note these are normal Python methods. Let's add a custom method, just for
demonstration: demonstration:
.. snippet:: .. code-block:: python
:filename: polls/models.py :caption: polls/models.py
import datetime import datetime
@ -644,8 +644,8 @@ Just one thing to do: we need to tell the admin that ``Question``
objects have an admin interface. To do this, open the :file:`polls/admin.py` objects have an admin interface. To do this, open the :file:`polls/admin.py`
file, and edit it to look like this: file, and edit it to look like this:
.. snippet:: .. code-block:: python
:filename: polls/admin.py :caption: polls/admin.py
from django.contrib import admin from django.contrib import admin

View File

@ -64,8 +64,8 @@ Writing more views
Now let's add a few more views to ``polls/views.py``. These views are Now let's add a few more views to ``polls/views.py``. These views are
slightly different, because they take an argument: slightly different, because they take an argument:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
def detail(request, question_id): def detail(request, question_id):
return HttpResponse("You're looking at question %s." % question_id) return HttpResponse("You're looking at question %s." % question_id)
@ -80,8 +80,8 @@ slightly different, because they take an argument:
Wire these new views into the ``polls.urls`` module by adding the following Wire these new views into the ``polls.urls`` module by adding the following
:func:`~django.urls.path` calls: :func:`~django.urls.path` calls:
.. snippet:: .. code-block:: python
:filename: polls/urls.py :caption: polls/urls.py
from django.urls import path from django.urls import path
@ -147,8 +147,8 @@ in :doc:`Tutorial 2 </intro/tutorial02>`. Here's one stab at a new ``index()``
view, which displays the latest 5 poll questions in the system, separated by view, which displays the latest 5 poll questions in the system, separated by
commas, according to publication date: commas, according to publication date:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.http import HttpResponse from django.http import HttpResponse
@ -196,8 +196,8 @@ Django simply as ``polls/index.html``.
Put the following code in that template: Put the following code in that template:
.. snippet:: html+django .. code-block:: html+django
:filename: polls/templates/polls/index.html :caption: polls/templates/polls/index.html
{% if latest_question_list %} {% if latest_question_list %}
<ul> <ul>
@ -211,8 +211,8 @@ Put the following code in that template:
Now let's update our ``index`` view in ``polls/views.py`` to use the template: Now let's update our ``index`` view in ``polls/views.py`` to use the template:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.http import HttpResponse from django.http import HttpResponse
from django.template import loader from django.template import loader
@ -244,8 +244,8 @@ It's a very common idiom to load a template, fill a context and return an
template. Django provides a shortcut. Here's the full ``index()`` view, template. Django provides a shortcut. Here's the full ``index()`` view,
rewritten: rewritten:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.shortcuts import render from django.shortcuts import render
@ -273,8 +273,8 @@ Raising a 404 error
Now, let's tackle the question detail view -- the page that displays the question text Now, let's tackle the question detail view -- the page that displays the question text
for a given poll. Here's the view: for a given poll. Here's the view:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.http import Http404 from django.http import Http404
from django.shortcuts import render from django.shortcuts import render
@ -295,8 +295,8 @@ We'll discuss what you could put in that ``polls/detail.html`` template a bit
later, but if you'd like to quickly get the above example working, a file later, but if you'd like to quickly get the above example working, a file
containing just: containing just:
.. snippet:: html+django .. code-block:: html+django
:filename: polls/templates/polls/detail.html :caption: polls/templates/polls/detail.html
{{ question }} {{ question }}
@ -309,8 +309,8 @@ It's a very common idiom to use :meth:`~django.db.models.query.QuerySet.get`
and raise :exc:`~django.http.Http404` if the object doesn't exist. Django and raise :exc:`~django.http.Http404` if the object doesn't exist. Django
provides a shortcut. Here's the ``detail()`` view, rewritten: provides a shortcut. Here's the ``detail()`` view, rewritten:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
@ -351,8 +351,8 @@ Back to the ``detail()`` view for our poll application. Given the context
variable ``question``, here's what the ``polls/detail.html`` template might look variable ``question``, here's what the ``polls/detail.html`` template might look
like: like:
.. snippet:: html+django .. code-block:: html+django
:filename: polls/templates/polls/detail.html :caption: polls/templates/polls/detail.html
<h1>{{ question.question_text }}</h1> <h1>{{ question.question_text }}</h1>
<ul> <ul>
@ -425,8 +425,8 @@ make it so that Django knows which app view to create for a url when using the
The answer is to add namespaces to your URLconf. In the ``polls/urls.py`` The answer is to add namespaces to your URLconf. In the ``polls/urls.py``
file, go ahead and add an ``app_name`` to set the application namespace: file, go ahead and add an ``app_name`` to set the application namespace:
.. snippet:: .. code-block:: python
:filename: polls/urls.py :caption: polls/urls.py
from django.urls import path from django.urls import path
@ -442,15 +442,15 @@ file, go ahead and add an ``app_name`` to set the application namespace:
Now change your ``polls/index.html`` template from: Now change your ``polls/index.html`` template from:
.. snippet:: html+django .. code-block:: html+django
:filename: polls/templates/polls/index.html :caption: polls/templates/polls/index.html
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li> <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
to point at the namespaced detail view: to point at the namespaced detail view:
.. snippet:: html+django .. code-block:: html+django
:filename: polls/templates/polls/index.html :caption: polls/templates/polls/index.html
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li> <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

View File

@ -12,8 +12,8 @@ Write a simple form
Let's update our poll detail template ("polls/detail.html") from the last Let's update our poll detail template ("polls/detail.html") from the last
tutorial, so that the template contains an HTML ``<form>`` element: tutorial, so that the template contains an HTML ``<form>`` element:
.. snippet:: html+django .. code-block:: html+django
:filename: polls/templates/polls/detail.html :caption: polls/templates/polls/detail.html
<h1>{{ question.question_text }}</h1> <h1>{{ question.question_text }}</h1>
@ -58,16 +58,16 @@ Now, let's create a Django view that handles the submitted data and does
something with it. Remember, in :doc:`Tutorial 3 </intro/tutorial03>`, we something with it. Remember, in :doc:`Tutorial 3 </intro/tutorial03>`, we
created a URLconf for the polls application that includes this line: created a URLconf for the polls application that includes this line:
.. snippet:: .. code-block:: python
:filename: polls/urls.py :caption: polls/urls.py
path('<int:question_id>/vote/', views.vote, name='vote'), path('<int:question_id>/vote/', views.vote, name='vote'),
We also created a dummy implementation of the ``vote()`` function. Let's We also created a dummy implementation of the ``vote()`` function. Let's
create a real version. Add the following to ``polls/views.py``: create a real version. Add the following to ``polls/views.py``:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
@ -146,8 +146,8 @@ response documentation </ref/request-response>`.
After somebody votes in a question, the ``vote()`` view redirects to the results After somebody votes in a question, the ``vote()`` view redirects to the results
page for the question. Let's write that view: page for the question. Let's write that view:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
@ -162,8 +162,8 @@ redundancy later.
Now, create a ``polls/results.html`` template: Now, create a ``polls/results.html`` template:
.. snippet:: html+django .. code-block:: html+django
:filename: polls/templates/polls/results.html :caption: polls/templates/polls/results.html
<h1>{{ question.question_text }}</h1> <h1>{{ question.question_text }}</h1>
@ -234,8 +234,8 @@ Amend URLconf
First, open the ``polls/urls.py`` URLconf and change it like so: First, open the ``polls/urls.py`` URLconf and change it like so:
.. snippet:: .. code-block:: python
:filename: polls/urls.py :caption: polls/urls.py
from django.urls import path from django.urls import path
@ -259,8 +259,8 @@ Next, we're going to remove our old ``index``, ``detail``, and ``results``
views and use Django's generic views instead. To do so, open the views and use Django's generic views instead. To do so, open the
``polls/views.py`` file and change it like so: ``polls/views.py`` file and change it like so:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render

View File

@ -166,8 +166,8 @@ whose name begins with ``test``.
Put the following in the ``tests.py`` file in the ``polls`` application: Put the following in the ``tests.py`` file in the ``polls`` application:
.. snippet:: .. code-block:: python
:filename: polls/tests.py :caption: polls/tests.py
import datetime import datetime
@ -248,8 +248,8 @@ return ``False`` if its ``pub_date`` is in the future. Amend the method in
``models.py``, so that it will only return ``True`` if the date is also in the ``models.py``, so that it will only return ``True`` if the date is also in the
past: past:
.. snippet:: .. code-block:: python
:filename: polls/models.py :caption: polls/models.py
def was_published_recently(self): def was_published_recently(self):
now = timezone.now() now = timezone.now()
@ -284,8 +284,8 @@ introduced another.
Add two more test methods to the same class, to test the behavior of the method Add two more test methods to the same class, to test the behavior of the method
more comprehensively: more comprehensively:
.. snippet:: .. code-block:: python
:filename: polls/tests.py :caption: polls/tests.py
def test_was_published_recently_with_old_question(self): def test_was_published_recently_with_old_question(self):
""" """
@ -400,8 +400,8 @@ The list of polls shows polls that aren't published yet (i.e. those that have a
In :doc:`Tutorial 4 </intro/tutorial04>` we introduced a class-based view, In :doc:`Tutorial 4 </intro/tutorial04>` we introduced a class-based view,
based on :class:`~django.views.generic.list.ListView`: based on :class:`~django.views.generic.list.ListView`:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
class IndexView(generic.ListView): class IndexView(generic.ListView):
template_name = 'polls/index.html' template_name = 'polls/index.html'
@ -415,15 +415,15 @@ We need to amend the ``get_queryset()`` method and change it so that it also
checks the date by comparing it with ``timezone.now()``. First we need to add checks the date by comparing it with ``timezone.now()``. First we need to add
an import: an import:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
from django.utils import timezone from django.utils import timezone
and then we must amend the ``get_queryset`` method like so: and then we must amend the ``get_queryset`` method like so:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
def get_queryset(self): def get_queryset(self):
""" """
@ -450,16 +450,16 @@ our :djadmin:`shell` session above.
Add the following to ``polls/tests.py``: Add the following to ``polls/tests.py``:
.. snippet:: .. code-block:: python
:filename: polls/tests.py :caption: polls/tests.py
from django.urls import reverse from django.urls import reverse
and we'll create a shortcut function to create questions as well as a new test and we'll create a shortcut function to create questions as well as a new test
class: class:
.. snippet:: .. code-block:: python
:filename: polls/tests.py :caption: polls/tests.py
def create_question(question_text, days): def create_question(question_text, days):
""" """
@ -559,8 +559,8 @@ What we have works well; however, even though future questions don't appear in
the *index*, users can still reach them if they know or guess the right URL. So the *index*, users can still reach them if they know or guess the right URL. So
we need to add a similar constraint to ``DetailView``: we need to add a similar constraint to ``DetailView``:
.. snippet:: .. code-block:: python
:filename: polls/views.py :caption: polls/views.py
class DetailView(generic.DetailView): class DetailView(generic.DetailView):
... ...
@ -574,8 +574,8 @@ And of course, we will add some tests, to check that a ``Question`` whose
``pub_date`` is in the past can be displayed, and that one with a ``pub_date`` ``pub_date`` is in the past can be displayed, and that one with a ``pub_date``
in the future is not: in the future is not:
.. snippet:: .. code-block:: python
:filename: polls/tests.py :caption: polls/tests.py
class QuestionDetailViewTests(TestCase): class QuestionDetailViewTests(TestCase):
def test_future_question(self): def test_future_question(self):

View File

@ -56,8 +56,8 @@ reference the path for templates.
Put the following code in that stylesheet (``polls/static/polls/style.css``): Put the following code in that stylesheet (``polls/static/polls/style.css``):
.. snippet:: css .. code-block:: css
:filename: polls/static/polls/style.css :caption: polls/static/polls/style.css
li a { li a {
color: green; color: green;
@ -65,8 +65,8 @@ Put the following code in that stylesheet (``polls/static/polls/style.css``):
Next, add the following at the top of ``polls/templates/polls/index.html``: Next, add the following at the top of ``polls/templates/polls/index.html``:
.. snippet:: html+django .. code-block:: html+django
:filename: polls/templates/polls/index.html :caption: polls/templates/polls/index.html
{% load static %} {% load static %}
@ -88,8 +88,8 @@ called ``background.gif``. In other words, put your image in
Then, add to your stylesheet (``polls/static/polls/style.css``): Then, add to your stylesheet (``polls/static/polls/style.css``):
.. snippet:: css .. code-block:: css
:filename: polls/static/polls/style.css :caption: polls/static/polls/style.css
body { body {
background: white url("images/background.gif") no-repeat; background: white url("images/background.gif") no-repeat;

View File

@ -18,8 +18,8 @@ Django the options you want when you register the object.
Let's see how this works by reordering the fields on the edit form. Replace Let's see how this works by reordering the fields on the edit form. Replace
the ``admin.site.register(Question)`` line with: the ``admin.site.register(Question)`` line with:
.. snippet:: .. code-block:: python
:filename: polls/admin.py :caption: polls/admin.py
from django.contrib import admin from django.contrib import admin
@ -47,8 +47,8 @@ of fields, choosing an intuitive order is an important usability detail.
And speaking of forms with dozens of fields, you might want to split the form And speaking of forms with dozens of fields, you might want to split the form
up into fieldsets: up into fieldsets:
.. snippet:: .. code-block:: python
:filename: polls/admin.py :caption: polls/admin.py
from django.contrib import admin from django.contrib import admin
@ -81,8 +81,8 @@ Yet.
There are two ways to solve this problem. The first is to register ``Choice`` There are two ways to solve this problem. The first is to register ``Choice``
with the admin just as we did with ``Question``. That's easy: with the admin just as we did with ``Question``. That's easy:
.. snippet:: .. code-block:: python
:filename: polls/admin.py :caption: polls/admin.py
from django.contrib import admin from django.contrib import admin
@ -115,8 +115,8 @@ It'd be better if you could add a bunch of Choices directly when you create the
Remove the ``register()`` call for the ``Choice`` model. Then, edit the ``Question`` Remove the ``register()`` call for the ``Choice`` model. Then, edit the ``Question``
registration code to read: registration code to read:
.. snippet:: .. code-block:: python
:filename: polls/admin.py :caption: polls/admin.py
from django.contrib import admin from django.contrib import admin
@ -162,8 +162,8 @@ fields for entering related ``Choice`` objects. For that reason, Django offers a
tabular way of displaying inline related objects; you just need to change tabular way of displaying inline related objects; you just need to change
the ``ChoiceInline`` declaration to read: the ``ChoiceInline`` declaration to read:
.. snippet:: .. code-block:: python
:filename: polls/admin.py :caption: polls/admin.py
class ChoiceInline(admin.TabularInline): class ChoiceInline(admin.TabularInline):
#... #...
@ -194,8 +194,8 @@ more helpful if we could display individual fields. To do that, use the
tuple of field names to display, as columns, on the change list page for the tuple of field names to display, as columns, on the change list page for the
object: object:
.. snippet:: .. code-block:: python
:filename: polls/admin.py :caption: polls/admin.py
class QuestionAdmin(admin.ModelAdmin): class QuestionAdmin(admin.ModelAdmin):
# ... # ...
@ -204,8 +204,8 @@ object:
Just for good measure, let's also include the ``was_published_recently()`` Just for good measure, let's also include the ``was_published_recently()``
method from :doc:`Tutorial 2 </intro/tutorial02>`: method from :doc:`Tutorial 2 </intro/tutorial02>`:
.. snippet:: .. code-block:: python
:filename: polls/admin.py :caption: polls/admin.py
class QuestionAdmin(admin.ModelAdmin): class QuestionAdmin(admin.ModelAdmin):
# ... # ...
@ -226,8 +226,8 @@ representation of the output.
You can improve that by giving that method (in :file:`polls/models.py`) a few You can improve that by giving that method (in :file:`polls/models.py`) a few
attributes, as follows: attributes, as follows:
.. snippet:: .. code-block:: python
:filename: polls/models.py :caption: polls/models.py
class Question(models.Model): class Question(models.Model):
# ... # ...
@ -301,8 +301,8 @@ keeping your templates within the project is a good convention to follow.
Open your settings file (:file:`mysite/settings.py`, remember) and add a Open your settings file (:file:`mysite/settings.py`, remember) and add a
:setting:`DIRS <TEMPLATES-DIRS>` option in the :setting:`TEMPLATES` setting: :setting:`DIRS <TEMPLATES-DIRS>` option in the :setting:`TEMPLATES` setting:
.. snippet:: .. code-block:: python
:filename: mysite/settings.py :caption: mysite/settings.py
TEMPLATES = [ TEMPLATES = [
{ {

View File

@ -2933,8 +2933,8 @@ instantiate any other Python class) and register your models and
``ModelAdmin`` subclasses with it instead of with the default site. Finally, ``ModelAdmin`` subclasses with it instead of with the default site. Finally,
update :file:`myproject/urls.py` to reference your :class:`AdminSite` subclass. update :file:`myproject/urls.py` to reference your :class:`AdminSite` subclass.
.. snippet:: .. code-block:: python
:filename: myapp/admin.py :caption: myapp/admin.py
from django.contrib.admin import AdminSite from django.contrib.admin import AdminSite
@ -2947,8 +2947,8 @@ update :file:`myproject/urls.py` to reference your :class:`AdminSite` subclass.
admin_site.register(MyModel) admin_site.register(MyModel)
.. snippet:: .. code-block:: python
:filename: myproject/urls.py :caption: myproject/urls.py
from django.urls import path from django.urls import path
@ -2976,24 +2976,24 @@ You can override the default ``django.contrib.admin.site`` by setting the
to the dotted import path of either a ``AdminSite`` subclass or a callable that to the dotted import path of either a ``AdminSite`` subclass or a callable that
returns a site instance. returns a site instance.
.. snippet:: .. code-block:: python
:filename: myproject/admin.py :caption: myproject/admin.py
from django.contrib import admin from django.contrib import admin
class MyAdminSite(admin.AdminSite): class MyAdminSite(admin.AdminSite):
... ...
.. snippet:: .. code-block:: python
:filename: myproject/apps.py :caption: myproject/apps.py
from django.contrib.admin.apps import AdminConfig from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig): class MyAdminConfig(AdminConfig):
default_site = 'myproject.admin.MyAdminSite' default_site = 'myproject.admin.MyAdminSite'
.. snippet:: .. code-block:: python
:filename: myproject/settings.py :caption: myproject/settings.py
INSTALLED_APPS = [ INSTALLED_APPS = [
... ...

View File

@ -31,8 +31,8 @@ In your custom ``change_form.html`` template, extend the
<script type="text/javascript" src="{% static 'app/formset_handlers.js' %}"></script> <script type="text/javascript" src="{% static 'app/formset_handlers.js' %}"></script>
{% endblock %} {% endblock %}
.. snippet:: javascript .. code-block:: javascript
:filename: app/static/app/formset_handlers.js :caption: app/static/app/formset_handlers.js
(function($) { (function($) {
$(document).on('formset:added', function(event, $row, formsetName) { $(document).on('formset:added', function(event, $row, formsetName) {
@ -69,8 +69,8 @@ namespace, just listen to the event triggered from there. For example:
<script type="text/javascript" src="{% static 'app/unregistered_handlers.js' %}"></script> <script type="text/javascript" src="{% static 'app/unregistered_handlers.js' %}"></script>
{% endblock %} {% endblock %}
.. snippet:: javascript .. code-block:: javascript
:filename: app/static/app/unregistered_handlers.js :caption: app/static/app/unregistered_handlers.js
django.jQuery(document).on('formset:added', function(event, $row, formsetName) { django.jQuery(document).on('formset:added', function(event, $row, formsetName) {
// Row added // Row added

View File

@ -314,8 +314,8 @@ The ``Func`` API is as follows:
``arg_joiner``, and any other ``**extra_context`` parameters to ``arg_joiner``, and any other ``**extra_context`` parameters to
customize the SQL as needed. For example: customize the SQL as needed. For example:
.. snippet:: .. code-block:: python
:filename: django/db/models/functions.py :caption: django/db/models/functions.py
class ConcatPair(Func): class ConcatPair(Func):
... ...

View File

@ -1194,8 +1194,8 @@ Relationships defined this way on :ref:`abstract models
<abstract-base-classes>` are resolved when the model is subclassed as a <abstract-base-classes>` are resolved when the model is subclassed as a
concrete model and are not relative to the abstract model's ``app_label``: concrete model and are not relative to the abstract model's ``app_label``:
.. snippet:: .. code-block:: python
:filename: products/models.py :caption: products/models.py
from django.db import models from django.db import models
@ -1205,8 +1205,8 @@ concrete model and are not relative to the abstract model's ``app_label``:
class Meta: class Meta:
abstract = True abstract = True
.. snippet:: .. code-block:: python
:filename: production/models.py :caption: production/models.py
from django.db import models from django.db import models
from products.models import AbstractCar from products.models import AbstractCar

View File

@ -559,8 +559,8 @@ The auto-escaping tag passes its effect onto templates that extend the
current one as well as templates included via the :ttag:`include` tag, current one as well as templates included via the :ttag:`include` tag,
just like all block tags. For example: just like all block tags. For example:
.. snippet:: .. code-block:: html+django
:filename: base.html :caption: base.html
{% autoescape off %} {% autoescape off %}
<h1>{% block title %}{% endblock %}</h1> <h1>{% block title %}{% endblock %}</h1>
@ -568,8 +568,8 @@ just like all block tags. For example:
{% endblock %} {% endblock %}
{% endautoescape %} {% endautoescape %}
.. snippet:: .. code-block:: html+django
:filename: child.html :caption: child.html
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}This &amp; that{% endblock %} {% block title %}This &amp; that{% endblock %}
@ -649,15 +649,15 @@ of all comments related to the current task with::
And of course you can easily access methods you've explicitly defined on your And of course you can easily access methods you've explicitly defined on your
own models: own models:
.. snippet:: .. code-block:: python
:filename: models.py :caption: models.py
class Task(models.Model): class Task(models.Model):
def foo(self): def foo(self):
return "bar" return "bar"
.. snippet:: .. code-block:: html+django
:filename: template.html :caption: template.html
{{ task.foo }} {{ task.foo }}

View File

@ -1264,8 +1264,8 @@ attribute (as below). If the ``app_name`` is set in this new way, the
``namespace`` argument is no longer required. It will default to the value of ``namespace`` argument is no longer required. It will default to the value of
``app_name``. For example, the URL patterns in the tutorial are changed from: ``app_name``. For example, the URL patterns in the tutorial are changed from:
.. snippet:: .. code-block:: python
:filename: mysite/urls.py :caption: mysite/urls.py
urlpatterns = [ urlpatterns = [
url(r'^polls/', include('polls.urls', namespace="polls")), url(r'^polls/', include('polls.urls', namespace="polls")),
@ -1274,16 +1274,16 @@ attribute (as below). If the ``app_name`` is set in this new way, the
to: to:
.. snippet:: .. code-block:: python
:filename: mysite/urls.py :caption: mysite/urls.py
urlpatterns = [ urlpatterns = [
url(r'^polls/', include('polls.urls')), # 'namespace="polls"' removed url(r'^polls/', include('polls.urls')), # 'namespace="polls"' removed
... ...
] ]
.. snippet:: .. code-block:: python
:filename: polls/urls.py :caption: polls/urls.py
app_name = 'polls' # added app_name = 'polls' # added
urlpatterns = [...] urlpatterns = [...]
@ -1292,8 +1292,8 @@ This change also means that the old way of including an ``AdminSite`` instance
is deprecated. Instead, pass ``admin.site.urls`` directly to is deprecated. Instead, pass ``admin.site.urls`` directly to
:func:`~django.conf.urls.url()`: :func:`~django.conf.urls.url()`:
.. snippet:: .. code-block:: python
:filename: urls.py :caption: urls.py
from django.conf.urls import url from django.conf.urls import url
from django.contrib import admin from django.contrib import admin

View File

@ -251,8 +251,8 @@ modify the pattern to work with any algorithm or with a custom user model.
First, we'll add the custom hasher: First, we'll add the custom hasher:
.. snippet:: .. code-block:: python
:filename: accounts/hashers.py :caption: accounts/hashers.py
from django.contrib.auth.hashers import ( from django.contrib.auth.hashers import (
PBKDF2PasswordHasher, SHA1PasswordHasher, PBKDF2PasswordHasher, SHA1PasswordHasher,
@ -271,8 +271,8 @@ First, we'll add the custom hasher:
The data migration might look something like: The data migration might look something like:
.. snippet:: .. code-block:: python
:filename: accounts/migrations/0002_migrate_sha1_passwords.py :caption: accounts/migrations/0002_migrate_sha1_passwords.py
from django.db import migrations from django.db import migrations
@ -306,8 +306,8 @@ several thousand users, depending on the speed of your hardware.
Finally, we'll add a :setting:`PASSWORD_HASHERS` setting: Finally, we'll add a :setting:`PASSWORD_HASHERS` setting:
.. snippet:: .. code-block:: python
:filename: mysite/settings.py :caption: mysite/settings.py
PASSWORD_HASHERS = [ PASSWORD_HASHERS = [
'django.contrib.auth.hashers.PBKDF2PasswordHasher', 'django.contrib.auth.hashers.PBKDF2PasswordHasher',

View File

@ -18,8 +18,8 @@ Basic forms
Given a simple contact form: Given a simple contact form:
.. snippet:: .. code-block:: python
:filename: forms.py :caption: forms.py
from django import forms from django import forms
@ -33,8 +33,8 @@ Given a simple contact form:
The view can be constructed using a ``FormView``: The view can be constructed using a ``FormView``:
.. snippet:: .. code-block:: python
:filename: views.py :caption: views.py
from myapp.forms import ContactForm from myapp.forms import ContactForm
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
@ -96,8 +96,8 @@ add extra validation) simply set
First we need to add :meth:`~django.db.models.Model.get_absolute_url()` to our First we need to add :meth:`~django.db.models.Model.get_absolute_url()` to our
``Author`` class: ``Author`` class:
.. snippet:: .. code-block:: python
:filename: models.py :caption: models.py
from django.db import models from django.db import models
from django.urls import reverse from django.urls import reverse
@ -112,8 +112,8 @@ Then we can use :class:`CreateView` and friends to do the actual
work. Notice how we're just configuring the generic class-based views work. Notice how we're just configuring the generic class-based views
here; we don't have to write any logic ourselves: here; we don't have to write any logic ourselves:
.. snippet:: .. code-block:: python
:filename: views.py :caption: views.py
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, DeleteView, UpdateView from django.views.generic.edit import CreateView, DeleteView, UpdateView
@ -146,8 +146,8 @@ and :attr:`~django.views.generic.edit.FormMixin.form_class` attributes, an
Finally, we hook these new views into the URLconf: Finally, we hook these new views into the URLconf:
.. snippet:: .. code-block:: python
:filename: urls.py :caption: urls.py
from django.urls import path from django.urls import path
from myapp.views import AuthorCreate, AuthorDelete, AuthorUpdate from myapp.views import AuthorCreate, AuthorDelete, AuthorUpdate
@ -187,8 +187,8 @@ To track the user that created an object using a :class:`CreateView`,
you can use a custom :class:`~django.forms.ModelForm` to do this. First, add you can use a custom :class:`~django.forms.ModelForm` to do this. First, add
the foreign key relation to the model: the foreign key relation to the model:
.. snippet:: .. code-block:: python
:filename: models.py :caption: models.py
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db import models from django.db import models
@ -203,8 +203,8 @@ In the view, ensure that you don't include ``created_by`` in the list of fields
to edit, and override to edit, and override
:meth:`~django.views.generic.edit.ModelFormMixin.form_valid()` to add the user: :meth:`~django.views.generic.edit.ModelFormMixin.form_valid()` to add the user:
.. snippet:: .. code-block:: python
:filename: views.py :caption: views.py
from django.views.generic.edit import CreateView from django.views.generic.edit import CreateView
from myapp.models import Author from myapp.models import Author

View File

@ -222,8 +222,8 @@ we'll want the functionality provided by
We'll demonstrate this with the ``Author`` model we used in the We'll demonstrate this with the ``Author`` model we used in the
:doc:`generic class-based views introduction<generic-display>`. :doc:`generic class-based views introduction<generic-display>`.
.. snippet:: .. code-block:: python
:filename: views.py :caption: views.py
from django.http import HttpResponseForbidden, HttpResponseRedirect from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.urls import reverse from django.urls import reverse
@ -255,8 +255,8 @@ mixin.
We can hook this into our URLs easily enough: We can hook this into our URLs easily enough:
.. snippet:: .. code-block:: python
:filename: urls.py :caption: urls.py
from django.urls import path from django.urls import path
from books.views import RecordInterest from books.views import RecordInterest

View File

@ -1429,8 +1429,8 @@ store your models. You must import the models in the ``__init__.py`` file.
For example, if you had ``organic.py`` and ``synthetic.py`` in the ``models`` For example, if you had ``organic.py`` and ``synthetic.py`` in the ``models``
directory: directory:
.. snippet:: .. code-block:: python
:filename: myapp/models/__init__.py :caption: myapp/models/__init__.py
from .organic import Person from .organic import Person
from .synthetic import Robot from .synthetic import Robot

View File

@ -226,8 +226,8 @@ The :class:`Form` class
We already know what we want our HTML form to look like. Our starting point for We already know what we want our HTML form to look like. Our starting point for
it in Django is this: it in Django is this:
.. snippet:: .. code-block:: python
:filename: forms.py :caption: forms.py
from django import forms from django import forms
@ -276,8 +276,8 @@ logic.
To handle the form we need to instantiate it in the view for the URL where we To handle the form we need to instantiate it in the view for the URL where we
want it to be published: want it to be published:
.. snippet:: .. code-block:: python
:filename: views.py :caption: views.py
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render from django.shortcuts import render
@ -404,8 +404,8 @@ More on fields
Consider a more useful form than our minimal example above, which we could use Consider a more useful form than our minimal example above, which we could use
to implement "contact me" functionality on a personal website: to implement "contact me" functionality on a personal website:
.. snippet:: .. code-block:: python
:filename: forms.py :caption: forms.py
from django import forms from django import forms
@ -453,8 +453,8 @@ values to a Python ``int`` and ``float`` respectively.
Here's how the form data could be processed in the view that handles this form: Here's how the form data could be processed in the view that handles this form:
.. snippet:: .. code-block:: python
:filename: views.py :caption: views.py
from django.core.mail import send_mail from django.core.mail import send_mail

View File

@ -21,8 +21,8 @@ Basic file uploads
Consider a simple form containing a :class:`~django.forms.FileField`: Consider a simple form containing a :class:`~django.forms.FileField`:
.. snippet:: .. code-block:: python
:filename: forms.py :caption: forms.py
from django import forms from django import forms
@ -46,8 +46,8 @@ Most of the time, you'll simply pass the file data from ``request`` into the
form as described in :ref:`binding-uploaded-files`. This would look form as described in :ref:`binding-uploaded-files`. This would look
something like: something like:
.. snippet:: .. code-block:: python
:filename: views.py :caption: views.py
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render from django.shortcuts import render
@ -133,8 +133,8 @@ Uploading multiple files
If you want to upload multiple files using one form field, set the ``multiple`` If you want to upload multiple files using one form field, set the ``multiple``
HTML attribute of field's widget: HTML attribute of field's widget:
.. snippet:: .. code-block:: python
:filename: forms.py :caption: forms.py
from django import forms from django import forms
@ -145,8 +145,8 @@ Then override the ``post`` method of your
:class:`~django.views.generic.edit.FormView` subclass to handle multiple file :class:`~django.views.generic.edit.FormView` subclass to handle multiple file
uploads: uploads:
.. snippet:: .. code-block:: python
:filename: views.py :caption: views.py
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
from .forms import FileFieldForm from .forms import FileFieldForm

View File

@ -761,8 +761,8 @@ and one called ``'publisher-polls'``. Assume we have enhanced that application
so that it takes the instance namespace into consideration when creating and so that it takes the instance namespace into consideration when creating and
displaying polls. displaying polls.
.. snippet:: .. code-block:: python
:filename: urls.py :caption: urls.py
from django.urls import include, path from django.urls import include, path
@ -771,8 +771,8 @@ displaying polls.
path('publisher-polls/', include('polls.urls', namespace='publisher-polls')), path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
] ]
.. snippet:: .. code-block:: python
:filename: polls/urls.py :caption: polls/urls.py
from django.urls import path from django.urls import path
@ -830,8 +830,8 @@ at the same level as the ``urlpatterns`` attribute. You have to pass the actual
module, or a string reference to the module, to :func:`~django.urls.include`, module, or a string reference to the module, to :func:`~django.urls.include`,
not the list of ``urlpatterns`` itself. not the list of ``urlpatterns`` itself.
.. snippet:: .. code-block:: python
:filename: polls/urls.py :caption: polls/urls.py
from django.urls import path from django.urls import path
@ -844,8 +844,8 @@ not the list of ``urlpatterns`` itself.
... ...
] ]
.. snippet:: .. code-block:: python
:filename: urls.py :caption: urls.py
from django.urls import include, path from django.urls import include, path

View File

@ -429,8 +429,8 @@ configuration process for :ref:`Django's default logging
<default-logging-configuration>`. Here's an example that disables Django's <default-logging-configuration>`. Here's an example that disables Django's
logging configuration and then manually configures logging: logging configuration and then manually configures logging:
.. snippet:: .. code-block:: python
:filename: settings.py :caption: settings.py
LOGGING_CONFIG = None LOGGING_CONFIG = None

View File

@ -325,8 +325,8 @@ following structure::
Let's take a look inside a couple of those files: Let's take a look inside a couple of those files:
.. snippet:: .. code-block:: python
:filename: runtests.py :caption: runtests.py
#!/usr/bin/env python #!/usr/bin/env python
import os import os
@ -353,8 +353,8 @@ necessary to use the Django test runner. You may want to add
command-line options for controlling verbosity, passing in specific test command-line options for controlling verbosity, passing in specific test
labels to run, etc. labels to run, etc.
.. snippet:: .. code-block:: python
:filename: tests/test_settings.py :caption: tests/test_settings.py
SECRET_KEY = 'fake-key' SECRET_KEY = 'fake-key'
INSTALLED_APPS = [ INSTALLED_APPS = [