[
  {
    "path": "Python/DjangoBook/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = _build\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n\n.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\nclean:\n\t-rm -rf $(BUILDDIR)/*\n\nhtml:\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/TheDjangoBook.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/TheDjangoBook.qhc\"\n\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/TheDjangoBook\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/TheDjangoBook\"\n\t@echo \"# devhelp\"\n\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n"
  },
  {
    "path": "Python/DjangoBook/Procfile",
    "content": "web: gunicorn -kgevent -w4 -b0.0.0.0:$PORT app:app\n"
  },
  {
    "path": "Python/DjangoBook/README.rst",
    "content": "===============\nThe Django Book\n===============\n\nWelcome to the community edition of the Django Book!\n\nThis book was originally published by Apress in 2009, and covered Django 1.0. Since then, it's languished. We're working on getting the book updated to cover Django 1.4, 1.5, and beyond. But **we need your help**, so we're making this book — warts and all — open source in the hopes that it'll find love as a community project.\n\nSo, if you'd like to help out, send us a pull request!\n"
  },
  {
    "path": "Python/DjangoBook/app.py",
    "content": "\"\"\"\nThe simplest possible app that can serve these Sphinx docs and issue\nredirects for the previous URLs.\n\"\"\"\n\nimport static\nimport selector\nfrom unipath import FSPath as Path\n\napp = selector.Selector()\n\ndef redirect(to):\n    \"\"\"\n    Create a 301 redirect WSGI app.\n\n    `to` may contain str.format-style formatting which'll be formatted against\n    the routing arguments (wsgiorg.routing_args).\n    \"\"\"\n    def _redirect(environ, start_response):\n        args, kwargs = environ['wsgiorg.routing_args']\n        start_response('301 MOVED PERMANENTLY',\n                       [('Location', to.format(*args, **kwargs))])\n        return []\n    return _redirect\n\n# Redirects for old doc URLs, since Cool URIs Don't Change.\napp.add('/',                    GET=redirect('/en/2.0/index.html'))\napp.add('/license/',            GET=redirect('/en/2.0/license.html'))\napp.add('/about/',              GET=redirect('/en/2.0/frontmatter.html'))\napp.add('/en/1.0/',             GET=redirect('/en/2.0/index.html'))\napp.add('/en/1.0/{doc:chunk}/', GET=redirect('/en/2.0/{doc}.html'))\napp.add('/en/2.0/{doc:chunk}/', GET=redirect('/en/2.0/{doc}.html'))\n\n# Serve docs at \"/en/2.0\" still, to leave room for the future.\n# One of these days I'll actually do this, not just talk about it!\ndocs = static.Cling(Path(__file__).parent.child('_build', 'html'))\napp.add(\"/en/2.0|\", GET=docs)\n"
  },
  {
    "path": "Python/DjangoBook/appendixA.rst",
    "content": "======================================\nAppendix A: Model Definition Reference\n======================================\n\nChapter 5 explains the basics of defining models, and we use them throughout\nthe rest of the book. There is, however, a *huge* range of model options\navailable not covered elsewhere. This appendix explains each possible model\ndefinition option.\n\nNote that although these APIs are considered stable, the Django developers\nconsistently add new shortcuts and conveniences to the model definition. It's a\ngood idea to always check the latest documentation online at\nhttp://docs.djangoproject.com/.\n\nFields\n======\n\nThe most important part of a model -- and the only required part of a model --\nis the list of database fields it defines.\n\n.. admonition:: Field Name Restrictions\n\n    Django places only two restrictions on model field names:\n\n    1. A field name cannot be a Python reserved word, because that would result\n       in a Python syntax error. For example::\n\n           class Example(models.Model):\n               pass = models.IntegerField() # 'pass' is a reserved word!\n\n    2. A field name cannot contain more than one underscore in a row, due to\n       the way Django's query lookup syntax works. For example::\n\n           class Example(models.Model):\n               foo__bar = models.IntegerField() # 'foo__bar' has two underscores!\n\n    These limitations can be worked around, though, because your field name\n    doesn't necessarily have to match your database column name. See\n    \"db_column\", below.\n\n    SQL reserved words, such as ``join``, ``where``, or ``select``, *are* allowed\n    as model field names, because Django escapes all database table names and\n    column names in every underlying SQL query. It uses the quoting syntax of your\n    particular database engine.\n\nEach field in your model should be an instance of the appropriate ``Field``\nclass. Django uses the field class types to determine a few things:\n\n* The database column type (e.g., ``INTEGER``, ``VARCHAR``).\n\n* The widget to use in Django's forms and admin site, if you care to use it\n  (e.g., ``<input type=\"text\">``, ``<select>``).\n\n* The minimal validation requirements, which are used in Django's admin\n  interface and by forms.\n\nA complete list of field classes follows, sorted alphabetically. Note that\nrelationship fields (``ForeignKey``, etc.) are handled in the next section.\n\nAutoField\n---------\n\nAn ``IntegerField`` that automatically increments according to available IDs.\nYou usually won't need to use this directly; a primary key field will\nautomatically be added to your model if you don't specify otherwise.\n\nBooleanField\n------------\n\nA true/false field.\n\n.. admonition:: MySQL users...\n\n    A boolean field in MySQL is stored as a ``TINYINT`` column with a value of\n    either 0 or 1 (most databases have a proper ``BOOLEAN`` type instead). So,\n    for MySQL, only, when a ``BooleanField`` is retrieved from the database\n    and stored on a model attribute, it will have the values 1 or 0, rather\n    than ``True`` or ``False``. Normally, this shouldn't be a problem, since\n    Python guarantees that ``1 == True`` and ``0 == False`` are both true.\n    Just be careful if you're writing something like ``obj is True`` when\n    ``obj`` is a value from a boolean attribute on a model. If that model was\n    constructed using the ``mysql`` backend, the \"``is``\" test will fail.\n    Prefer an equality test (using \"``==``\") in cases like this.\n\nCharField\n---------\n\nA string field, for small- to large-sized strings.\n\nFor very large amounts of text, use ``TextField``.\n\n``CharField`` has one extra required argument: ``max_length``. This is the\nmaximum length (in characters) of the field. The ``max_length`` is enforced\nat the database level and in Django's validation.\n\nCommaSeparatedIntegerField\n--------------------------\n\nA field of integers separated by commas. As in ``CharField``, the\n``max_length`` argument is required.\n\nDateField\n---------\n\nA date, represented in Python by a ``datetime.date`` instance.\n\nDateTimeField\n-------------\n\nA date and time, represented in Python by a ``datetime.datetime`` instance.\n\nDecimalField\n------------\n\nA fixed-precision decimal number, represented in Python by a\n``decimal.Decimal`` instance. Has two **required** arguments:\n\n``max_digits``\n    The maximum number of digits allowed in the number\n\n``decimal_places``\n    The number of decimal places to store with the number\n\nFor example, to store numbers up to 999 with a resolution of 2 decimal places,\nyou'd use::\n\n    models.DecimalField(..., max_digits=5, decimal_places=2)\n\nAnd to store numbers up to approximately one billion with a resolution of 10\ndecimal places::\n\n    models.DecimalField(..., max_digits=19, decimal_places=10)\n\nWhen assigning to a ``DecimalField``, use either a ``decimal.Decimal`` object\nor a string -- not a Python float.\n\nEmailField\n----------\n\nA ``CharField`` that checks that the value is a valid e-mail address.\n\nFileField\n---------\n\nA file-upload field.\n\n.. note::\n    The ``primary_key`` and ``unique`` arguments are not supported, and will\n    raise a ``TypeError`` if used.\n\nHas one **required** argument:\n\n``upload_to``\n    A local filesystem path that will be appended to your ``MEDIA_ROOT``\n    setting to determine the value of the ``django.core.files.File.url``\n    attribute.\n\n    This path may contain \"strftime formatting\" (see the Python docs for the\n    ``time`` standard library module), which will be replaced using the\n    date/time of the file upload (so that uploaded files don't fill up the given\n    directory).\n\n    This may also be a callable, such as a function, which will be called to\n    obtain the upload path, including the filename. This callable must be able\n    to accept two arguments, and return a Unix-style path (with forward slashes)\n    to be passed along to the storage system. The two arguments that will be\n    passed are:\n\n    ======================  ===============================================\n    Argument                Description\n    ======================  ===============================================\n    ``instance``            An instance of the model where the\n                            ``FileField`` is defined. More specifically,\n                            this is the particular instance where the\n                            current file is being attached.\n\n                            In most cases, this object will not have been\n                            saved to the database yet, so if it uses the\n                            default ``AutoField``, *it might not yet have a\n                            value for its primary key field*.\n\n    ``filename``            The filename that was originally given to the\n                            file. This may or may not be taken into account\n                            when determining the final destination path.\n    ======================  ===============================================\n\nAlso has one optional argument:\n\n``storage``\n    Optional. A storage object, which handles the storage and retrieval of your\n    files.\n\nUsing a ``FileField`` or an ``ImageField`` (see below) in a model\ntakes a few steps:\n\n1. In your settings file, you'll need to define ``MEDIA_ROOT`` as the\n   full path to a directory where you'd like Django to store uploaded files.\n   (For performance, these files are not stored in the database.) Define\n   ``MEDIA_URL`` as the base public URL of that directory. Make sure\n   that this directory is writable by the Web server's user account.\n\n2. Add the ``FileField`` or ``ImageField`` to your model, making\n   sure to define the ``upload_to`` option to tell Django\n   to which subdirectory of ``MEDIA_ROOT`` it should upload files.\n\n3. All that will be stored in your database is a path to the file\n   (relative to ``MEDIA_ROOT``). You'll most likely want to use the\n   convenience ``url`` function provided by\n   Django. For example, if your ``ImageField`` is called ``mug_shot``,\n   you can get the absolute URL to your image in a template with\n   ``{{ object.mug_shot.url }}``.\n\nFor example, say your ``MEDIA_ROOT`` is set to ``'/home/media'``, and\n``upload_to`` is set to ``'photos/%Y/%m/%d'``. The ``'%Y/%m/%d'``\npart of ``upload_to`` is strftime formatting; ``'%Y'`` is the\nfour-digit year, ``'%m'`` is the two-digit month and ``'%d'`` is the two-digit\nday. If you upload a file on Jan. 15, 2007, it will be saved in the directory\n``/home/media/photos/2007/01/15``.\n\nIf you want to retrieve the upload file's on-disk filename, or a URL that refers\nto that file, or the file's size, you can use the\n``name``, ``url`` and ``size`` attributes.\n\nNote that whenever you deal with uploaded files, you should pay close attention\nto where you're uploading them and what type of files they are, to avoid\nsecurity holes. *Validate all uploaded files* so that you're sure the files are\nwhat you think they are. For example, if you blindly let somebody upload files,\nwithout validation, to a directory that's within your Web server's document\nroot, then somebody could upload a CGI or PHP script and execute that script by\nvisiting its URL on your site. Don't allow that.\n\nBy default, ``FileField`` instances are\ncreated as ``varchar(100)`` columns in your database. As with other fields, you\ncan change the maximum length using the ``max_length`` argument.\n\nFilePathField\n-------------\n\nA ``CharField`` whose choices are limited to the filenames in a certain\ndirectory on the filesystem. Has three special arguments, of which the first is\n**required**:\n\n``path``\n    Required. The absolute filesystem path to a directory from which this\n    ``FilePathField`` should get its choices. Example: ``\"/home/images\"``.\n\n``match``\n    Optional. A regular expression, as a string, that ``FilePathField``\n    will use to filter filenames. Note that the regex will be applied to the\n    base filename, not the full path. Example: ``\"foo.*\\.txt$\"``, which will\n    match a file called ``foo23.txt`` but not ``bar.txt`` or ``foo23.gif``.\n\n``recursive``\n    Optional. Either ``True`` or ``False``. Default is ``False``. Specifies\n    whether all subdirectories of ``path`` should be included.\n\nOf course, these arguments can be used together.\n\nThe one potential gotcha is that ``match`` applies to the\nbase filename, not the full path. So, this example::\n\n    FilePathField(path=\"/home/images\", match=\"foo.*\", recursive=True)\n\n...will match ``/home/images/bar/foo.gif`` but not ``/home/images/foo/bar.gif``\nbecause the ``match`` applies to the base filename\n(``foo.gif`` and ``bar.gif``).\n\nBy default, ``FilePathField`` instances are\ncreated as ``varchar(100)`` columns in your database. As with other fields, you\ncan change the maximum length using the ``max_length`` argument.\n\nFloatField\n----------\n\nA floating-point number represented in Python by a ``float`` instance.\n\nImageField\n----------\n\nLike ``FileField``, but validates that the uploaded object is a valid\nimage. Has two extra optional arguments:\n\n``height_field``\n    Name of a model field which will be auto-populated with the height of the\n    image each time the model instance is saved.\n\n``width_field``\n    Name of a model field which will be auto-populated with the width of the\n    image each time the model instance is saved.\n\nIn addition to the special attributes that are available for FileField``,\nan ``ImageField`` also has ``height`` and ``width`` attributes, both of which\ncorrespond to the image's height and width in pixels.\n\nRequires the Python Imaging Library, available at http://www.pythonware.com/products/pil/.\n\nBy default, ``ImageField`` instances are\ncreated as ``varchar(100)`` columns in your database. As with other fields, you\ncan change the maximum length using the ``max_length`` argument.\n\nIntegerField\n------------\n\nAn integer.\n\nIPAddressField\n--------------\n\nAn IP address, in string format (e.g. ``'192.0.2.30'``).\n\nNullBooleanField\n----------------\n\nLike a ``BooleanField``, but allows ``NULL`` as one of the options. Use\nthis instead of a ``BooleanField`` with ``null=True``.\n\nPositiveIntegerField\n--------------------\n\nLike an ``IntegerField``, but must be positive.\n\nPositiveSmallIntegerField\n-------------------------\n\nLike a ``PositiveIntegerField``, but only allows values under a certain\n(database-dependent) point.\n\nSlugField\n---------\n\n\"Slug\" is a newspaper term. A slug is a short label for something,\ncontaining only letters, numbers, underscores or hyphens. They're generally used\nin URLs.\n\nLike a ``CharField``, you can specify ``max_length``. If ``max_length`` is not\nspecified, Django will use a default length of 50.\n\nImplies setting ``db_index`` to ``True``.\n\nSmallIntegerField\n-----------------\n\nLike an ``IntegerField``, but only allows values under a certain\n(database-dependent) point.\n\nTextField\n---------\n\nA large text field.\n\nAlso see ``CharField`` for storing smaller bits of text.\n\nTimeField\n---------\n\nA time, represented in Python by a ``datetime.time`` instance. Accepts the same\nauto-population options as ``DateField``.\n\nURLField\n--------\n\nA ``CharField`` for a URL. Has one extra optional argument:\n\n``verify_exists``\n    If ``True`` (the default), the URL given will be checked for existence\n    (i.e., the URL actually loads and doesn't give a 404 response). It should\n    be noted that when using the single-threaded development server, validating\n    a url being served by the same server will hang.\n    This should not be a problem for multithreaded servers.\n\nLike all ``CharField`` subclasses, ``URLField`` takes the optional\n``max_length`` argument. If you don't specify\n``max_length``, a default of 200 is used.\n\nXMLField\n--------\n\nA ``TextField`` that checks that the value is valid XML that matches a\ngiven schema. Takes one required argument:\n\n``schema_path``\n    The filesystem path to a RelaxNG schema against which to validate the\n    field. For more on RelaxNG, see http://www.relaxng.org/.\n\nUniversal Field Options\n=======================\n\nThe following arguments are available to all field types. All are optional.\n\nnull\n----\n\nIf ``True``, Django will store empty values as ``NULL`` in the database. If\n``False``, saving empty values will likely result in a database error. Default\nis ``False``.\n\nNote that empty string values will always get stored as empty strings, not as\n``NULL``. Only use ``null=True`` for non-string fields such as integers,\nbooleans and dates. For both types of fields, you will also need to set\n``blank=True`` if you wish to permit empty values in forms, as the\n``null`` parameter only affects database storage (see\n``blank``).\n\nAvoid using ``null`` on string-based fields such as\n``CharField`` and ``TextField`` unless you have an excellent reason.\nIf a string-based field has ``null=True``, that means it has two possible values\nfor \"no data\": ``NULL``, and the empty string. In most cases, it's redundant to\nhave two possible values for \"no data;\" Django's convention is to use the empty\nstring, not ``NULL``.\n\n.. note::\n\n    When using the Oracle database backend, the ``null=True`` option will be\n    coerced for string-based fields that have the empty string as a possible\n    value, and the value ``NULL`` will be stored to denote the empty string.\n\nFor more on this, see the section \"Making Date and Numeric Fields Optional\" in\nChapter 6.\n\nblank\n-----\n\nIf ``True``, the field is allowed to be blank. Default is ``False``.\n\nNote that this is different than ``null``. ``null`` is\npurely database-related, whereas ``blank`` is validation-related. If\na field has ``blank=True``, validation on Django's admin site will allow entry\nof an empty value. If a field has ``blank=False``, the field will be required.\n\nchoices\n-------\n\nAn iterable (e.g., a list or tuple) of 2-tuples to use as choices for this\nfield.\n\nA choices list looks like this::\n\n    YEAR_IN_SCHOOL_CHOICES = (\n        ('FR', 'Freshman'),\n        ('SO', 'Sophomore'),\n        ('JR', 'Junior'),\n        ('SR', 'Senior'),\n        ('GR', 'Graduate'),\n    )\n\nThe first element in each tuple is the actual value to be stored. The second\nelement is the human-readable name for the option.\n\nThe choices list can be defined either as part of your model class::\n\n    class Foo(models.Model):\n        GENDER_CHOICES = (\n            ('M', 'Male'),\n            ('F', 'Female'),\n        )\n        gender = models.CharField(max_length=1, choices=GENDER_CHOICES)\n\nor outside your model class altogether::\n\n    GENDER_CHOICES = (\n        ('M', 'Male'),\n        ('F', 'Female'),\n    )\n    class Foo(models.Model):\n        gender = models.CharField(max_length=1, choices=GENDER_CHOICES)\n\nYou can also collect your available choices into named groups that can\nbe used for organizational purposes in a form::\n\n    MEDIA_CHOICES = (\n        ('Audio', (\n                ('vinyl', 'Vinyl'),\n                ('cd', 'CD'),\n            )\n        ),\n        ('Video', (\n                ('vhs', 'VHS Tape'),\n                ('dvd', 'DVD'),\n            )\n        ),\n        ('unknown', 'Unknown'),\n    )\n\nThe first element in each tuple is the name to apply to the group. The\nsecond element is an iterable of 2-tuples, with each 2-tuple containing\na value and a human-readable name for an option. Grouped options may be\ncombined with ungrouped options within a single list (such as the\n`unknown` option in this example).\n\nFinally, note that choices can be any iterable object -- not necessarily a list\nor tuple. This lets you construct choices dynamically. But if you find yourself\nhacking ``choices`` to be dynamic, you're probably better off using a\nproper database table with a `ForeignKey``. ``choices`` is\nmeant for static data that doesn't change much, if ever.\n\ndb_column\n---------\n\nThe name of the database column to use for this field. If this isn't given,\nDjango will use the field's name.\n\nIf your database column name is an SQL reserved word, or contains\ncharacters that aren't allowed in Python variable names -- notably, the\nhyphen -- that's OK. Django quotes column and table names behind the\nscenes.\n\ndb_index\n--------\n\nIf ``True``, ``django-admin.py sqlindexes`` will output a\n``CREATE INDEX`` statement for this field.\n\ndb_tablespace\n-------------\n\nThe name of the database tablespace to use for this field's index, if this field\nis indexed. The default is the project's ``DEFAULT_INDEX_TABLESPACE``\nsetting, if set, or the ``db_tablespace`` of the model, if any. If\nthe backend doesn't support tablespaces, this option is ignored.\n\ndefault\n-------\n\nThe default value for the field. This can be a value or a callable object. If\ncallable it will be called every time a new object is created.\n\neditable\n--------\n\nIf ``False``, the field will not be editable in the admin or via forms\nautomatically generated from the model class. Default is ``True``.\n\nhelp_text\n---------\n\nExtra \"help\" text to be displayed under the field on the object's admin form.\nIt's useful for documentation even if your object doesn't have an admin form.\n\nNote that this value is *not* HTML-escaped when it's displayed in the admin\ninterface. This lets you include HTML in ``help_text`` if you so\ndesire. For example::\n\n    help_text=\"Please use the following format: <em>YYYY-MM-DD</em>.\"\n\nAlternatively you can use plain text and\n``django.utils.html.escape()`` to escape any HTML special characters.\n\nprimary_key\n-----------\n\nIf ``True``, this field is the primary key for the model.\n\nIf you don't specify ``primary_key=True`` for any fields in your model, Django\nwill automatically add an ``AutoField`` to hold the primary key, so you\ndon't need to set ``primary_key=True`` on any of your fields unless you want to\noverride the default primary-key behavior.\n\n``primary_key=True`` implies ``null=False`` and ``unique=True``.\nOnly one primary key is allowed on an object.\n\nunique\n------\n\nIf ``True``, this field must be unique throughout the table.\n\nThis is enforced at the database level and at the level of forms created with\n``ModelForm`` (including forms in the Django admin site). If\nyou try to save a model with a duplicate value in a ``unique``\nfield, an ``IntegrityError`` will be raised by the model's\n``save`` method.\n\nThis option is valid on all field types except ``ManyToManyField``,\n``FileField`` and ``ImageField``.\n\nunique_for_date\n---------------\n\nSet this to the name of a ``DateField`` or ``DateTimeField`` to\nrequire that this field be unique for the value of the date field.\n\nFor example, if you have a field ``title`` that has\n``unique_for_date=\"pub_date\"``, then Django wouldn't allow the entry of two\nrecords with the same ``title`` and ``pub_date``.\n\nThis is enforced at the level of forms created with ``ModelForm`` (including\nforms in the Django admin site) but not at the database level.\n\nunique_for_month\n----------------\n\nLike ``unique_for_date``, but requires the field to be unique with\nrespect to the month.\n\nunique_for_year\n---------------\n\nLike ``unique_for_date`` and ``unique_for_month``.\n\nverbose_name\n------------\n\nA human-readable name for the field. If the verbose name isn't given, Django\nwill automatically create it using the field's attribute name, converting\nunderscores to spaces.\n\nRelationships\n=============\n\nClearly, the power of relational databases lies in relating tables to each\nother. Django offers ways to define the three most common types of database\nrelationships: many-to-one, many-to-many, and one-to-one.\n\nForeignKey\n----------\n\nA many-to-one relationship. Requires a positional argument: the class to which\nthe model is related.\n\nTo create a recursive relationship -- an object that has a many-to-one\nrelationship with itself -- use ``models.ForeignKey('self')``.\n\nIf you need to create a relationship on a model that has not yet been defined,\nyou can use the name of the model, rather than the model object itself::\n\n    class Car(models.Model):\n        manufacturer = models.ForeignKey('Manufacturer')\n        # ...\n\n    class Manufacturer(models.Model):\n        # ...\n\nNote, however, that this only refers to models in the same ``models.py`` file.\n\nTo refer to models defined in another\napplication, you must instead explicitly specify the application label. For\nexample, if the ``Manufacturer`` model above is defined in another application\ncalled ``production``, you'd need to use::\n\n    class Car(models.Model):\n        manufacturer = models.ForeignKey('production.Manufacturer')\n\nBehind the scenes, Django appends ``\"_id\"`` to the field name to create its\ndatabase column name. In the above example, the database table for the ``Car``\nmodel will have a ``manufacturer_id`` column. (You can change this explicitly by\nspecifying ``db_column``) However, your code should never have to\ndeal with the database column name, unless you write custom SQL. You'll always\ndeal with the field names of your model object.\n\n``ForeignKey`` accepts an extra set of arguments -- all optional -- that\ndefine the details of how the relation works.\n\n``limit_choices_to``\n    A dictionary of lookup arguments and values\n    that limit the available admin choices for this object. Use this with\n    functions from the Python ``datetime`` module to limit choices of objects by\n    date. For example::\n\n        limit_choices_to = {'pub_date__lte': datetime.now}\n\n    only allows the choice of related objects with a ``pub_date`` before the\n    current date/time to be chosen.\n\n    ``limit_choices_to`` has no effect on the inline FormSets that are created\n    to display related objects in the admin.\n\n``related_name``\n    The name to use for the relation from the related object back to this one.\n\n``to_field``\n    The field on the related object that the relation is to. By default, Django\n    uses the primary key of the related object.\n\nManyToManyField\n---------------\n\nA many-to-many relationship. Requires a positional argument: the class to which\nthe model is related. This works exactly the same as it does for\n``ForeignKey``, including all the options regarding recursive relationships\nand lazy relationships.\n\nBehind the scenes, Django creates an intermediary join table to represent the\nmany-to-many relationship. By default, this table name is generated using the\nnames of the two tables being joined. Since some databases don't support table\nnames above a certain length, these table names will be automatically\ntruncated to 64 characters and a uniqueness hash will be used. This means you\nmight see table names like ``author_books_9cdf4``; this is perfectly normal.\nYou can manually provide the name of the join table using the\n``db_table`` option.\n\n``ManyToManyField`` accepts an extra set of arguments -- all optional --\nthat control how the relationship functions.\n\n``related_name``\n    Same as ``related_name`` in ``ForeignKey``.\n\n``limit_choices_to``\n    Same as ``limit_choices_to`` in ``ForeignKey``.\n\n    ``limit_choices_to`` has no effect when used on a ``ManyToManyField`` with a\n    custom intermediate table specified using the\n    ``through`` paramter.\n\n``symmetrical``\n    Only used in the definition of ManyToManyFields on self. Consider the\n    following model::\n\n        class Person(models.Model):\n            friends = models.ManyToManyField(\"self\")\n\n    When Django processes this model, it identifies that it has a\n    ``ManyToManyField`` on itself, and as a result, it doesn't add a\n    ``person_set`` attribute to the ``Person`` class. Instead, the\n    ``ManyToManyField`` is assumed to be symmetrical -- that is, if I am\n    your friend, then you are my friend.\n\n    If you do not want symmetry in many-to-many relationships with ``self``, set\n    ``symmetrical`` to ``False``. This will force Django to\n    add the descriptor for the reverse relationship, allowing\n    ``ManyToManyField`` relationships to be non-symmetrical.\n\n``through``\n    Django will automatically generate a table to manage many-to-many\n    relationships. However, if you want to manually specify the intermediary\n    table, you can use the ``through`` option to specify\n    the Django model that represents the intermediate table that you want to\n    use.\n\n    The most common use for this option is when you want to associate\n    extra data with a many-to-many relationship.\n\n``db_table``\n    The name of the table to create for storing the many-to-many data. If this\n    is not provided, Django will assume a default name based upon the names of\n    the two tables being joined.\n\nOneToOneField\n-------------\n\nA one-to-one relationship. Conceptually, this is similar to a\n``ForeignKey`` with ``unique=True``, but the\n\"reverse\" side of the relation will directly return a single object.\n\nThis is most useful as the primary key of a model which \"extends\"\nanother model in some way; multi-table-inheritance is\nimplemented by adding an implicit one-to-one relation from the child\nmodel to the parent model, for example.\n\nOne positional argument is required: the class to which the model will be\nrelated. This works exactly the same as it does for ``ForeignKey``,\nincluding all the options regarding recursive relationships and lazy\nrelationships.\n\nAdditionally, ``OneToOneField`` accepts all of the extra arguments\naccepted by ``ForeignKey``, plus one extra argument:\n\n``parent_link``\n    When ``True`` and used in a model which inherits from another\n    (concrete) model, indicates that this field should be used as the\n    link back to the parent class, rather than the extra\n    ``OneToOneField`` which would normally be implicitly created by\n    subclassing.\n\nModel Metadata Options\n======================\n\nModel-specific metadata lives in a ``class Meta`` defined in the body of your\nmodel class::\n\n    class Book(models.Model):\n        title = models.CharField(maxlength=100)\n\n        class Meta:\n            # model metadata options go here\n            ...\n\nModel metadata is \"anything that's not a field,\" such as ordering options and so forth.\n\nThe sections that follow present a list of all possible ``Meta`` options.\nNo options are required. Adding ``class Meta`` to a model is completely optional.\n\nabstract\n--------\n\nIf ``True``, this model will be an abstract base class. See the Django\ndocumentation for more on abstract base classes.\n\ndb_table\n--------\n\nThe name of the database table to use for the model::\n\n    db_table = 'music_album'\n\nTable names\n~~~~~~~~~~~\n\nTo save you time, Django automatically derives the name of the database table\nfrom the name of your model class and the app that contains it. A model's\ndatabase table name is constructed by joining the model's \"app label\" -- the\nname you used in ``manage.py startapp`` -- to the model's class name, with an\nunderscore between them.\n\nFor example, if you have an app ``bookstore`` (as created by\n``manage.py startapp bookstore``), a model defined as ``class Book`` will have\na database table named ``bookstore_book``.\n\nTo override the database table name, use the ``db_table`` parameter in\n``class Meta``.\n\nIf your database table name is an SQL reserved word, or contains characters that\naren't allowed in Python variable names -- notably, the hyphen -- that's OK.\nDjango quotes column and table names behind the scenes.\n\ndb_tablespace\n-------------\n\nThe name of the database tablespace to use for the model. If the backend doesn't\nsupport tablespaces, this option is ignored.\n\nget_latest_by\n-------------\n\nThe name of a ``DateField`` or ``DateTimeField`` in the model. This\nspecifies the default field to use in your model ``Manager``'s\n``latest`` method.\n\nExample::\n\n    get_latest_by = \"order_date\"\n\nmanaged\n-------\n\nDefaults to ``True``, meaning Django will create the appropriate database\ntables in ``django-admin.py syncdb`` and remove them as part of a ``reset``\nmanagement command. That is, Django *manages* the database tables' lifecycles.\n\nIf ``False``, no database table creation or deletion operations will be\nperformed for this model. This is useful if the model represents an existing\ntable or a database view that has been created by some other means. This is\nthe *only* difference when ``managed`` is ``False``. All other aspects of\nmodel handling are exactly the same as normal. This includes\n\n1. Adding an automatic primary key field to the model if you don't declare\n   it. To avoid confusion for later code readers, it's recommended to\n   specify all the columns from the database table you are modeling when\n   using unmanaged models.\n\n2. If a model with ``managed=False`` contains a\n   ``ManyToManyField`` that points to another\n   unmanaged model, then the intermediary table for the many-to-many join\n   will also not be created. However, the intermediary table between one\n   managed and one unmanaged model *will* be created.\n\n   If you need to change this default behavior, create the intermediary\n   table as an explicit model (with ``managed`` set as needed) and use the\n   ``through`` attribute to make the relation use your\n   custom model.\n\nFor tests involving models with ``managed=False``, it's up to you to ensure\nthe correct tables are created as part of the test setup.\n\nIf you're interested in changing the Python-level behavior of a model class,\nyou *could* use ``managed=False`` and create a copy of an existing model.\nHowever, there's a better approach for that situation: proxy-models.\n\nordering\n--------\n\nThe default ordering for the object, for use when obtaining lists of objects::\n\n    ordering = ['-order_date']\n\nThis is a tuple or list of strings. Each string is a field name with an optional\n\"-\" prefix, which indicates descending order. Fields without a leading \"-\" will\nbe ordered ascending. Use the string \"?\" to order randomly.\n\n.. note::\n\n    Regardless of how many fields are in ``ordering``, the admin\n    site uses only the first field.\n\nFor example, to order by a ``pub_date`` field ascending, use this::\n\n    ordering = ['pub_date']\n\nTo order by ``pub_date`` descending, use this::\n\n    ordering = ['-pub_date']\n\nTo order by ``pub_date`` descending, then by ``author`` ascending, use this::\n\n    ordering = ['-pub_date', 'author']\n\nproxy\n-----\n\nIf set to ``True``, a model which subclasses another model will be treated as\na proxy model. For more on proxy models, see the Django documentation.\n\nunique_together\n---------------\n\nSets of field names that, taken together, must be unique::\n\n    unique_together = ((\"driver\", \"restaurant\"),)\n\nThis is a list of lists of fields that must be unique when considered together.\nIt's used by ``ModelForm`` forms (including forms in the Django admin site) and\nis enforced at the database level (i.e., the appropriate ``UNIQUE`` statements\nare included in the ``CREATE TABLE`` statement).\n\nFor convenience, unique_together can be a single sequence when dealing with a single\nset of fields::\n\n    unique_together = (\"driver\", \"restaurant\")\n\nverbose_name\n------------\n\nA human-readable name for the object, singular::\n\n    verbose_name = \"pizza\"\n\nIf this isn't given, Django will use a munged version of the class name:\n``CamelCase`` becomes ``camel case``.\n\nverbose_name_plural\n-------------------\n\nThe plural name for the object::\n\n    verbose_name_plural = \"stories\"\n\nIf this isn't given, Django will use ``verbose_name`` + ``\"s\"``.\n"
  },
  {
    "path": "Python/DjangoBook/appendixB.rst",
    "content": "==================================\nAppendix B: Database API Reference\n==================================\n\nDjango's database API is the other half of the model API discussed in Appendix\nA. Once you've defined a model, you'll use this API any time you need to\naccess the database. You've seen examples of this API in use throughout the\nbook; this appendix explains all the various options in detail.\n\nLike the model APIs discussed in Appendix A, though these APIs are considered\nvery stable, the Django developers consistently add new shortcuts and\nconveniences. It's a good idea to always check the latest documentation online,\navailable at http://docs.djangoproject.com/.\n\nThroughout this reference, we'll refer to the following models, which might form\na simple blog application::\n\n    from django.db import models\n\n    class Blog(models.Model):\n        name = models.CharField(max_length=100)\n        tagline = models.TextField()\n\n        def __unicode__(self):\n            return self.name\n\n    class Author(models.Model):\n        name = models.CharField(max_length=50)\n        email = models.EmailField()\n\n        def __unicode__(self):\n            return self.name\n\n    class Entry(models.Model):\n        blog = models.ForeignKey(Blog)\n        headline = models.CharField(max_length=255)\n        body_text = models.TextField()\n        pub_date = models.DateTimeField()\n        authors = models.ManyToManyField(Author)\n\n        def __unicode__(self):\n            return self.headline\n\nCreating Objects\n================\n\nTo create an object, instantiate it using keyword arguments to the model class, and\nthen call ``save()`` to save it to the database::\n\n    >>> from mysite.blog.models import Blog\n    >>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')\n    >>> b.save()\n\nThis performs an ``INSERT`` SQL statement behind the scenes. Django doesn't hit\nthe database until you explicitly call ``save()``.\n\nThe ``save()`` method has no return value.\n\nTo create an object and save it all in one step, see the ``create`` manager\nmethod.\n\nWhat Happens When You Save?\n---------------------------\n\nWhen you save an object, Django performs the following steps:\n\n#. **Emit a pre_save signal.** This provides a notification that\n   an object is about to be saved. You can register a listener that\n   will be invoked whenever this signal is emitted. Check the online\n   documentation for more on signals.\n\n#. **Preprocess the data.** Each field on the object is asked to\n   perform any automated data modification that the field may need\n   to perform.\n\n   Most fields do *no* preprocessing -- the field data is kept as is.\n   Preprocessing is only used on fields that have special behavior,\n   like file fields.\n\n#. **Prepare the data for the database.** Each field is asked to provide\n   its current value in a data type that can be written to the database.\n\n   Most fields require no data preparation. Simple data types, such as\n   integers and strings, are \"ready to write\" as a Python object. However,\n   more complex data types often require some modification. For example,\n   ``DateFields`` use a Python ``datetime`` object to store data.\n   Databases don't store ``datetime`` objects, so the field value\n   must be converted into an ISO-compliant date string for insertion\n   into the database.\n\n#. **Insert the data into the database.** The preprocessed, prepared\n   data is then composed into an SQL statement for insertion into the\n   database.\n\n#. **Emit a post_save signal.** As with the ``pre_save`` signal, this\n   is used to provide notification that an object has been successfully\n   saved.\n\nAutoincrementing Primary Keys\n------------------------------\n\nFor convenience, each model is given an autoincrementing primary key field\nnamed ``id`` unless you explicitly specify ``primary_key=True`` on a field (see\nthe section titled \"AutoField\" in Appendix A).\n\nIf your model has an ``AutoField``, that autoincremented value will be\ncalculated and saved as an attribute on your object the first time you call\n``save()``::\n\n    >>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')\n    >>> b2.id     # Returns None, because b doesn't have an ID yet.\n    None\n\n    >>> b2.save()\n    >>> b2.id     # Returns the ID of your new object.\n    14\n\nThere's no way to tell what the value of an ID will be before you call\n``save()``, because that value is calculated by your database, not by Django.\n\nIf a model has an ``AutoField`` but you want to define a new object's ID\nexplicitly when saving, just define it explicitly before saving, rather than\nrelying on the autoassignment of the ID::\n\n    >>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')\n    >>> b3.id\n    3\n    >>> b3.save()\n    >>> b3.id\n    3\n\nIf you assign auto-primary-key values manually, make sure not to use an\nalready existing primary key value! If you create a new object with an explicit\nprimary key value that already exists in the database, Django will assume you're\nchanging the existing record rather than creating a new one.\n\nGiven the preceding ``'Cheddar Talk'`` blog example, this example would override the\nprevious record in the database::\n\n    >>> b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')\n    >>> b4.save()  # Overrides the previous blog with ID=3!\n\nExplicitly specifying auto-primary-key values is mostly useful for bulk-saving\nobjects, when you're confident you won't have primary key collision.\n\nSaving Changes to Objects\n=========================\n\nTo save changes to an object that's already in the database, use ``save()``.\n\nGiven a ``Blog`` instance ``b5`` that has already been saved to the database,\nthis example changes its name and updates its record in the database::\n\n    >>> b5.name = 'New name'\n    >>> b5.save()\n\nThis performs an ``UPDATE`` SQL statement behind the scenes. Again, Django\ndoesn't hit the database until you explicitly call ``save()``.\n\n.. admonition:: How Django Knows When to ``UPDATE`` and When to ``INSERT``\n\n    You may have noticed that Django database objects use the same ``save()`` method\n    for creating and changing objects. Django abstracts the need to use\n    ``INSERT`` or ``UPDATE`` SQL statements. Specifically, when you call\n    ``save()``, Django follows this algorithm:\n\n    * If the object's primary key attribute is set to a value that evaluates\n      to ``True`` (i.e., a value other than ``None`` or the empty string),\n      Django executes a ``SELECT`` query to determine whether a record with\n      the given primary key already exists.\n\n    * If the record with the given primary key does already exist, Django\n      executes an ``UPDATE`` query.\n\n    * If the object's primary key attribute is *not* set, or if it's set but\n      a record doesn't exist, Django executes an ``INSERT``.\n\n    Because of this, you should be careful not to specify a primary key value\n    explicitly when saving new objects if you cannot guarantee the primary key\n    value is unused.\n\nUpdating ``ForeignKey`` fields works exactly the same way; simply assign an\nobject of the right type to the field in question::\n\n    >>> joe = Author.objects.create(name=\"Joe\")\n    >>> entry.author = joe\n    >>> entry.save()\n\nDjango will complain if you try to assign an object of the wrong type.\n\nRetrieving Objects\n==================\n\nThroughout the book you've seen objects retrieved using code like the following::\n\n    >>> blogs = Blog.objects.filter(author__name__contains=\"Joe\")\n\nThere are quite a few \"moving parts\" behind the scenes here: when you\nretrieve objects from the database, you're actually constructing a ``QuerySet``\nusing the model's ``Manager``. This ``QuerySet`` knows how to execute SQL and\nreturn the requested objects.\n\nAppendix A looked at both of these objects from a model-definition point of\nview; now we'll look at how they operate.\n\nA ``QuerySet`` represents a collection of objects from your database. It can\nhave zero, one, or many *filters* -- criteria that narrow down the collection\nbased on given parameters. In SQL terms, a ``QuerySet`` equates to a ``SELECT``\nstatement, and a filter is a ``WHERE``.\n\nYou get a ``QuerySet`` by using your model's ``Manager``. Each model has at\nleast one ``Manager``, and it's called ``objects`` by default. Access it\ndirectly via the model class, like so::\n\n    >>> Blog.objects\n    <django.db.models.manager.Manager object at 0x137d00d>\n\n``Manager``\\s are accessible only via model classes, rather than from model\ninstances, to enforce a separation between \"table-level\" operations and\n\"record-level\" operations::\n\n    >>> b = Blog(name='Foo', tagline='Bar')\n    >>> b.objects\n    Traceback (most recent call last):\n      File \"<stdin>\", line 1, in <module>\n    AttributeError: Manager isn't accessible via Blog instances.\n\nThe ``Manager`` is the main source of ``QuerySet``\\s for a model. It acts as a\n\"root\" ``QuerySet`` that describes all objects in the model's database table.\nFor example, ``Blog.objects`` is the initial ``QuerySet`` that contains all\n``Blog`` objects in the database.\n\nCaching and QuerySets\n=====================\n\nEach ``QuerySet`` contains a cache, to minimize database access. It's important\nto understand how it works, in order to write the most efficient code.\n\nIn a newly created ``QuerySet``, the cache is empty. The first time a\n``QuerySet`` is evaluated -- and, hence, a database query happens -- Django\nsaves the query results in the ``QuerySet``'s cache and returns the results\nthat have been explicitly requested (e.g., the next element, if the\n``QuerySet`` is being iterated over). Subsequent evaluations of the\n``QuerySet`` reuse the cached results.\n\nKeep this caching behavior in mind, because it may bite you if you don't use\nyour ``QuerySet``\\s correctly. For example, the following will create two\n``QuerySet``\\s, evaluate them, and throw them away::\n\n    print [e.headline for e in Entry.objects.all()]\n    print [e.pub_date for e in Entry.objects.all()]\n\nThat means the same database query will be executed twice, effectively doubling\nyour database load. Also, there's a possibility the two lists may not include\nthe same database records, because an ``Entry`` may have been added or deleted\nin the split second between the two requests.\n\nTo avoid this problem, simply save the ``QuerySet`` and reuse it::\n\n    queryset = Poll.objects.all()\n    print [p.headline for p in queryset] # Evaluate the query set.\n    print [p.pub_date for p in queryset] # Reuse the cache from the evaluation.\n\nFiltering Objects\n=================\n\nThe simplest way to retrieve objects from a table is to get all of them.\nTo do this, use the ``all()`` method on a ``Manager``::\n\n    >>> Entry.objects.all()\n\nThe ``all()`` method returns a ``QuerySet`` of all the objects in the database.\n\nUsually, though, you'll need to select only a subset of the complete set of\nobjects. To create such a subset, you refine the initial ``QuerySet``, adding filter\nconditions. You'll usually do this using the ``filter()`` and/or ``exclude()``\nmethods::\n\n    >>> y2006 = Entry.objects.filter(pub_date__year=2006)\n    >>> not2006 = Entry.objects.exclude(pub_date__year=2006)\n\n``filter()`` and ``exclude()`` both take *field lookup* arguments, which are\ndiscussed in detail shortly.\n\nChaining Filters\n----------------\n\nThe result of refining a ``QuerySet`` is itself a ``QuerySet``, so it's\npossible to chain refinements together, for example::\n\n    >>> qs = Entry.objects.filter(headline__startswith='What')\n    >>> qs = qs.exclude(pub_date__gte=datetime.datetime.now())\n    >>> qs = qs.filter(pub_date__gte=datetime.datetime(2005, 1, 1))\n\nThis takes the initial ``QuerySet`` of all entries in the database, adds a\nfilter, then an exclusion, and then another filter. The final result is a\n``QuerySet`` containing all entries with a headline that starts with \"What\"\nthat were published between January 1, 2005, and the current day.\n\nIt's important to point out here that ``QuerySets`` are lazy -- the act of creating\na ``QuerySet`` doesn't involve any database activity. In fact, the three preceding lines\ndon't make *any* database calls; you can chain filters together all day\nlong and Django won't actually run the query until the ``QuerySet`` is\n*evaluated*.\n\nYou can evaluate a ``QuerySet`` in any following ways:\n\n* *Iterating*: A ``QuerySet`` is iterable, and it executes its database query the first\n  time you iterate over it. For example, the following ``QuerySet`` isn't evaluated\n  until it's iterated over in the ``for`` loop::\n\n      qs = Entry.objects.filter(pub_date__year=2006)\n      qs = qs.filter(headline__icontains=\"bill\")\n      for e in qs:\n          print e.headline\n\n  This prints all headlines from 2006 that contain \"bill\" but causes\n  only one database hit.\n\n* *Printing it*: A ``QuerySet`` is evaluated when you call ``repr()`` on it.\n  This is for convenience in the Python interactive interpreter, so you can\n  immediately see your results when using the API interactively.\n\n* *Slicing*: As explained in the upcoming \"Limiting QuerySets\" section,\n  a ``QuerySet`` can be sliced using Python's array-slicing syntax.\n  Usually slicing a ``QuerySet`` returns another (unevaluated)``QuerySet``,\n  but Django will execute the database query if you use the \"step\"\n  parameter of slice syntax.\n\n* *Converting to a list*: You can force evaluation of a ``QuerySet`` by calling\n  ``list()`` on it, for example::\n\n      >>> entry_list = list(Entry.objects.all())\n\n  Be warned, though, that this could have a large memory overhead, because\n  Django will load each element of the list into memory. In contrast,\n  iterating over a ``QuerySet`` will take advantage of your database to load\n  data and instantiate objects only as you need them.\n\n.. admonition:: Filtered QuerySets Are Unique\n\n    Each time you refine a ``QuerySet``, you get a brand-new ``QuerySet`` that\n    is in no way bound to the previous ``QuerySet``. Each refinement creates a\n    separate and distinct ``QuerySet`` that can be stored, used, and reused::\n\n        q1 = Entry.objects.filter(headline__startswith=\"What\")\n        q2 = q1.exclude(pub_date__gte=datetime.now())\n        q3 = q1.filter(pub_date__gte=datetime.now())\n\n    These three ``QuerySets`` are separate. The first is a base ``QuerySet``\n    containing all entries that contain a headline starting with \"What\". The\n    second is a subset of the first, with an additional criterion that excludes\n    records whose ``pub_date`` is greater than now. The third is a subset of the\n    first, with an additional criterion that selects only the records whose\n    ``pub_date`` is greater than now. The initial ``QuerySet`` (``q1``) is\n    unaffected by the refinement process.\n\nLimiting QuerySets\n------------------\n\nUse Python's array-slicing syntax to limit your ``QuerySet`` to a certain number\nof results. This is the equivalent of SQL's ``LIMIT`` and ``OFFSET`` clauses.\n\nFor example, this returns the first five entries (``LIMIT 5``)::\n\n    >>> Entry.objects.all()[:5]\n\nThis returns the sixth through tenth entries (``OFFSET 5 LIMIT 5``)::\n\n    >>> Entry.objects.all()[5:10]\n\nGenerally, slicing a ``QuerySet`` returns a new ``QuerySet`` -- it doesn't\nevaluate the query. An exception is if you use the \"step\" parameter\nof Python slice syntax. For example, this would actually execute the query in\norder to return a list of every *second* object of the first ten::\n\n    >>> Entry.objects.all()[:10:2]\n\nTo retrieve a *single* object rather than a list (e.g., ``SELECT foo FROM bar\nLIMIT 1``), use a simple index instead of a slice. For example, this returns the\nfirst ``Entry`` in the database, after ordering entries alphabetically by\nheadline::\n\n    >>> Entry.objects.order_by('headline')[0]\n\nThis is roughly equivalent to the following::\n\n    >>> Entry.objects.order_by('headline')[0:1].get()\n\nNote, however, that the first of these will raise ``IndexError`` while the\nsecond will raise ``DoesNotExist`` if no objects match the given criteria.\n\nQuery Methods That Return New QuerySets\n---------------------------------------\n\nDjango provides a range of ``QuerySet`` refinement methods that modify either\nthe types of results returned by the ``QuerySet`` or the way its SQL query is\nexecuted. These methods are described in the sections that follow. Some of the\nmethods take field lookup arguments, which are discussed in detail a bit later\non.\n\nfilter(\\*\\*lookup)\n~~~~~~~~~~~~~~~~~~\n\nReturns a new ``QuerySet`` containing objects that match the given lookup\nparameters.\n\nexclude(\\*\\*lookup)\n~~~~~~~~~~~~~~~~~~~\n\nReturns a new ``QuerySet`` containing objects that do *not* match the given\nlookup parameters.\n\norder_by(\\*fields)\n~~~~~~~~~~~~~~~~~~\n\nBy default, results returned by a ``QuerySet`` are ordered by the ordering\ntuple given by the ``ordering`` option in the model's metadata (see Appendix A). You can\noverride this for a particular query using the ``order_by()`` method::\n\n    >> Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')\n\nThis result will be ordered by ``pub_date`` descending, then by\n``headline`` ascending. The negative sign in front of ``\"-pub_date\"`` indicates\n*descending* order. Ascending order is assumed if the ``-`` is absent. To order\nrandomly, use ``\"?\"``, like so::\n\n    >>> Entry.objects.order_by('?')\n\nOrdering randomly incurs a performance penalty, though, so you shouldn't use it\nfor anything with heavy load.\n\nIf no ordering is specified in a model's ``class Meta`` and a ``QuerySet`` from\nthat model doesn't include ``order_by()``, then ordering will be undefined and\nmay differ from query to query.\n\ndistinct()\n~~~~~~~~~~\n\nReturns a new ``QuerySet`` that uses ``SELECT DISTINCT`` in its SQL query. This\neliminates duplicate rows from the query results.\n\nBy default, a ``QuerySet`` will not eliminate duplicate rows. In practice, this\nis rarely a problem, because simple queries such as ``Blog.objects.all()`` don't\nintroduce the possibility of duplicate result rows.\n\nHowever, if your query spans multiple tables, it's possible to get duplicate\nresults when a ``QuerySet`` is evaluated. That's when you'd use ``distinct()``.\n\nvalues(\\*fields)\n~~~~~~~~~~~~~~~~\n\nReturns a special ``QuerySet`` that evaluates to a list of dictionaries instead\nof model-instance objects. Each of those dictionaries represents an object, with\nthe keys corresponding to the attribute names of model objects::\n\n    # This list contains a Blog object.\n    >>> Blog.objects.filter(name__startswith='Beatles')\n    [Beatles Blog]\n\n    # This list contains a dictionary.\n    >>> Blog.objects.filter(name__startswith='Beatles').values()\n    [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]\n\n``values()`` takes optional positional arguments, ``*fields``, which specify\nfield names to which the ``SELECT`` should be limited. If you specify the\nfields, each dictionary will contain only the field keys/values for the fields\nyou specify. If you don't specify the fields, each dictionary will contain a\nkey and value for every field in the database table::\n\n    >>> Blog.objects.values()\n    [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],\n    >>> Blog.objects.values('id', 'name')\n    [{'id': 1, 'name': 'Beatles Blog'}]\n\nThis method is useful when you know you're only going to need values from a\nsmall number of the available fields and you won't need the functionality of a\nmodel instance object. It's more efficient to select only the fields you need to\nuse.\n\ndates(field, kind, order)\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReturns a special ``QuerySet`` that evaluates to a list of ``datetime.datetime``\nobjects representing all available dates of a particular kind within the\ncontents of the ``QuerySet``.\n\nThe ``field`` argument must be the name of a ``DateField`` or ``DateTimeField``\nof your model. The ``kind`` argument must be either ``\"year\"``, ``\"month\"``, or\n``\"day\"``. Each ``datetime.datetime`` object in the result list is \"truncated\"\nto the given ``type``:\n\n* ``\"year\"`` returns a list of all distinct year values for the field.\n\n* ``\"month\"`` returns a list of all distinct year/month values for the field.\n\n* ``\"day\"`` returns a list of all distinct year/month/day values for the field.\n\n``order``, which defaults to ``'ASC'``, should be either ``'ASC'`` or\n``'DESC'``. This specifies how to order the results.\n\nHere are a few examples::\n\n    >>> Entry.objects.dates('pub_date', 'year')\n    [datetime.datetime(2005, 1, 1)]\n\n    >>> Entry.objects.dates('pub_date', 'month')\n    [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)]\n\n    >>> Entry.objects.dates('pub_date', 'day')\n    [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)]\n\n    >>> Entry.objects.dates('pub_date', 'day', order='DESC')\n    [datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)]\n\n    >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')\n    [datetime.datetime(2005, 3, 20)]\n\nselect_related()\n~~~~~~~~~~~~~~~~\n\nReturns a ``QuerySet`` that will automatically \"follow\" foreign key\nrelationships, selecting that additional related-object data when it executes\nits query. This is a performance booster that results in (sometimes much)\nlarger queries but means later use of foreign key relationships won't require\ndatabase queries.\n\nThe following examples illustrate the difference between plain lookups and\n``select_related()`` lookups. Here's standard lookup::\n\n    # Hits the database.\n    >>> e = Entry.objects.get(id=5)\n\n    # Hits the database again to get the related Blog object.\n    >>> b = e.blog\n\nAnd here's ``select_related`` lookup::\n\n    # Hits the database.\n    >>> e = Entry.objects.select_related().get(id=5)\n\n    # Doesn't hit the database, because e.blog has been prepopulated\n    # in the previous query.\n    >>> b = e.blog\n\n``select_related()`` follows foreign keys as far as possible. If you have the\nfollowing models::\n\n    class City(models.Model):\n        # ...\n\n    class Person(models.Model):\n        # ...\n        hometown = models.ForeignKey(City)\n\n    class Book(models.Model):\n        # ...\n        author = models.ForeignKey(Person)\n\nthen a call to ``Book.objects.select_related().get(id=4)`` will cache the\nrelated ``Person`` *and* the related ``City``::\n\n    >>> b = Book.objects.select_related().get(id=4)\n    >>> p = b.author         # Doesn't hit the database.\n    >>> c = p.hometown       # Doesn't hit the database.\n\n    >>> b = Book.objects.get(id=4) # No select_related() in this example.\n    >>> p = b.author         # Hits the database.\n    >>> c = p.hometown       # Hits the database.\n\nNote that ``select_related()`` does not follow foreign keys that have\n``null=True``.\n\nUsually, using ``select_related()`` can vastly improve performance because your\napplication can avoid many database calls. However, in situations with deeply nested\nsets of relationships, ``select_related()`` can sometimes end up following \"too\nmany\" relations and can generate queries so large that they end up being slow.\n\nQuerySet Methods That Do Not Return QuerySets\n---------------------------------------------\n\nThe following ``QuerySet`` methods evaluate the ``QuerySet`` and return\nsomething *other than* a ``QuerySet`` -- a single object, value, and so forth.\n\nget(\\*\\*lookup)\n~~~~~~~~~~~~~~~\n\nReturns the object matching the given lookup parameters, which should be in the\nformat described in the \"Field Lookups\" section. This raises ``AssertionError`` if\nmore than one object was found.\n\n``get()`` raises a ``DoesNotExist`` exception if an object wasn't found for the\ngiven parameters. The ``DoesNotExist`` exception is an attribute of the model\nclass, for example::\n\n    >>> Entry.objects.get(id='foo') # raises Entry.DoesNotExist\n\nThe ``DoesNotExist`` exception inherits from\n``django.core.exceptions.ObjectDoesNotExist``, so you can target multiple\n``DoesNotExist`` exceptions::\n\n    >>> from django.core.exceptions import ObjectDoesNotExist\n    >>> try:\n    ...     e = Entry.objects.get(id=3)\n    ...     b = Blog.objects.get(id=1)\n    ... except ObjectDoesNotExist:\n    ...     print \"Either the entry or blog doesn't exist.\"\n\ncreate(\\*\\*kwargs)\n~~~~~~~~~~~~~~~~~~\n\nThis is a convenience method for creating an object and saving it all in one step.\nIt lets you compress two common steps::\n\n    >>> p = Person(first_name=\"Bruce\", last_name=\"Springsteen\")\n    >>> p.save()\n\ninto a single line::\n\n    >>> p = Person.objects.create(first_name=\"Bruce\", last_name=\"Springsteen\")\n\nget_or_create(\\*\\*kwargs)\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis is a convenience method for looking up an object and creating one if it doesn't\nexist. It returns a tuple of ``(object, created)``, where ``object`` is the retrieved or\ncreated object and ``created`` is a Boolean specifying whether a new object was\ncreated.\n\nThis method is meant as a shortcut to boilerplate code and is mostly useful for\ndata-import scripts. For example::\n\n    try:\n        obj = Person.objects.get(first_name='John', last_name='Lennon')\n    except Person.DoesNotExist:\n        obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))\n        obj.save()\n\nThis pattern gets quite unwieldy as the number of fields in a model increases. The\nprevious example can be rewritten using ``get_or_create()`` like so::\n\n    obj, created = Person.objects.get_or_create(\n        first_name = 'John',\n        last_name  = 'Lennon',\n        defaults   = {'birthday': date(1940, 10, 9)}\n    )\n\nAny keyword arguments passed to ``get_or_create()`` -- *except* an optional one\ncalled ``defaults`` -- will be used in a ``get()`` call. If an object is found,\n``get_or_create()`` returns a tuple of that object and ``False``. If an object\nis *not* found, ``get_or_create()`` will instantiate and save a new object,\nreturning a tuple of the new object and ``True``. The new object will be created\naccording to this algorithm::\n\n    defaults = kwargs.pop('defaults', {})\n    params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])\n    params.update(defaults)\n    obj = self.model(**params)\n    obj.save()\n\nIn English, that means start with any non-``'defaults'`` keyword argument that\ndoesn't contain a double underscore (which would indicate a nonexact lookup).\nThen add the contents of ``defaults``, overriding any keys if necessary, and\nuse the result as the keyword arguments to the model class.\n\nIf you have a field named ``defaults`` and want to use it as an exact lookup in\n``get_or_create()``, just use ``'defaults__exact'`` like so::\n\n    Foo.objects.get_or_create(\n        defaults__exact = 'bar',\n        defaults={'defaults': 'bar'}\n    )\n\n.. note::\n\n    As mentioned earlier, ``get_or_create()`` is mostly useful in scripts that\n    need to parse data and create new records if existing ones aren't available.\n    But if you need to use ``get_or_create()`` in a view, please make sure to\n    use it only in ``POST`` requests unless you have a good reason not to.\n    ``GET`` requests shouldn't have any effect on data; use ``POST`` whenever a\n    request to a page has a side effect on your data.\n\ncount()\n~~~~~~~\n\nReturns an integer representing the number of objects in the database matching\nthe ``QuerySet``. ``count()`` never raises exceptions. Here's an example::\n\n    # Returns the total number of entries in the database.\n    >>> Entry.objects.count()\n    4\n\n    # Returns the number of entries whose headline contains 'Lennon'\n    >>> Entry.objects.filter(headline__contains='Lennon').count()\n    1\n\n``count()`` performs a ``SELECT COUNT(*)`` behind the scenes, so you should\nalways use ``count()`` rather than loading all of the records into Python objects\nand calling ``len()`` on the result.\n\nDepending on which database you're using (e.g., PostgreSQL or MySQL),\n``count()`` may return a long integer instead of a normal Python integer. This\nis an underlying implementation quirk that shouldn't pose any real-world\nproblems.\n\nin_bulk(id_list)\n~~~~~~~~~~~~~~~~\n\nTakes a list of primary key values and returns a dictionary mapping each\nprimary key value to an instance of the object with the given ID, for example::\n\n    >>> Blog.objects.in_bulk([1])\n    {1: Beatles Blog}\n    >>> Blog.objects.in_bulk([1, 2])\n    {1: Beatles Blog, 2: Cheddar Talk}\n    >>> Blog.objects.in_bulk([])\n    {}\n\nIDs of objects that don't exist are silently dropped from the result dictionary.\nIf you pass ``in_bulk()`` an empty list, you'll get an empty dictionary.\n\nlatest(field_name=None)\n~~~~~~~~~~~~~~~~~~~~~~~\n\nReturns the latest object in the table, by date, using the ``field_name``\nprovided as the date field. This example returns the latest ``Entry`` in the\ntable, according to the ``pub_date`` field::\n\n    >>> Entry.objects.latest('pub_date')\n\nIf your model's ``Meta`` specifies ``get_latest_by``, you can leave off the\n``field_name`` argument to ``latest()``. Django will use the field specified in\n``get_latest_by`` by default.\n\nLike ``get()``, ``latest()`` raises ``DoesNotExist`` if an object doesn't exist\nwith the given parameters.\n\nField Lookups\n=============\n\nField lookups are how you specify the meat of an SQL ``WHERE`` clause. They're\nspecified as keyword arguments to the ``QuerySet`` methods ``filter()``,\n``exclude()``, and ``get()``.\n\nBasic lookup keyword arguments take the form ``field__lookuptype=value``\n(note the double underscore). For example::\n\n    >>> Entry.objects.filter(pub_date__lte='2006-01-01')\n\ntranslates (roughly) into the following SQL::\n\n    SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';\n\nIf you pass an invalid keyword argument, a lookup function will raise\n``TypeError``.\n\nThe supported lookup types follow.\n\nexact\n-----\n\nPerforms an exact match::\n\n    >>> Entry.objects.get(headline__exact=\"Man bites dog\")\n\nThis matches any object with the exact headline \"Man bites dog\".\n\nIf you don't provide a lookup type -- that is, if your keyword argument doesn't\ncontain a double underscore -- the lookup type is assumed to be ``exact``.\n\nFor example, the following two statements are equivalent::\n\n    >>> Blog.objects.get(id__exact=14) # Explicit form\n    >>> Blog.objects.get(id=14) # __exact is implied\n\nThis is for convenience, because ``exact`` lookups are the common case.\n\niexact\n------\n\nPerforms a case-insensitive exact match::\n\n    >>> Blog.objects.get(name__iexact='beatles blog')\n\nThis will match ``'Beatles Blog'``, ``'beatles blog'``,\n``'BeAtLes BLoG'``, and so forth.\n\ncontains\n--------\n\nPerforms a case-sensitive containment test::\n\n    Entry.objects.get(headline__contains='Lennon')\n\nThis will match the headline ``'Today Lennon honored'`` but not\n``'today lennon honored'``.\n\nSQLite doesn't support case-sensitive ``LIKE`` statements; when using\nSQLite,``contains`` acts like ``icontains``.\n\n.. admonition:: Escaping Percent Signs and Underscores in LIKE Statements\n\n    The field lookups that equate to ``LIKE`` SQL statements (``iexact``,\n    ``contains``, ``icontains``, ``startswith``, ``istartswith``, ``endswith``,\n    and ``iendswith``) will automatically escape the two special characters used in\n    ``LIKE`` statements -- the percent sign and the underscore. (In a ``LIKE``\n    statement, the percent sign signifies a multiple-character wildcard and the\n    underscore signifies a single-character wildcard.)\n\n    This means things should work intuitively, so the abstraction doesn't leak.\n    For example, to retrieve all the entries that contain a percent sign, just use\n    the percent sign as any other character::\n\n        Entry.objects.filter(headline__contains='%')\n\n    Django takes care of the quoting for you. The resulting SQL will look something\n    like this::\n\n        SELECT ... WHERE headline LIKE '%\\%%';\n\n    The same goes for underscores. Both percentage signs and underscores are handled\n    for you transparently.\n\nicontains\n---------\n\nPerforms a case-insensitive containment test::\n\n    >>> Entry.objects.get(headline__icontains='Lennon')\n\nUnlike ``contains``, ``icontains`` *will* match ``'today lennon honored'``.\n\ngt, gte, lt, and lte\n--------------------\n\nThese represent greater than, greater than or equal to, less than, and less\nthan or equal to::\n\n    >>> Entry.objects.filter(id__gt=4)\n    >>> Entry.objects.filter(id__lt=15)\n    >>> Entry.objects.filter(id__gte=0)\n\nThese queries return any object with an ID greater than 4, an ID less than 15,\nand an ID greater than or equal to 1, respectively.\n\nYou'll usually use these on numeric fields. Be careful with character fields\nsince character order isn't always what you'd expect (i.e., the string \"4\" sorts\n*after* the string \"10\").\n\nin\n--\n\nFilters where a value is on a given list::\n\n    Entry.objects.filter(id__in=[1, 3, 4])\n\nThis returns all objects with the ID 1, 3, or 4.\n\nstartswith\n----------\n\nPerforms a case-sensitive starts-with::\n\n    >>> Entry.objects.filter(headline__startswith='Will')\n\nThis will return the headlines \"Will he run?\" and \"Willbur named judge\", but not\n\"Who is Will?\" or \"will found in crypt\".\n\nistartswith\n-----------\n\nPerforms a case-insensitive starts-with::\n\n    >>> Entry.objects.filter(headline__istartswith='will')\n\nThis will return the headlines \"Will he run?\", \"Willbur named judge\", and\n\"will found in crypt\", but not \"Who is Will?\"\n\nendswith and iendswith\n----------------------\n\nPerform case-sensitive and case-insensitive ends-with::\n\n    >>> Entry.objects.filter(headline__endswith='cats')\n    >>> Entry.objects.filter(headline__iendswith='cats')\n\nSimilar to ``startswith`` and ``istartswith``.\n\nrange\n-----\n\nPerforms an inclusive range check::\n\n    >>> start_date = datetime.date(2005, 1, 1)\n    >>> end_date = datetime.date(2005, 3, 31)\n    >>> Entry.objects.filter(pub_date__range=(start_date, end_date))\n\nYou can use ``range`` anywhere you can use ``BETWEEN`` in SQL -- for dates,\nnumbers, and even characters.\n\nyear, month, and day\n--------------------\n\nFor date/datetime fields, perform exact year, month, or day matches::\n\n    # Return all entries published in 2005\n    >>>Entry.objects.filter(pub_date__year=2005)\n\n    # Return all entries published in December\n    >>> Entry.objects.filter(pub_date__month=12)\n\n    # Return all entries published on the 3rd of the month\n    >>> Entry.objects.filter(pub_date__day=3)\n\n    # Combination: return all entries on Christmas of any year\n    >>> Entry.objects.filter(pub_date__month=12, pub_date_day=25)\n\nisnull\n------\n\nTakes either ``True`` or ``False``, which correspond to SQL queries of\n``IS NULL`` and ``IS NOT NULL``, respectively::\n\n    >>> Entry.objects.filter(pub_date__isnull=True)\n\nsearch\n------\n\nA Boolean full-text search that takes advantage of full-text indexing. This is like\n``contains`` but is significantly faster due to full-text indexing.\n\nNote this is available only in MySQL and requires direct manipulation of the\ndatabase to add the full-text index.\n\nThe pk Lookup Shortcut\n----------------------\n\nFor convenience, Django provides a ``pk`` lookup type, which stands for\n\"primary_key\".\n\nIn the example ``Blog`` model, the primary key is the ``id`` field, so these\nthree statements are equivalent::\n\n    >>> Blog.objects.get(id__exact=14) # Explicit form\n    >>> Blog.objects.get(id=14) # __exact is implied\n    >>> Blog.objects.get(pk=14) # pk implies id__exact\n\nThe use of ``pk`` isn't limited to ``__exact`` queries -- any query term can be\ncombined with ``pk`` to perform a query on the primary key of a model::\n\n    # Get blogs entries  with id 1, 4, and 7\n    >>> Blog.objects.filter(pk__in=[1,4,7])\n\n    # Get all blog entries with id > 14\n    >>> Blog.objects.filter(pk__gt=14)\n\n``pk`` lookups also work across joins. For example, these three statements are\nequivalent::\n\n    >>> Entry.objects.filter(blog__id__exact=3) # Explicit form\n    >>> Entry.objects.filter(blog__id=3) # __exact is implied\n    >>> Entry.objects.filter(blog__pk=3) # __pk implies __id__exact\n\nThe point of ``pk`` is to give you a generic way to refer to the primary key in\ncases where you're not sure whether the model's primary key is called ``id``.\n\nComplex Lookups with Q Objects\n==============================\n\nKeyword argument queries -- in ``filter()`` and so on -- are ANDed together. If\nyou need to execute more complex queries (e.g., queries with ``OR``\nstatements), you can use ``Q`` objects.\n\nA ``Q`` object (``django.db.models.Q``) is an object used to encapsulate a\ncollection of keyword arguments. These keyword arguments are specified as in\nthe \"Field Lookups\" section.\n\nFor example, this ``Q`` object encapsulates a single ``LIKE`` query::\n\n    Q(question__startswith='What')\n\n``Q`` objects can be combined using the ``&`` and ``|`` operators. When an\noperator is used on two ``Q`` objects, it yields a new ``Q`` object. For example,\nthis statement yields a single ``Q`` object that represents the\nOR of two ``\"question__startswith\"`` queries::\n\n    Q(question__startswith='Who') | Q(question__startswith='What')\n\nThis is equivalent to the following SQL ``WHERE`` clause::\n\n    WHERE question LIKE 'Who%' OR question LIKE 'What%'\n\nYou can compose statements of arbitrary complexity by combining ``Q`` objects\nwith the ``&`` and ``|`` operators. You can also use parenthetical grouping.\n\nEach lookup function that takes keyword arguments (e.g., ``filter()``,\n``exclude()``, ``get()``) can also be passed one or more ``Q`` objects as\npositional (not-named) arguments. If you provide multiple ``Q`` object\narguments to a lookup function, the arguments will be ANDed together, for\nexample::\n\n    Poll.objects.get(\n        Q(question__startswith='Who'),\n        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))\n    )\n\nroughly translates into the following SQL::\n\n    SELECT * from polls WHERE question LIKE 'Who%'\n        AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')\n\nLookup functions can mix the use of ``Q`` objects and keyword arguments. All\narguments provided to a lookup function (be they keyword arguments or ``Q``\nobjects) are ANDed together. However, if a ``Q`` object is provided, it must\nprecede the definition of any keyword arguments. For example, the following::\n\n    Poll.objects.get(\n        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),\n        question__startswith='Who')\n\nwould be a valid query, equivalent to the previous example, but this::\n\n    # INVALID QUERY\n    Poll.objects.get(\n        question__startswith='Who',\n        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))\n\nwould not be valid.\n\nYou can find some examples online at http://www.djangoproject.com/documentation/models/or_lookups/.\n\nRelated Objects\n===============\n\nWhen you define a relationship in a model (i.e., a ``ForeignKey``,\n``OneToOneField``, or ``ManyToManyField``), instances of that model will have\na convenient API to access the related object(s).\n\nFor example, an ``Entry`` object ``e`` can get its associated ``Blog`` object by\naccessing the ``blog`` attribute ``e.blog``.\n\nDjango also creates API accessors for the \"other\" side of the relationship --\nthe link from the related model to the model that defines the relationship.\nFor example, a ``Blog`` object ``b`` has access to a list of all related\n``Entry`` objects via the ``entry_set`` attribute: ``b.entry_set.all()``.\n\nAll examples in this section use the sample ``Blog``, ``Author``, and ``Entry``\nmodels defined at the start of the appendix.\n\nLookups That Span Relationships\n-------------------------------\n\nDjango offers a powerful and intuitive way to \"follow\" relationships in\nlookups, taking care of the SQL ``JOIN``\\s for you automatically behind the\nscenes. To span a relationship, just use the field name of related fields\nacross models, separated by double underscores, until you get to the field you\nwant.\n\nThis example retrieves all ``Entry`` objects with a ``Blog`` whose ``name``\nis ``'Beatles Blog'``::\n\n    >>> Entry.objects.filter(blog__name__exact='Beatles Blog')\n\nThis spanning can be as deep as you'd like.\n\nIt works backward, too. To refer to a \"reverse\" relationship, just use the\nlowercase name of the model.\n\nThis example retrieves all ``Blog`` objects that have at least one ``Entry``\nwhose ``headline`` contains ``'Lennon'``::\n\n    >>> Blog.objects.filter(entry__headline__contains='Lennon')\n\nForeign Key Relationships\n-------------------------\n\nIf a model has a ``ForeignKey``, instances of that model will have access to\nthe related (foreign) object via a simple attribute of the model, for example::\n\n    e = Entry.objects.get(id=2)\n    e.blog # Returns the related Blog object.\n\nYou can get and set via a foreign key attribute. As you may expect, changes to\nthe foreign key aren't saved to the database until you call ``save()``, for example::\n\n    e = Entry.objects.get(id=2)\n    e.blog = some_blog\n    e.save()\n\nIf a ``ForeignKey`` field has ``null=True`` set (i.e., it allows ``NULL``\nvalues), you can set it to ``NULL`` by assigning ``None`` to it and saving::\n\n    e = Entry.objects.get(id=2)\n    e.blog = None\n    e.save() # \"UPDATE blog_entry SET blog_id = NULL ...;\"\n\nForward access to one-to-many relationships is cached the first time the\nrelated object is accessed. Subsequent accesses to the foreign key on the same\nobject instance are cached, for example::\n\n    e = Entry.objects.get(id=2)\n    print e.blog  # Hits the database to retrieve the associated Blog.\n    print e.blog  # Doesn't hit the database; uses cached version.\n\nNote that the ``select_related()`` ``QuerySet`` method recursively prepopulates\nthe cache of all one-to-many relationships ahead of time::\n\n    e = Entry.objects.select_related().get(id=2)\n    print e.blog  # Doesn't hit the database; uses cached version.\n    print e.blog  # Doesn't hit the database; uses cached version.\n\n``select_related()`` is documented in the \"QuerySet Methods That Return New\nQuerySets\" section.\n\n\"Reverse\" Foreign Key Relationships\n-----------------------------------\n\nForeign key relationships are automatically symmetrical -- a reverse\nrelationship is inferred from the presence of a ``ForeignKey`` pointing to\nanother model.\n\nIf a model has a ``ForeignKey``, instances of the foreign key model will have\naccess to a ``Manager`` that returns all instances of the first model that\nrelate to that object. By default, this ``Manager`` is named ``FOO_set``, where\n``FOO`` is the source model name, lowercased. This ``Manager`` returns\n``QuerySets``, which can be filtered and manipulated as described in the\n\"Retrieving Objects\" section.\n\nHere's an example::\n\n    b = Blog.objects.get(id=1)\n    b.entry_set.all() # Returns all Entry objects related to Blog.\n\n    # b.entry_set is a Manager that returns QuerySets.\n    b.entry_set.filter(headline__contains='Lennon')\n    b.entry_set.count()\n\nYou can override the ``FOO_set`` name by setting the ``related_name``\nparameter in the ``ForeignKey()`` definition. For example, if the ``Entry``\nmodel was altered to ``blog = ForeignKey(Blog, related_name='entries')``, the\npreceding example code would look like this::\n\n    b = Blog.objects.get(id=1)\n    b.entries.all() # Returns all Entry objects related to Blog.\n\n    # b.entries is a Manager that returns QuerySets.\n    b.entries.filter(headline__contains='Lennon')\n    b.entries.count()\n\n``related_name`` is particularly useful if a model has two foreign keys to the\nsame second model.\n\nYou cannot access a reverse ``ForeignKey`` ``Manager`` from the class; it must\nbe accessed from an instance::\n\n    Blog.entry_set # Raises AttributeError: \"Manager must be accessed via instance\".\n\nIn addition to the ``QuerySet`` methods defined in the \"Retrieving Objects\" section,\nthe ``ForeignKey`` ``Manager`` has these additional methods:\n\n* ``add(obj1, obj2, ...)``: Adds the specified model objects to the related\n  object set, for example::\n\n      b = Blog.objects.get(id=1)\n      e = Entry.objects.get(id=234)\n      b.entry_set.add(e) # Associates Entry e with Blog b.\n\n* ``create(**kwargs)``: Creates a new object, saves it, and puts it in the\n  related object set. It returns the newly created object::\n\n      b = Blog.objects.get(id=1)\n      e = b.entry_set.create(headline='Hello', body_text='Hi', pub_date=datetime.date(2005, 1, 1))\n      # No need to call e.save() at this point -- it's already been saved.\n\n  This is equivalent to (but much simpler than) the following::\n\n      b = Blog.objects.get(id=1)\n      e = Entry(blog=b, headline='Hello', body_text='Hi', pub_date=datetime.date(2005, 1, 1))\n      e.save()\n\n  Note that there's no need to specify the keyword argument of the model\n  that defines the relationship. In the preceding example, we don't pass the\n  parameter ``blog`` to ``create()``. Django figures out that the new\n  ``Entry`` object's ``blog`` field should be set to ``b``.\n\n* ``remove(obj1, obj2, ...)``: Removes the specified model objects from the\n  related object set::\n\n      b = Blog.objects.get(id=1)\n      e = Entry.objects.get(id=234)\n      b.entry_set.remove(e) # Disassociates Entry e from Blog b.\n\n  In order to prevent database inconsistency, this method only exists on\n  ``ForeignKey`` objects where ``null=True``. If the related field can't be\n  set to ``None`` (``NULL``), then an object can't be removed from a\n  relation without being added to another. In the preceding example, removing\n  ``e`` from ``b.entry_set()`` is equivalent to doing ``e.blog = None``,\n  and because the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this\n  is invalid.\n\n* ``clear()``: Removes all objects from the related object set::\n\n      b = Blog.objects.get(id=1)\n      b.entry_set.clear()\n\n  Note this doesn't delete the related objects -- it just disassociates\n  them.\n\n  Just like ``remove()``, ``clear()`` is only available on ``ForeignKey``s\n  where ``null=True``.\n\nTo assign the members of a related set in one fell swoop, just assign to it\nfrom any iterable object, for example::\n\n    b = Blog.objects.get(id=1)\n    b.entry_set = [e1, e2]\n\nIf the ``clear()`` method is available, any pre-existing objects will be\nremoved from the ``entry_set`` before all objects in the iterable (in this\ncase, a list) are added to the set. If the ``clear()`` method is *not*\navailable, all objects in the iterable will be added without removing any\nexisting elements.\n\nEach \"reverse\" operation described in this section has an immediate effect on\nthe database. Every addition, creation, and deletion is immediately and\nautomatically saved to the database.\n\nMany-to-Many Relationships\n--------------------------\n\nBoth ends of a many-to-many relationship get automatic API access to the other\nend. The API works just as a \"reverse\" one-to-many relationship (described\nin the previous section).\n\nThe only difference is in the attribute naming: the model that defines the\n``ManyToManyField`` uses the attribute name of that field itself, whereas the\n\"reverse\" model uses the lowercased model name of the original model, plus\n``'_set'`` (just like reverse one-to-many relationships).\n\nAn example makes this concept easier to understand::\n\n    e = Entry.objects.get(id=3)\n    e.authors.all() # Returns all Author objects for this Entry.\n    e.authors.count()\n    e.authors.filter(name__contains='John')\n\n    a = Author.objects.get(id=5)\n    a.entry_set.all() # Returns all Entry objects for this Author.\n\nLike ``ForeignKey``, ``ManyToManyField`` can specify ``related_name``. In the\npreceding example, if the ``ManyToManyField`` in ``Entry`` had specified\n``related_name='entries'``, then each ``Author`` instance would have an\n``entries`` attribute instead of ``entry_set``.\n\n.. admonition:: How Are the Backward Relationships Possible?\n\n    Other object-relational mappers require you to define relationships on both\n    sides. The Django developers believe this is a violation of the DRY (Don't\n    Repeat Yourself) principle, so Django requires you to define the\n    relationship on only one end. But how is this possible, given that a model\n    class doesn't know which other model classes are related to it until those\n    other model classes are loaded?\n\n    The answer lies in the ``INSTALLED_APPS`` setting. The first time any model\n    is loaded, Django iterates over every model in ``INSTALLED_APPS`` and\n    creates the backward relationships in memory as needed. Essentially, one of\n    the functions of ``INSTALLED_APPS`` is to tell Django the entire model\n    domain.\n\nQueries Over Related Objects\n----------------------------\n\nQueries involving related objects follow the same rules as queries involving\nnormal value fields. When specifying the value for a query to match, you\nmay use either an object instance itself or the primary key value for the\nobject.\n\nFor example, if you have a ``Blog`` object ``b`` with ``id=5``, the following\nthree queries would be identical::\n\n    Entry.objects.filter(blog=b) # Query using object instance\n    Entry.objects.filter(blog=b.id) # Query using id from instance\n    Entry.objects.filter(blog=5) # Query using id directly\n\nDeleting Objects\n================\n\nThe delete method, conveniently, is named ``delete()``. This method immediately\ndeletes the object and has no return value::\n\n    e.delete()\n\nYou can also delete objects in bulk. Every ``QuerySet`` has a ``delete()``\nmethod, which deletes all members of that ``QuerySet``. For example, this\ndeletes all ``Entry`` objects with a ``pub_date`` year of 2005::\n\n    Entry.objects.filter(pub_date__year=2005).delete()\n\nWhen Django deletes an object, it emulates the behavior of the SQL\nconstraint ``ON DELETE CASCADE`` -- in other words, any objects that\nhad foreign keys pointing at the object to be deleted will be deleted\nalong with it, for example::\n\n    b = Blog.objects.get(pk=1)\n    # This will delete the Blog and all of its Entry objects.\n    b.delete()\n\nNote that ``delete()`` is the only ``QuerySet`` method that is not exposed on a\n``Manager`` itself. This is a safety mechanism to prevent you from accidentally\nrequesting ``Entry.objects.delete()`` and deleting *all* the entries. If you\n*do* want to delete all the objects, then you have to explicitly request a\ncomplete query set::\n\n    Entry.objects.all().delete()\n\nShortcuts\n=========\n\nAs you develop views, you will discover a number of common idioms in the\nway you use the database API. Django encodes some of these idioms as\nshortcuts that can be used to simplify the process of writing views. These\nfunctions are in the ``django.shortcuts`` module.\n\nget_object_or_404()\n-------------------\n\nOne common idiom to use ``get()`` and raise ``Http404`` if the\nobject doesn't exist. This idiom is captured by ``get_object_or_404()``.\nThis function takes a Django model as its first argument and an\narbitrary number of keyword arguments, which it passes to the default\nmanager's ``get()`` function. It raises ``Http404`` if the object doesn't\nexist, for example::\n\n    # Get the Entry with a primary key of 3\n    e = get_object_or_404(Entry, pk=3)\n\nWhen you provide a model to this shortcut function, the default manager\nis used to execute the underlying ``get()`` query. If you don't want to\nuse the default manager, or if you want to search a list of related objects,\nyou can provide ``get_object_or_404()`` with a ``Manager`` object instead::\n\n    # Get the author of blog instance e with a name of 'Fred'\n    a = get_object_or_404(e.authors, name='Fred')\n\n    # Use a custom manager 'recent_entries' in the search for an\n    # entry with a primary key of 3\n    e = get_object_or_404(Entry.recent_entries, pk=3)\n\nget_list_or_404()\n-----------------\n\n``get_list_or_404`` behaves the same way as ``get_object_or_404()``,\nexcept that it uses ``filter()`` instead of ``get()``. It raises\n``Http404`` if the list is empty.\n\nFalling Back to Raw SQL\n=======================\n\nIf you find yourself needing to write an SQL query that is too complex for\nDjango's database mapper to handle, you can fall back into raw SQL statement\nmode.\n\nThe preferred way to do this is by giving your model custom methods or custom\nmanager methods that execute queries. Although there's nothing in Django that\n*requires* database queries to live in the model layer, this approach keeps all\nyour data access logic in one place, which is smart from a code organization\nstandpoint. For instructions, see Appendix A.\n\nFinally, it's important to note that the Django database layer is merely an\ninterface to your database. You can access your database via other tools,\nprogramming languages, or database frameworks -- there's nothing Django-specific\nabout your database.\n"
  },
  {
    "path": "Python/DjangoBook/appendixC.rst",
    "content": "==================================\nAppendix C: Generic View Reference\n==================================\n\nChapter 11 introduced generic views but leaves out some of the gory details.\nThis appendix describes each generic view along with all the options each view can\ntake. Be sure to read Chapter 11 before trying to understand the reference\nmaterial that follows. You might want to refer back to the ``Book``,\n``Publisher``, and ``Author`` objects defined in that chapter; the examples that\nfollow use these models.\n\nCommon Arguments to Generic Views\n=================================\n\nMost of these views take a large number of arguments that can change the generic\nview's behavior. Many of these arguments work the same across a large number of\nviews. Table C-1 describes each of these common arguments; anytime you see one\nof these arguments in a generic view's argument list, it will work as described in\nthe table.\n\n.. table:: Table C-1. Common Arguments to Generic Views\n\n    ==========================  ===============================================\n    Argument                    Description\n    ==========================  ===============================================\n    ``allow_empty``             A Boolean specifying whether to display the\n                                page if no objects are available. If this is\n                                ``False`` and no objects are available, the view\n                                will raise a 404 error instead of displaying an\n                                empty page. By default, this is ``True``.\n\n    ``context_processors``      A list of additional template-context processors\n                                (besides the defaults) to apply to the view's\n                                template. See Chapter 9 for information on\n                                template context processors.\n\n    ``extra_context``           A dictionary of values to add to the template\n                                context. By default, this is an empty\n                                dictionary. If a value in the dictionary is\n                                callable, the generic view will call it just\n                                before rendering the template.\n\n    ``mimetype``                The MIME type to use for the resulting\n                                document. It defaults to the value of the\n                                ``DEFAULT_MIME_TYPE`` setting, which is\n                                ``text/html`` if you haven't changed it.\n\n    ``queryset``                A ``QuerySet`` (i.e., something like\n                                ``Author.objects.all()``) to read objects from.\n                                See Appendix B for more information about\n                                ``QuerySet`` objects. Most generic views require\n                                this argument.\n\n    ``template_loader``         The template loader to use when loading the\n                                template. By default, it's\n                                ``django.template.loader``. See Chapter 9 for\n                                information on template loaders.\n\n    ``template_name``           The full name of a template to use in rendering\n                                the page. This lets you override the default\n                                template name derived from the ``QuerySet``.\n\n    ``template_object_name``    The name of the template variable to\n                                use in the template context. By default, this is\n                                ``'object'``. Views that list more than one\n                                object (i.e., ``object_list`` views and various\n                                objects-for-date views) will append ``'_list'``\n                                to the value of this parameter.\n    ==========================  ===============================================\n\n\"Simple\" Generic Views\n======================\n\nThe module``django.views.generic.simple`` contains simple views that handle a\ncouple of common cases: rendering a template when no view logic is needed and\nissuing a redirect.\n\nRendering a Template\n--------------------\n\n*View function*: ``django.views.generic.simple.direct_to_template``\n\nThis view renders a given template, passing it a ``{{ params }}`` template\nvariable, which is a dictionary of the parameters captured in the URL.\n\nExample\n```````\n\nGiven the following URLconf::\n\n    from django.conf.urls.defaults import *\n    from django.views.generic.simple import direct_to_template\n\n    urlpatterns = patterns('',\n        (r'^foo/$',             direct_to_template, {'template': 'foo_index.html'}),\n        (r'^foo/(?P<id>\\d+)/$', direct_to_template, {'template': 'foo_detail.html'}),\n    )\n\na request to ``/foo/`` would render the template ``foo_index.html``, and a\nrequest to ``/foo/15/`` would render ``foo_detail.html`` with a context\nvariable ``{{ params.id }}`` that is set to ``15``.\n\nRequired Arguments\n``````````````````\n\n* ``template``: The full name of a template to use.\n\nRedirecting to Another URL\n--------------------------\n\n*View function*: ``django.views.generic.simple.redirect_to``\n\nThis view redirects to another URL. The given URL may contain dictionary-style string\nformatting, which will be interpolated against the parameters captured in the\nURL.\n\nIf the given URL is ``None``, Django will return an HTTP 410 (\"Gone\") message.\n\nExample\n```````\n\nThis URLconf redirects from ``/foo/<id>/`` to ``/bar/<id>/``::\n\n    from django.conf.urls.defaults import *\n    from django.views.generic.simple import redirect_to\n\n    urlpatterns = patterns('django.views.generic.simple',\n        ('^foo/(?p<id>\\d+)/$', redirect_to, {'url': '/bar/%(id)s/'}),\n    )\n\nThis example returns a \"Gone\" response for requests to ``/bar/``::\n\n    from django.views.generic.simple import redirect_to\n\n    urlpatterns = patterns('django.views.generic.simple',\n        ('^bar/$', redirect_to, {'url': None}),\n    )\n\nRequired Arguments\n``````````````````\n\n* ``url``: The URL to redirect to, as a string. Or ``None`` to return a 410\n  (\"Gone\") HTTP response.\n\nList/Detail Generic Views\n=========================\n\nThe list/detail generic views (in the module\n``django.views.generic.list_detail``) handle the common case of displaying a\nlist of items at one view and individual \"detail\" views of those items at\nanother.\n\nLists of Objects\n----------------\n\n*View function*: ``django.views.generic.list_detail.object_list``\n\nUse this view to display a page representing a list of objects.\n\nExample\n```````\n\nGiven the ``Author`` object from Chapter 5, we can use the ``object_list`` view\nto show a simple list of all authors given the following URLconf snippet::\n\n    from mysite.books.models import Author\n    from django.conf.urls.defaults import *\n    from django.views.generic import list_detail\n\n    author_list_info = {\n        'queryset':   Author.objects.all(),\n    }\n\n    urlpatterns = patterns('',\n        (r'authors/$', list_detail.object_list, author_list_info)\n    )\n\nRequired Arguments\n``````````````````\n\n* ``queryset``: A ``QuerySet`` of objects to list (see Table C-1).\n\nOptional Arguments\n``````````````````\n\n* ``paginate_by``: An integer specifying how many objects should be\n  displayed per page. If this is given, the view will paginate objects with\n  ``paginate_by`` objects per page. The view will expect either a ``page``\n  query string parameter (via ``GET``) containing a zero-indexed page\n  number, or a ``page`` variable specified in the URLconf. See the following\n  \"Notes on Pagination\" section.\n\nAdditionally, this view may take any of these common arguments described in\nTable C-1:\n\n* ``allow_empty``\n* ``context_processors``\n* ``extra_context``\n* ``mimetype``\n* ``template_loader``\n* ``template_name``\n* ``template_object_name``\n\nTemplate Name\n`````````````\n\nIf ``template_name`` isn't specified, this view will use the template\n``<app_label>/<model_name>_list.html`` by default. Both the application label and the\nmodel name are derived from the ``queryset`` parameter. The application label is the\nname of the application that the model is defined in, and the model name is the\nlowercased version of the name of the model class.\n\nIn the previous example using ``Author.objects.all()`` as the ``queryset``, the application\nlabel would be ``books`` and the model name would be ``author``. This means\nthe default template would be ``books/author_list.html``.\n\nTemplate Context\n````````````````\n\nIn addition to ``extra_context``, the template's context will contain the following:\n\n* ``object_list``: The list of objects. This variable's name depends on the\n  ``template_object_name`` parameter, which is ``'object'`` by default. If\n  ``template_object_name`` is ``'foo'``, this variable's name will be\n  ``foo_list``.\n\n* ``is_paginated``: A Boolean representing whether the results are\n  paginated. Specifically, this is set to ``False`` if the number of\n  available objects is less than or equal to ``paginate_by``.\n\nIf the results are paginated, the context will contain these extra variables:\n\n* ``results_per_page``: The number of objects per page. (This is the same as\n  the ``paginate_by`` parameter.)\n\n* ``has_next``: A Boolean representing whether there's a next page.\n\n* ``has_previous``: A Boolean representing whether there's a previous page.\n\n* ``page``: The current page number, as an integer. This is 1-based.\n\n* ``next``: The next page number, as an integer. If there's no next page,\n  this will still be an integer representing the theoretical next-page\n  number. This is 1-based.\n\n* ``previous``: The previous page number, as an integer. This is 1-based.\n\n* ``pages``: The total number of pages, as an integer.\n\n* ``hits``: The total number of objects across *all* pages, not just this\n  page.\n\n.. admonition:: A Note on Pagination\n\n    If ``paginate_by`` is specified, Django will paginate the results. You can\n    specify the page number in the URL in one of two ways:\n\n    * Use the ``page`` parameter in the URLconf. For example, this is what\n      your URLconf might look like::\n\n        (r'^objects/page(?P<page>[0-9]+)/$', 'object_list', dict(info_dict))\n\n    * Pass the page number via the ``page`` query-string parameter. For\n      example, a URL would look like this::\n\n        /objects/?page=3\n\n    In both cases, ``page`` is 1-based, not 0-based, so the first page would be\n    represented as page ``1``.\n\nDetail Views\n------------\n\n*View function*: ``django.views.generic.list_detail.object_detail``\n\nThis view provides a \"detail\" view of a single object.\n\nExample\n```````\n\nContinuing the previous ``object_list`` example, we could add a detail view for a\ngiven author by modifying the URLconf:\n\n.. parsed-literal::\n\n    from mysite.books.models import Author\n    from django.conf.urls.defaults import *\n    from django.views.generic import list_detail\n\n    author_list_info = {\n        'queryset' :   Author.objects.all(),\n    }\n    **author_detail_info = {**\n        **\"queryset\" : Author.objects.all(),**\n        **\"template_object_name\" : \"author\",**\n    **}**\n\n    urlpatterns = patterns('',\n        (r'authors/$', list_detail.object_list, author_list_info),\n        **(r'^authors/(?P<object_id>\\d+)/$', list_detail.object_detail, author_detail_info),**\n    )\n\nRequired Arguments\n``````````````````\n\n* ``queryset``: A ``QuerySet`` that will be searched for the object (see Table C-1).\n\nand either\n\n* ``object_id``: The value of the primary-key field for the object.\n\nor\n\n* ``slug``: The slug of the given object. If you pass this field, then the\n  ``slug_field`` argument (see the following section) is also required.\n\nOptional Arguments\n``````````````````\n\n* ``slug_field``: The name of the field on the object containing the slug.\n  This is required if you are using the ``slug`` argument, but it must be\n  absent if you're using the ``object_id`` argument.\n\n* ``template_name_field``: The name of a field on the object whose value is\n  the template name to use. This lets you store template names in your data.\n\n  In other words, if your object has a field ``'the_template'`` that\n  contains a string ``'foo.html'``, and you set ``template_name_field`` to\n  ``'the_template'``, then the generic view for this object will use the\n  template ``'foo.html'``.\n\n  If the template named by ``template_name_field`` doesn't exist, the one\n  named by ``template_name`` is used instead.  It's a bit of a\n  brain-bender, but it's useful in some cases.\n\nThis view may also take these common arguments (see Table C-1):\n\n* ``context_processors``\n* ``extra_context``\n* ``mimetype``\n* ``template_loader``\n* ``template_name``\n* ``template_object_name``\n\nTemplate Name\n`````````````\n\nIf ``template_name`` and ``template_name_field`` aren't specified, this view\nwill use the template ``<app_label>/<model_name>_detail.html`` by default.\n\nTemplate Context\n````````````````\n\nIn addition to ``extra_context``, the template's context will be as follows:\n\n* ``object``: The object. This variable's name depends on the\n  ``template_object_name`` parameter, which is ``'object'`` by default. If\n  ``template_object_name`` is ``'foo'``, this variable's name will be\n  ``foo``.\n\nDate-Based Generic Views\n========================\n\nDate-based generic views are generally used to provide a set of \"archive\"\npages for dated material. Think year/month/day archives for a newspaper, or a\ntypical blog archive.\n\n.. admonition:: Tip:\n\n    By default, these views ignore objects with dates in the future.\n\n    This means that if you try to visit an archive page in the future, Django\n    will automatically show a 404 (\"Page not found\") error, even if there are objects\n    published that day.\n\n    Thus, you can publish postdated objects that don't appear publicly until\n    their desired publication date.\n\n    However, for different types of date-based objects, this isn't appropriate\n    (e.g., a calendar of upcoming events). For these views, setting the\n    ``allow_future`` option to ``True`` will make the future objects appear (and\n    allow users to visit \"future\" archive pages).\n\nArchive Index\n-------------\n\n*View function*: ``django.views.generic.date_based.archive_index``\n\nThis view provides a top-level index page showing the \"latest\" (i.e., most\nrecent) objects by date.\n\nExample\n```````\n\nSay a typical book publisher wants a page of recently published books. Given some\n``Book`` object with a ``publication_date`` field, we can use the\n``archive_index`` view for this common task:\n\n.. parsed-literal::\n\n    from mysite.books.models import Book\n    from django.conf.urls.defaults import *\n    from django.views.generic import date_based\n\n    book_info = {\n        \"queryset\"   : Book.objects.all(),\n        \"date_field\" : \"publication_date\"\n    }\n\n    urlpatterns = patterns('',\n        (r'^books/$', date_based.archive_index, book_info),\n    )\n\nRequired Arguments\n``````````````````\n\n* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in the\n  ``QuerySet``'s model that the date-based archive should use to determine\n  the objects on the page.\n\n* ``queryset``: A ``QuerySet`` of objects for which the archive serves.\n\nOptional Arguments\n``````````````````\n\n* ``allow_future``: A Boolean specifying whether to include \"future\" objects\n  on this page, as described in the previous note.\n\n* ``num_latest``: The number of latest objects to send to the template\n  context. By default, it's 15.\n\nThis view may also take these common arguments (see Table C-1):\n\n* ``allow_empty``\n* ``context_processors``\n* ``extra_context``\n* ``mimetype``\n* ``template_loader``\n* ``template_name``\n\nTemplate Name\n`````````````\n\nIf ``template_name`` isn't specified, this view will use the template\n``<app_label>/<model_name>_archive.html`` by default.\n\nTemplate Context\n````````````````\n\nIn addition to ``extra_context``, the template's context will be as follows:\n\n* ``date_list``: A list of ``datetime.date`` objects representing all years\n  that have objects available according to ``queryset``. These are ordered\n  in reverse.\n\n  For example, if you have blog entries from 2003 through 2006, this list\n  will contain four ``datetime.date`` objects: one for each of those years.\n\n* ``latest``: The ``num_latest`` objects in the system, in descending order\n  by ``date_field``. For example, if ``num_latest`` is ``10``, then\n  ``latest`` will be a list of the latest ten objects in ``queryset``.\n\nYear Archives\n-------------\n\n*View function*: ``django.views.generic.date_based.archive_year``\n\nUse this view for yearly archive pages. These pages have a list of months in\nwhich objects exists, and they can optionally display all the objects published in\na given year.\n\nExample\n```````\n\nExtending the ``archive_index`` example from earlier, we'll add a way to view all\nthe books published in a given year:\n\n.. parsed-literal::\n\n    from mysite.books.models import Book\n    from django.conf.urls.defaults import *\n    from django.views.generic import date_based\n\n    book_info = {\n        \"queryset\"   : Book.objects.all(),\n        \"date_field\" : \"publication_date\"\n    }\n\n    urlpatterns = patterns('',\n        (r'^books/$', date_based.archive_index, book_info),\n        **(r'^books/(?P<year>\\d{4})/?$', date_based.archive_year, book_info),**\n    )\n\nRequired Arguments\n``````````````````\n\n* ``date_field``: As for ``archive_index`` (see the previous section).\n\n* ``queryset``: A ``QuerySet`` of objects for which the archive serves.\n\n* ``year``: The four-digit year for which the archive serves (as in our\n  example, this is usually taken from a URL parameter).\n\nOptional Arguments\n``````````````````\n\n* ``make_object_list``: A Boolean specifying whether to retrieve the full\n  list of objects for this year and pass those to the template. If ``True``,\n  this list of objects will be made available to the template as\n  ``object_list``. (The name ``object_list`` may be different; see the\n  information about ``object_list`` in the following \"Template Context\"\n  section.) By default, this is ``False``.\n\n* ``allow_future``: A Boolean specifying whether to include \"future\" objects\n  on this page.\n\nThis view may also take these common arguments (see Table C-1):\n\n* ``allow_empty``\n* ``context_processors``\n* ``extra_context``\n* ``mimetype``\n* ``template_loader``\n* ``template_name``\n* ``template_object_name``\n\nTemplate Name\n`````````````\n\nIf ``template_name`` isn't specified, this view will use the template\n``<app_label>/<model_name>_archive_year.html`` by default.\n\nTemplate Context\n````````````````\n\nIn addition to ``extra_context``, the template's context will be as follows:\n\n* ``date_list``: A list of ``datetime.date`` objects representing all months\n  that have objects available in the given year, according to ``queryset``,\n  in ascending order.\n\n* ``year``: The given year, as a four-character string.\n\n* ``object_list``: If the ``make_object_list`` parameter is ``True``, this\n  will be set to a list of objects available for the given year, ordered by\n  the date field. This variable's name depends on the\n  ``template_object_name`` parameter, which is ``'object'`` by default. If\n  ``template_object_name`` is ``'foo'``, this variable's name will be\n  ``foo_list``.\n\n  If ``make_object_list`` is ``False``, ``object_list`` will be passed to\n  the template as an empty list.\n\nMonth Archives\n--------------\n\n*View function*: ``django.views.generic.date_based.archive_month``\n\nThis view provides monthly archive pages showing all objects for a given month.\n\nExample\n```````\n\nContinuing with our example, adding month views should look familiar:\n\n.. parsed-literal::\n\n    urlpatterns = patterns('',\n        (r'^books/$', date_based.archive_index, book_info),\n        (r'^books/(?P<year>\\d{4})/?$', date_based.archive_year, book_info),\n        **(**\n            **r'^(?P<year>\\d{4})/(?P<month>[a-z]{3})/$',**\n            **date_based.archive_month,**\n            **book_info**\n        **),**\n    )\n\nRequired Arguments\n``````````````````\n\n* ``year``: The four-digit year for which the archive serves (a string).\n\n* ``month``: The month for which the archive serves, formatted according to\n  the ``month_format`` argument.\n\n* ``queryset``: A ``QuerySet`` of objects for which the archive serves.\n\n* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in the\n  ``QuerySet``'s model that the date-based archive should use to determine\n  the objects on the page.\n\nOptional Arguments\n``````````````````\n\n* ``month_format``: A format string that regulates what format the ``month``\n  parameter uses. This should be in the syntax accepted by Python's\n  ``time.strftime``. (See Python's strftime documentation at\n  http://docs.python.org/library/time.html#time.strftime.) It's set\n  to ``\"%b\"`` by default, which is a three-letter month abbreviation (i.e.,\n  \"jan\", \"feb\", etc.). To change it to use numbers, use ``\"%m\"``.\n\n* ``allow_future``: A Boolean specifying whether to include \"future\" objects\n  on this page, as described in the previous note.\n\nThis view may also take these common arguments (see Table C-1):\n\n* ``allow_empty``\n* ``context_processors``\n* ``extra_context``\n* ``mimetype``\n* ``template_loader``\n* ``template_name``\n* ``template_object_name``\n\nTemplate Name\n`````````````\n\nIf ``template_name`` isn't specified, this view will use the template\n``<app_label>/<model_name>_archive_month.html`` by default.\n\nTemplate Context\n````````````````\n\nIn addition to ``extra_context``, the template's context will be as follows:\n\n* ``month``: A ``datetime.date`` object representing the given month.\n\n* ``next_month``: A ``datetime.date`` object representing the first day of\n  the next month. If the next month is in the future, this will be ``None``.\n\n* ``previous_month``: A ``datetime.date`` object representing the first day\n  of the previous month. Unlike ``next_month``, this will never be ``None``.\n\n* ``object_list``: A list of objects available for the given month. This\n  variable's name depends on the ``template_object_name`` parameter, which\n  is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, this\n  variable's name will be ``foo_list``.\n\nWeek Archives\n-------------\n\n*View function*: ``django.views.generic.date_based.archive_week``\n\nThis view shows all objects in a given week.\n\n.. note::\n\n    For the sake of consistency with Python's built-in date/time handling,\n    Django assumes that the first day of the week is Sunday.\n\nExample\n```````\n\n.. parsed-literal::\n\n    urlpatterns = patterns('',\n        # ...\n        **(**\n            **r'^(?P<year>\\d{4})/(?P<week>\\d{2})/$',**\n            **date_based.archive_week,**\n            **book_info**\n        **),**\n    )\n\n\nRequired Arguments\n``````````````````\n\n* ``year``: The four-digit year for which the archive serves (a string).\n\n* ``week``: The week of the year for which the archive serves (a string).\n\n* ``queryset``: A ``QuerySet`` of objects for which the archive serves.\n\n* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in the\n  ``QuerySet``'s model that the date-based archive should use to determine\n  the objects on the page.\n\nOptional Arguments\n``````````````````\n\n* ``allow_future``: A Boolean specifying whether to include \"future\" objects\n  on this page, as described in the previous note.\n\nThis view may also take these common arguments (see Table C-1):\n\n* ``allow_empty``\n* ``context_processors``\n* ``extra_context``\n* ``mimetype``\n* ``template_loader``\n* ``template_name``\n* ``template_object_name``\n\nTemplate Name\n`````````````\n\nIf ``template_name`` isn't specified, this view will use the template\n``<app_label>/<model_name>_archive_week.html`` by default.\n\nTemplate Context\n````````````````\n\nIn addition to ``extra_context``, the template's context will be as follows:\n\n* ``week``: A ``datetime.date`` object representing the first day of the\n  given week.\n\n* ``object_list``: A list of objects available for the given week. This\n  variable's name depends on the ``template_object_name`` parameter, which\n  is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, this\n  variable's name will be ``foo_list``.\n\nDay Archives\n------------\n\n*View function*: ``django.views.generic.date_based.archive_day``\n\nThis view generates all objects in a given day.\n\nExample\n```````\n\n.. parsed-literal::\n\n    urlpatterns = patterns('',\n        # ...\n        **(**\n            **r'^(?P<year>\\d{4})/(?P<month>[a-z]{3})/(?P<day>\\d{2})/$',**\n            **date_based.archive_day,**\n            **book_info**\n        **),**\n    )\n\n\nRequired Arguments\n``````````````````\n\n* ``year``: The four-digit year for which the archive serves (a string).\n\n* ``month``: The month for which the archive serves, formatted according to the\n  ``month_format`` argument.\n\n* ``day``: The day for which the archive serves, formatted according to the\n  ``day_format`` argument.\n\n* ``queryset``: A ``QuerySet`` of objects for which the archive serves.\n\n* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in the\n  ``QuerySet``'s model that the date-based archive should use to determine\n  the objects on the page.\n\nOptional Arguments\n``````````````````\n\n* ``month_format``: A format string that regulates what format the ``month``\n  parameter uses. See the detailed explanation in the \"Month Archives\"\n  section, above.\n\n* ``day_format``: Like ``month_format``, but for the ``day`` parameter. It\n  defaults to ``\"%d\"`` (the day of the month as a decimal number, 01-31).\n\n* ``allow_future``: A Boolean specifying whether to include \"future\" objects\n  on this page, as described in the previous note.\n\nThis view may also take these common arguments (see Table C-1):\n\n* ``allow_empty``\n* ``context_processors``\n* ``extra_context``\n* ``mimetype``\n* ``template_loader``\n* ``template_name``\n* ``template_object_name``\n\nTemplate Name\n`````````````\n\nIf ``template_name`` isn't specified, this view will use the template\n``<app_label>/<model_name>_archive_day.html`` by default.\n\nTemplate Context\n````````````````\n\nIn addition to ``extra_context``, the template's context will be as follows:\n\n* ``day``: A ``datetime.date`` object representing the given day.\n\n* ``next_day``: A ``datetime.date`` object representing the next day. If the\n  next day is in the future, this will be ``None``.\n\n* ``previous_day``: A ``datetime.date`` object representing the previous day.\n  Unlike ``next_day``, this will never be ``None``.\n\n* ``object_list``: A list of objects available for the given day. This\n  variable's name depends on the ``template_object_name`` parameter, which\n  is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, this\n  variable's name will be ``foo_list``.\n\nArchive for Today\n-----------------\n\nThe ``django.views.generic.date_based.archive_today`` view shows all objects for\n*today*. This is exactly the same as ``archive_day``, except the\n``year``/``month``/``day`` arguments are not used, and today's date is used\ninstead.\n\nExample\n```````\n\n.. parsed-literal::\n\n    urlpatterns = patterns('',\n        # ...\n        **(r'^books/today/$', date_based.archive_today, book_info),**\n    )\n\n\nDate-Based Detail Pages\n-----------------------\n\n*View function*: ``django.views.generic.date_based.object_detail``\n\nUse this view for a page representing an individual object.\n\nThis has a different URL from the ``object_detail`` view; the ``object_detail``\nview uses URLs like ``/entries/<slug>/``, while this one uses URLs like\n``/entries/2006/aug/27/<slug>/``.\n\n.. note::\n\n    If you're using date-based detail pages with slugs in the URLs, you probably\n    also want to use the ``unique_for_date`` option on the slug field to\n    validate that slugs aren't duplicated in a single day. See Appendix A for\n    details on ``unique_for_date``.\n\nExample\n```````\n\nThis one differs (slightly) from all the other date-based examples in that we\nneed to provide either an object ID or a slug so that Django can look up the\nobject in question.\n\nSince the object we're using doesn't have a slug field, we'll use ID-based URLs.\nIt's considered a best practice to use a slug field, but in the interest of\nsimplicity we'll let it go.\n\n.. parsed-literal::\n\n    urlpatterns = patterns('',\n        # ...\n        **(**\n            **r'^(?P<year>\\d{4})/(?P<month>[a-z]{3})/(?P<day>\\d{2})/(?P<object_id>[\\w-]+)/$',**\n            **date_based.object_detail,**\n            **book_info**\n        **),**\n    )\n\nRequired Arguments\n``````````````````\n\n* ``year``: The object's four-digit year (a string).\n\n* ``month``: The object's month, formatted according to the ``month_format``\n  argument.\n\n* ``day``: The object's day, formatted according to the ``day_format`` argument.\n\n* ``queryset``: A ``QuerySet`` that contains the object.\n\n* ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in the\n  ``QuerySet``'s model that the generic view should use to look up the\n  object according to ``year``, ``month``, and ``day``.\n\nYou'll also need either:\n\n* ``object_id``: The value of the primary-key field for the object.\n\nor:\n\n* ``slug``: The slug of the given object. If you pass this field, then the\n  ``slug_field`` argument (described in the following section) is also\n  required.\n\nOptional Arguments\n``````````````````\n\n* ``allow_future``: A Boolean specifying whether to include \"future\" objects\n  on this page, as described in the previous note.\n\n* ``day_format``: Like ``month_format``, but for the ``day`` parameter. It\n  defaults to ``\"%d\"`` (the day of the month as a decimal number, 01-31).\n\n* ``month_format``: A format string that regulates what format the ``month``\n  parameter uses. See the detailed explanation in the \"Month Archives\"\n  section, above.\n\n* ``slug_field``: The name of the field on the object containing the slug.\n  This is required if you are using the ``slug`` argument, but it must be\n  absent if you're using the ``object_id`` argument.\n\n* ``template_name_field``: The name of a field on the object whose value is\n  the template name to use. This lets you store template names in the data.\n  In other words, if your object has a field ``'the_template'`` that\n  contains a string ``'foo.html'``, and you set ``template_name_field`` to\n  ``'the_template'``, then the generic view for this object will use the\n  template ``'foo.html'``.\n\nThis view may also take these common arguments (see Table C-1):\n\n* ``context_processors``\n* ``extra_context``\n* ``mimetype``\n* ``template_loader``\n* ``template_name``\n* ``template_object_name``\n\nTemplate Name\n`````````````\n\nIf ``template_name`` and ``template_name_field`` aren't specified, this view\nwill use the template ``<app_label>/<model_name>_detail.html`` by default.\n\nTemplate Context\n````````````````\n\nIn addition to ``extra_context``, the template's context will be as follows:\n\n* ``object``: The object. This variable's name depends on the\n  ``template_object_name`` parameter, which is ``'object'`` by default. If\n  ``template_object_name`` is ``'foo'``, this variable's name will be\n  ``foo``.\n"
  },
  {
    "path": "Python/DjangoBook/appendixD.rst",
    "content": "====================\nAppendix D: Settings\n====================\n\nYour Django settings file contains all the configuration of your Django\ninstallation. This appendix explains how settings work and which settings are\navailable.\n\nWhat's a Settings File?\n=======================\n\nA *settings file* is just a Python module with module-level variables.\n\nHere are a couple of example settings::\n\n    DEBUG = False\n    DEFAULT_FROM_EMAIL = 'webmaster@example.com'\n    TEMPLATE_DIRS = ('/home/templates/mike', '/home/templates/john')\n\nBecause a settings file is a Python module, the following apply:\n\n* It must be valid Python code; syntax errors aren't allowed.\n\n* It can assign settings dynamically using normal Python syntax,\n  for example::\n\n      MY_SETTING = [str(i) for i in range(30)]\n\n* It can import values from other settings files.\n\nDefault Settings\n----------------\n\nA Django settings file doesn't have to define any settings if it doesn't need\nto. Each setting has a sensible default value. These defaults live in the file\n``django/conf/global_settings.py``.\n\nHere's the algorithm Django uses in compiling settings:\n\n* Load settings from ``global_settings.py``.\n* Load settings from the specified settings file, overriding the global\n  settings as necessary.\n\nNote that a settings file should *not* import from ``global_settings``, because\nthat's redundant.\n\nSeeing Which Settings You've Changed\n------------------------------------\n\nThere's an easy way to view which of your settings deviate from the default\nsettings. The command ``manage.py diffsettings`` displays differences between\nthe current settings file and Django's default settings.\n\n``manage.py`` is described in more detail in Appendix F.\n\nUsing Settings in Python Code\n-----------------------------\n\nIn your Django applications, use settings by importing the object\n``django.conf.settings``, for example::\n\n    from django.conf import settings\n\n    if settings.DEBUG:\n        # Do something\n\nNote that ``django.conf.settings`` isn't a module -- it's an object. So\nimporting individual settings is not possible::\n\n    from django.conf.settings import DEBUG  # This won't work.\n\nAlso note that your code should *not* import from either ``global_settings`` or\nyour own settings file. ``django.conf.settings`` abstracts the concepts of\ndefault settings and site-specific settings; it presents a single interface.\nIt also decouples the code that uses settings from the location of your\nsettings.\n\nAltering Settings at Runtime\n----------------------------\n\nYou shouldn't alter settings in your applications at runtime. For example,\ndon't do this in a view::\n\n    from django.conf import settings\n\n    settings.DEBUG = True   # Don't do this!\n\nThe only place that settings should be defined in is a settings file.\n\nSecurity\n--------\n\nBecause a settings file contains sensitive information, such as the database\npassword, you should make every attempt to limit access to it. For example,\nchange its file permissions so that only you and your Web server's user can\nread it. This is especially important in a shared-hosting environment.\n\nCreating Your Own Settings\n--------------------------\n\nThere's nothing stopping you from creating your own settings, for your own\nDjango applications. Just follow these conventions:\n\n* Use all uppercase for setting names.\n\n* For settings that are sequences, use tuples instead of lists. Settings\n  should be considered immutable and shouldn't be changed once they're\n  defined. Using tuples mirrors these semantics.\n\n* Don't reinvent an already existing setting.\n\nDesignating the Settings: DJANGO_SETTINGS_MODULE\n================================================\n\nWhen you use Django, you have to tell it which settings you're using. Do this\nby using the environment variable ``DJANGO_SETTINGS_MODULE``.\n\nThe value of ``DJANGO_SETTINGS_MODULE`` should be in Python path syntax (e.g.,\n``mysite.settings``). Note that the settings module should be on the\nPython import search path (``PYTHONPATH``).\n\n.. admonition:: Tip:\n\n    A good guide to ``PYTHONPATH`` can be found at\n    http://diveintopython.org/getting_to_know_python/everything_is_an_object.html.\n\nThe django-admin.py Utility\n---------------------------\n\nWhen using ``django-admin.py`` (see Appendix F), you can either set the\nenvironment variable once or explicitly pass in the settings module each time\nyou run the utility.\n\nHere's an example using the Unix Bash shell::\n\n    export DJANGO_SETTINGS_MODULE=mysite.settings\n    django-admin.py runserver\n\nHere's an example using the Windows shell::\n\n    set DJANGO_SETTINGS_MODULE=mysite.settings\n    django-admin.py runserver\n\nUse the ``--settings`` command-line argument to specify the settings manually::\n\n    django-admin.py runserver --settings=mysite.settings\n\nThe ``manage.py`` utility created by ``startproject`` as part of the project\nskeleton sets ``DJANGO_SETTINGS_MODULE`` automatically; see Appendix F for more\nabout ``manage.py``.\n\nOn the Server (mod_python)\n--------------------------\n\nIn your live server environment, you'll need to tell Apache/mod_python which\nsettings file to use. Do that with ``SetEnv``::\n\n    <Location \"/mysite/\">\n        SetHandler python-program\n        PythonHandler django.core.handlers.modpython\n        SetEnv DJANGO_SETTINGS_MODULE mysite.settings\n    </Location>\n\nFor more information, read the Django mod_python documentation online at\nhttp://docs.djangoproject.com/en/dev/howto/deployment/modpython/.\n\nUsing Settings Without Setting DJANGO_SETTINGS_MODULE\n=====================================================\n\nIn some cases, you might want to bypass the ``DJANGO_SETTINGS_MODULE``\nenvironment variable. For example, if you're using the template system by\nitself, you likely don't want to have to set up an environment variable\npointing to a settings module.\n\nIn these cases, you can configure Django's settings manually. Do this by\ncalling ``django.conf.settings.configure()``. Here's an example::\n\n    from django.conf import settings\n\n    settings.configure(\n        DEBUG = True,\n        TEMPLATE_DEBUG = True,\n        TEMPLATE_DIRS = [\n            '/home/web-apps/myapp',\n            '/home/web-apps/base',\n        ]\n    )\n\nPass ``configure()`` as many keyword arguments as you'd like, with each keyword\nargument representing a setting and its value. Each argument name should be all\nuppercase, with the same name as the settings described earlier. If a particular\nsetting is not passed to ``configure()`` and is needed at some later point,\nDjango will use the default setting value.\n\nConfiguring Django in this fashion is mostly necessary -- and, indeed,\nrecommended -- when you're using a piece of the framework inside a larger\napplication.\n\nConsequently, when configured via ``settings.configure()``, Django will not\nmake any modifications to the process environment variables. (See the\nexplanation of ``TIME_ZONE`` later in this appendix for why this would normally occur.)\nIt's assumed that you're already in full control of your environment in these cases.\n\nCustom Default Settings\n-----------------------\n\nIf you'd like default values to come from somewhere other than\n``django.conf.global_settings``, you can pass in a module or class that\nprovides the default settings as the ``default_settings`` argument (or as the\nfirst positional argument) in the call to ``configure()``.\n\nIn this example, default settings are taken from ``myapp_defaults``, and the\n``DEBUG`` setting is set to ``True``, regardless of its value in\n``myapp_defaults``::\n\n    from django.conf import settings\n    from myapp import myapp_defaults\n\n    settings.configure(default_settings=myapp_defaults, DEBUG=True)\n\nThe following example, which uses ``myapp_defaults`` as a positional argument,\nis equivalent::\n\n    settings.configure(myapp_defaults, DEBUG = True)\n\nNormally, you will not need to override the defaults in this fashion. The\nDjango defaults are sufficiently tame that you can safely use them. Be aware\nthat if you do pass in a new default module, it entirely *replaces* the Django\ndefaults, so you must specify a value for every possible setting that might be\nused in that code you are importing. Check in\n``django.conf.settings.global_settings`` for the full list.\n\nEither configure() or DJANGO_SETTINGS_MODULE Is Required\n--------------------------------------------------------\n\nIf you're not setting the ``DJANGO_SETTINGS_MODULE`` environment variable, you\n*must* call ``configure()`` at some point before using any code that reads\nsettings.\n\nIf you don't set ``DJANGO_SETTINGS_MODULE`` and don't call ``configure()``,\nDjango will raise an ``EnvironmentError`` exception the first time a setting\nis accessed.\n\nIf you set ``DJANGO_SETTINGS_MODULE``, access settings values somehow, and *then*\ncall ``configure()``, Django will raise an ``EnvironmentError`` stating that settings\nhave already been configured.\n\nAlso, it's an error to call ``configure()`` more than once, or to call\n``configure()`` after any setting has been accessed.\n\nIt boils down to this: use exactly one of either ``configure()`` or\n``DJANGO_SETTINGS_MODULE``, and only once.\n\nAvailable Settings\n==================\n\nThe following sections consist of a list of the main available settings,\nin alphabetical order, and their default values.\n\nABSOLUTE_URL_OVERRIDES\n----------------------\n\n*Default*: ``{}`` (empty dictionary)\n\nThis is a dictionary mapping ``\"app_label.model_name\"`` strings to functions that take\na model object and return its URL. This is a way of overriding\n``get_absolute_url()`` methods on a per-installation basis. Here's an example::\n\n    ABSOLUTE_URL_OVERRIDES = {\n        'blogs.weblog': lambda o: \"/blogs/%s/\" % o.slug,\n        'news.story': lambda o: \"/stories/%s/%s/\" % (o.pub_year, o.slug),\n    }\n\nNote that the model name used in this setting should be all lowercase, regardless\nof the case of the actual model class name.\n\nADMIN_MEDIA_PREFIX\n------------------\n\n*Default*: ``'/media/'``\n\nThis setting is the URL prefix for admin media: CSS, JavaScript, and images.\nMake sure to use a trailing slash.\n\nADMINS\n------\n\n*Default*: ``()`` (empty tuple)\n\nThis is a tuple that lists people who get code error notifications. When\n``DEBUG=False`` and a view raises an exception, Django will email these people\nwith the full exception information. Each member of the tuple should be a tuple\nof (Full name, e-mail address), for example::\n\n    (('John', 'john@example.com'), ('Mary', 'mary@example.com'))\n\nNote that Django will email *all* of these people whenever an error happens.\n\nALLOWED_INCLUDE_ROOTS\n---------------------\n\n*Default*: ``()`` (empty tuple)\n\nThis is a tuple of strings representing allowed prefixes for the ``{% ssi %}`` template\ntag. This is a security measure, so that template authors can't access files\nthat they shouldn't be accessing.\n\nFor example, if ``ALLOWED_INCLUDE_ROOTS`` is ``('/home/html', '/var/www')``,\nthen ``{% ssi /home/html/foo.txt %}`` would work, but ``{% ssi /etc/passwd %}``\nwouldn't.\n\nAPPEND_SLASH\n------------\n\n*Default*: ``True``\n\nThis setting indicates whether to append trailing slashes to URLs. This is used only if\n``CommonMiddleware`` is installed (see Chapter 17). See also ``PREPEND_WWW``.\n\nCACHE_BACKEND\n-------------\n\n*Default*: ``'locmem://'``\n\nThis is the cache back-end to use (see Chapter 15).\n\nCACHE_MIDDLEWARE_KEY_PREFIX\n---------------------------\n\n*Default*: ``''`` (empty string)\n\nThis is the cache key prefix that the cache middleware should use (see Chapter 15).\n\nDATABASE_ENGINE\n---------------\n\n*Default*: ``''`` (empty string)\n\nThis setting indicates which database back-end to use, e.g.\n``'postgresql_psycopg2'``, or ``'mysql'``.\n\nDATABASE_HOST\n-------------\n\n*Default*: ``''`` (empty string)\n\nThis setting indicates which host to use when connecting to the database.\nAn empty string means ``localhost``. This is not used with SQLite.\n\nIf this value starts with a forward slash (``'/'``) and you're using MySQL,\nMySQL will connect via a Unix socket to the specified socket::\n\n    DATABASE_HOST = '/var/run/mysql'\n\nIf you're using MySQL and this value *doesn't* start with a forward slash, then\nthis value is assumed to be the host.\n\nDATABASE_NAME\n-------------\n\n*Default*: ``''`` (empty string)\n\nThis is the name of the database to use. For SQLite, it's the full path to the database\nfile.\n\nDATABASE_OPTIONS\n----------------\n\n*Default*: ``{}`` (empty dictionary)\n\nThis is extra parameters to use when connecting to the database. Consult the back-end\nmodule's document for available keywords.\n\nDATABASE_PASSWORD\n-----------------\n\n*Default*: ``''`` (empty string)\n\nThis setting is the password to use when connecting to the database. It is not used with SQLite.\n\nDATABASE_PORT\n-------------\n\n*Default*: ``''`` (empty string)\n\nThis is the port to use when connecting to the database. An empty string means the\ndefault port. It is not used with SQLite.\n\nDATABASE_USER\n-------------\n\n*Default*: ``''`` (empty string)\n\nThis setting is the username to use when connecting to the database. It is not used with SQLite.\n\nDATE_FORMAT\n-----------\n\n*Default*: ``'N j, Y'`` (e.g., ``Feb. 4, 2003``)\n\nThis is the default formatting to use for date fields on Django admin change-list pages\n-- and, possibly, by other parts of the system. It accepts the same format as the\n``now`` tag (see Appendix E, Table E-2).\n\nSee also ``DATETIME_FORMAT``, ``TIME_FORMAT``, ``YEAR_MONTH_FORMAT``, and\n``MONTH_DAY_FORMAT``.\n\nDATETIME_FORMAT\n---------------\n\n*Default*: ``'N j, Y, P'`` (e.g., ``Feb. 4, 2003, 4 p.m.``)\n\nThis is the default formatting to use for datetime fields on Django admin change-list\npages -- and, possibly, by other parts of the system. It accepts the same format as the\n``now`` tag (see Appendix E, Table E-2).\n\nSee also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``,\n``YEAR_MONTH_FORMAT``, and ``MONTH_DAY_FORMAT``.\n\nDEBUG\n-----\n\n*Default*: ``False``\n\nThis setting is a Boolean that turns debug mode on and off.\n\nIf you define custom settings, ``django/views/debug.py`` has a ``HIDDEN_SETTINGS``\nregular expression that will hide from the ``DEBUG`` view anything that contains\n``'SECRET``, ``PASSWORD``, or ``PROFANITIES'``. This allows untrusted users to\nbe able to give backtraces without seeing sensitive (or offensive) settings.\n\nStill, note that there are always going to be sections of your debug output that\nare inappropriate for public consumption. File paths, configuration options, and\nthe like all give attackers extra information about your server. Never deploy a\nsite with ``DEBUG`` turned on.\n\nDEFAULT_CHARSET\n---------------\n\n*Default*: ``'utf-8'``\n\nThis is the default charset to use for all ``HttpResponse`` objects, if a MIME type isn't\nmanually specified. It is used with ``DEFAULT_CONTENT_TYPE`` to construct the\n``Content-Type`` header. See Appendix G for more about ``HttpResponse`` objects.\n\nDEFAULT_CONTENT_TYPE\n--------------------\n\n*Default*: ``'text/html'``\n\nThis is the default content type to use for all ``HttpResponse`` objects, if a MIME type\nisn't manually specified. It is used with ``DEFAULT_CHARSET`` to construct the\n``Content-Type`` header. See Appendix G for more about ``HttpResponse`` objects.\n\nDEFAULT_FROM_EMAIL\n------------------\n\n*Default*: ``'webmaster@localhost'``\n\nThis is the default email address to use for various automated correspondence from the\nsite manager(s).\n\nDISALLOWED_USER_AGENTS\n----------------------\n\n*Default*: ``()`` (empty tuple)\n\nThis is a list of compiled regular expression objects representing User-Agent strings\nthat are not allowed to visit any page, systemwide. Use this for bad\nrobots/crawlers. This is used only if ``CommonMiddleware`` is installed (see\nChapter 17).\n\nEMAIL_HOST\n----------\n\n*Default*: ``'localhost'``\n\nThis is the host to use for sending email. See also ``EMAIL_PORT``.\n\nEMAIL_HOST_PASSWORD\n-------------------\n\n*Default*: ``''`` (empty string)\n\nThis is the password to use for the SMTP server defined in ``EMAIL_HOST``. This setting is\nused in conjunction with ``EMAIL_HOST_USER`` when authenticating to the SMTP\nserver. If either of these settings is empty, Django won't attempt\nauthentication.\n\nSee also ``EMAIL_HOST_USER``.\n\nEMAIL_HOST_USER\n---------------\n\n*Default*: ``''`` (empty string)\n\nThis is the username to use for the SMTP server defined in ``EMAIL_HOST``. If it's empty,\nDjango won't attempt authentication. See also ``EMAIL_HOST_PASSWORD``.\n\nEMAIL_PORT\n----------\n\n*Default*: ``25``\n\nThis is the port to use for the SMTP server defined in ``EMAIL_HOST``.\n\nEMAIL_SUBJECT_PREFIX\n--------------------\n\n*Default*: ``'[Django] '``\n\nThis is the subject-line prefix for email messages sent with ``django.core.mail.mail_admins``\nor ``django.core.mail.mail_managers``. You'll probably want to include the\ntrailing space.\n\nFIXTURE_DIRS\n-------------\n\n*Default*: ``()`` (empty tuple)\n\nThis is a list of locations of the fixture data files, in search order. Note that these\npaths should use Unix-style forward slashes, even on Windows. It is used by Django's\ntesting framework, which is covered online at\nhttp://docs.djangoproject.com/en/dev/topics/testing/.\n\nIGNORABLE_404_ENDS\n------------------\n\n*Default*: ``('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico',\n'.php')``\n\nThis is a tuple of strings that specify beginnings of URLs that should be\nignored by the 404 e-mailer. (See Chapter 12 for more on the 404 e-mailer.)\n\nNo errors will be sent for URLs end with strings from this sequence.\n\nSee also ``IGNORABLE_404_STARTS`` and ``SEND_BROKEN_LINK_EMAILS``.\n\nIGNORABLE_404_STARTS\n--------------------\n\n*Default*: ``('/cgi-bin/', '/_vti_bin', '/_vti_inf')``\n\nSee also ``SEND_BROKEN_LINK_EMAILS`` and ``IGNORABLE_404_ENDS``.\n\nINSTALLED_APPS\n--------------\n\n*Default*: ``()`` (empty tuple)\n\nA tuple of strings designating all applications that are enabled in this Django\ninstallation. Each string should be a full Python path to a Python package that\ncontains a Django application. See Chapter 5 for more about applications.\n\nLANGUAGE_CODE\n-------------\n\n*Default*: ``'en-us'``\n\nThis is a string representing the language code for this installation. This should be\nin standard language format -- for example, U.S. English is ``\"en-us\"``. See\nChapter 19.\n\nLANGUAGES\n---------\n\n*Default*: A tuple of all available languages. This list is continually growing\nand any copy included here would inevitably become rapidly out of date. You can\nsee the current list of translated languages by looking in\n``django/conf/global_settings.py``.\n\nThe list is a tuple of two-tuples in the format (language code, language name)\n-- for example, ``('ja', 'Japanese')``. This specifies which languages are\navailable for language selection. See Chapter 19 for more on language selection.\n\nGenerally, the default value should suffice. Only set this setting if you want\nto restrict language selection to a subset of the Django-provided languages.\n\nIf you define a custom ``LANGUAGES`` setting, it's OK to mark the languages as\ntranslation strings, but you should *never* import ``django.utils.translation``\nfrom within your settings file, because that module in itself depends on the\nsettings, and that would cause a circular import.\n\nThe solution is to use a \"dummy\" ``gettext()`` function. Here's a sample\nsettings file::\n\n    gettext = lambda s: s\n\n    LANGUAGES = (\n        ('de', gettext('German')),\n        ('en', gettext('English')),\n    )\n\nWith this arrangement, ``make-messages.py`` will still find and mark these\nstrings for translation, but the translation won't happen at runtime -- so\nyou'll have to remember to wrap the languages in the *real* ``gettext()`` in\nany code that uses ``LANGUAGES`` at runtime.\n\nMANAGERS\n--------\n\n*Default*: ``()`` (empty tuple)\n\nThis tuple is in the same format as ``ADMINS`` that specifies who should get\nbroken-link notifications when ``SEND_BROKEN_LINK_EMAILS=True``.\n\nMEDIA_ROOT\n----------\n\n*Default*: ``''`` (empty string)\n\nThis is an absolute path to the directory that holds media for this installation (e.g.,\n``\"/home/media/media.lawrence.com/\"``). See also ``MEDIA_URL``.\n\nMEDIA_URL\n---------\n\n*Default*: ``''`` (empty string)\n\nThis URL handles the media served from ``MEDIA_ROOT`` (e.g.,\n``\"http://media.lawrence.com\"``).\n\nNote that this should have a trailing slash if it has a path component:\n\n* *Correct*: ``\"http://www.example.com/static/\"``\n* *Incorrect*: ``\"http://www.example.com/static\"``\n\nSee Chapter 12 for more on deployment and serving media.\n\nMIDDLEWARE_CLASSES\n------------------\n\n*Default*::\n\n    (\"django.contrib.sessions.middleware.SessionMiddleware\",\n     \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n     \"django.middleware.common.CommonMiddleware\",\n     \"django.middleware.doc.XViewMiddleware\")\n\nThis is a tuple of middleware classes to use. See Chapter 17.\n\nMONTH_DAY_FORMAT\n----------------\n\n*Default*: ``'F j'``\n\nThis is the default formatting to use for date fields on Django admin change-list\npages -- and, possibly, by other parts of the system -- in cases when only the\nmonth and day are displayed. It accepts the same format as the\n``now`` tag (see Appendix E, Table E-2).\n\nFor example, when a Django admin change-list page is being filtered by a date,\nthe header for a given day displays the day and month. Different locales have\ndifferent formats. For example, U.S. English would have \"January 1,\" whereas\nSpanish might have \"1 Enero.\"\n\nSee also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``, and\n``YEAR_MONTH_FORMAT``.\n\nPREPEND_WWW\n-----------\n\n*Default*: ``False``\n\nThis setting indicates whether to prepend the \"www.\" subdomain to URLs that don't have it.\nThis is used only if ``CommonMiddleware`` is installed (see the Chapter 17). See also\n``APPEND_SLASH``.\n\nROOT_URLCONF\n------------\n\n*Default*: Not defined\n\nThis is a string representing the full Python import path to your root URLconf (e.g.,\n``\"mydjangoapps.urls\"``). See Chapter 3.\n\nSECRET_KEY\n----------\n\n*Default*: (Generated automatically when you start a project)\n\nThis is a secret key for this particular Django installation. It is used to provide a seed in\nsecret-key hashing algorithms. Set this to a random string -- the longer, the\nbetter. ``django-admin.py startproject`` creates one automatically and most\nof the time you won't need to change it\n\nSEND_BROKEN_LINK_EMAILS\n-----------------------\n\n*Default*: ``False``\n\nThis setting indicates whether to send an email to the ``MANAGERS`` each time somebody visits a\nDjango-powered page that is 404-ed with a nonempty referer (i.e., a broken\nlink). This is only used if ``CommonMiddleware`` is installed (see Chapter 17).\nSee also ``IGNORABLE_404_STARTS`` and ``IGNORABLE_404_ENDS``.\n\nSERIALIZATION_MODULES\n---------------------\n\n*Default*: Not defined.\n\nSerialization is a feature still under heavy development. Refer to the online\ndocumentation at http://docs.djangoproject.com/en/dev/topics/serialization/\nfor more information.\n\nSERVER_EMAIL\n------------\n\n*Default*: ``'root@localhost'``\n\nThis is the email address that error messages come from, such as those sent to\n``ADMINS`` and ``MANAGERS``.\n\nSESSION_COOKIE_AGE\n------------------\n\n*Default*: ``1209600`` (two weeks, in seconds)\n\nThis is the age of session cookies, in seconds. See Chapter 14.\n\nSESSION_COOKIE_DOMAIN\n---------------------\n\n*Default*: ``None``\n\nThis is the domain to use for session cookies. Set this to a string such as\n``\".lawrence.com\"`` for cross-domain cookies, or use ``None`` for a standard\ndomain cookie. See Chapter 14.\n\nSESSION_COOKIE_NAME\n-------------------\n\n*Default*: ``'sessionid'``\n\nThis is the name of the cookie to use for sessions; it can be whatever you want.\nSee Chapter 14.\n\nSESSION_COOKIE_SECURE\n---------------------\n\n*Default*: ``False``\n\nThis setting indicates whether to use a secure cookie for the session cookie.\nIf this is set to ``True``, the cookie will be marked as \"secure,\"\nwhich means browsers may ensure that the cookie is only sent under an HTTPS connection.\nSee Chapter 14.\n\nSESSION_EXPIRE_AT_BROWSER_CLOSE\n-------------------------------\n\n*Default*: ``False``\n\nThis setting indicates whether to expire the session when the user closes\nhis browser. See Chapter 14.\n\nSESSION_SAVE_EVERY_REQUEST\n--------------------------\n\n*Default*: ``False``\n\nThis setting indicates whether to save the session data on every request. See Chapter 14.\n\nSITE_ID\n-------\n\n*Default*: Not defined\n\nThis is the ID, as an integer, of the current site in the ``django_site`` database\ntable. It is used so that application data can hook into specific site(s)\nand a single database can manage content for multiple sites. See Chapter 16.\n\nTEMPLATE_CONTEXT_PROCESSORS\n---------------------------\n\n*Default*::\n\n    (\"django.core.context_processors.auth\",\n    \"django.core.context_processors.debug\",\n    \"django.core.context_processors.i18n\",\n    \"django.core.context_processors.media\")\n\nThis is a tuple of callables that are used to populate the context in ``RequestContext``.\nThese callables take a request object as their argument and return a dictionary\nof items to be merged into the context. See Chapter 9.\n\nTEMPLATE_DEBUG\n--------------\n\n*Default*: ``False``\n\nThis Boolean turns template debug mode on and off. If it is ``True``, the fancy\nerror page will display a detailed report for any ``TemplateSyntaxError``. This\nreport contains the relevant snippet of the template, with the appropriate line\nhighlighted.\n\nNote that Django only displays fancy error pages if ``DEBUG`` is ``True``, so\nyou'll want to set that to take advantage of this setting.\n\nSee also ``DEBUG``.\n\nTEMPLATE_DIRS\n-------------\n\n*Default*: ``()`` (empty tuple)\n\nThis is a list of locations of the template source files, in search order. Note that these\npaths should use Unix-style forward slashes, even on Windows. See Chapters 4 and\n9.\n\nTEMPLATE_LOADERS\n----------------\n\n*Default*::\n\n    ('django.template.loaders.filesystem.load_template_source',\n    'django.template.loaders.app_directories.load_template_source')\n\nThis is a tuple of callables (as strings) that know how to import templates from\nvarious sources. See Chapter 9.\n\nTEMPLATE_STRING_IF_INVALID\n--------------------------\n\n*Default*: ``''`` (Empty string)\n\nThis is output, as a string, that the template system should use for invalid (e.g.,\nmisspelled) variables. See Chapter 9.\n\nTEST_RUNNER\n-----------\n\n*Default*: ``'django.test.simple.run_tests'``\n\nThis is the name of the method to use for starting the test suite. It is used by Django's\ntesting framework, which is covered online at\nhttp://docs.djangoproject.com/en/dev/topics/testing/.\n\nTEST_DATABASE_NAME\n------------------\n\n*Default*: ``None``\n\nThis is the name of database to use when running the test suite. If a value of ``None``\nis specified, the test database will use the name ``'test_' +\nsettings.DATABASE_NAME``. See the documentation for Django's testing framework,\nwhich is covered online at http://docs.djangoproject.com/en/dev/topics/testing/.\n\nTIME_FORMAT\n-----------\n\n*Default*: ``'P'`` (e.g., ``4 p.m.``)\n\nThis is the default formatting to use for time fields on Django admin change-list pages\n-- and, possibly, by other parts of the system. It accepts the same format as the\n``now`` tag (see Appendix E, Table E-2).\n\nSee also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``,\n``YEAR_MONTH_FORMAT``, and ``MONTH_DAY_FORMAT``.\n\nTIME_ZONE\n---------\n\n*Default*: ``'America/Chicago'``\n\nThis is a string representing the time zone for this installation. Time zones are in the\nUnix-standard ``zic`` format. One relatively complete list of time zone strings\ncan be found at\nhttp://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE.\n\nThis is the time zone to which Django will convert all dates/times --\nnot necessarily the time zone of the server. For example, one server may serve\nmultiple Django-powered sites, each with a separate time-zone setting.\n\nNormally, Django sets the ``os.environ['TZ']`` variable to the time zone you\nspecify in the ``TIME_ZONE`` setting. Thus, all your views and models will\nautomatically operate in the correct time zone. However, if you're using the\nmanually configuring settings (described above in the section titled \"Using\nSettings Without Setting DJANGO_SETTINGS_MODULE\"), Django will *not* touch the\n``TZ`` environment variable, and it will be up to you to ensure your processes\nare running in the correct environment.\n\n.. note::\n    Django cannot reliably use alternate time zones in a Windows environment. If\n    you're running Django on Windows, this variable must be set to match the\n    system time zone.\n\nURL_VALIDATOR_USER_AGENT\n------------------------\n\n*Default*: ``Django/<version> (http://www.djangoproject.com/)``\n\nThis is the string to use as the ``User-Agent`` header when checking to see if URLs\nexist (see the ``verify_exists`` option on ``URLField``; see Appendix A).\n\nUSE_ETAGS\n---------\n\n*Default*: ``False``\n\nThis Boolean specifies whether to output the ETag header. It saves\nbandwidth but slows down performance. This is only used if ``CommonMiddleware``\nis installed (see Chapter 17).\n\nUSE_I18N\n--------\n\n*Default*: ``True``\n\nThis Boolean specifies whether Django's internationalization system (see\nChapter 19) should be enabled. It provides an easy way to turn off internationalization, for\nperformance. If this is set to ``False``, Django will make some optimizations so\nas not to load the internationalization machinery.\n\nYEAR_MONTH_FORMAT\n-----------------\n\n*Default*: ``'F Y'``\n\nThis is the default formatting to use for date fields on Django admin change-list pages\n-- and, possibly, by other parts of the system -- in cases when only the year\nand month are displayed. It accepts the same format as the ``now`` tag (see\nAppendix E).\n\nFor example, when a Django admin change-list page is being filtered by a date\ndrill-down, the header for a given month displays the month and the year.\nDifferent locales have different formats. For example, U.S. English would use\n\"January 2006,\" whereas another locale might use \"2006/January.\"\n\nSee also ``DATE_FORMAT``, ``DATETIME_FORMAT``, ``TIME_FORMAT``, and\n``MONTH_DAY_FORMAT``.\n"
  },
  {
    "path": "Python/DjangoBook/appendixE.rst",
    "content": "==============================================\nAppendix E: Built-in Template Tags and Filters\n==============================================\n\nChapter 4 lists a number of the most useful built-in template tags and\nfilters. However, Django ships with many more built-in tags and filters.\nThis appendix covers them.\n\nBuilt-in Tag Reference\n======================\n\nautoescape\n----------\n\nControl the current auto-escaping behavior. This tag takes either ``on`` or\n``off`` as an argument and that determines whether auto-escaping is in effect\ninside the block.\n\nWhen auto-escaping is in effect, all variable content has HTML escaping applied\nto it before placing the result into the output (but after any filters have\nbeen applied). This is equivalent to manually applying the ``escape`` filter\nto each variable.\n\nThe only exceptions are variables that are already marked as \"safe\" from\nescaping, either by the code that populated the variable, or because it has had\nthe ``safe`` or ``escape`` filters applied.\n\nblock\n-----\n\nDefine a block that can be overridden by child templates. See\nChapter 4 for more information on template inheritance.\n\ncomment\n-------\n\nIgnore everything between ``{% comment %}`` and ``{% endcomment %}``\n\ncycle\n-----\n\nCycle among the given strings or variables each time this tag is encountered.\n\nWithin a loop, cycles among the given strings each time through the\nloop::\n\n    {% for o in some_list %}\n        <tr class=\"{% cycle 'row1' 'row2' %}\">\n            ...\n        </tr>\n    {% endfor %}\n\nYou can use variables, too. For example, if you have two template variables,\n``rowvalue1`` and ``rowvalue2``, you can cycle between their values like this::\n\n    {% for o in some_list %}\n        <tr class=\"{% cycle rowvalue1 rowvalue2 %}\">\n            ...\n        </tr>\n    {% endfor %}\n\nYes, you can mix variables and strings::\n\n    {% for o in some_list %}\n        <tr class=\"{% cycle 'row1' rowvalue2 'row3' %}\">\n            ...\n        </tr>\n    {% endfor %}\n\nIn some cases you might want to refer to the next value of a cycle from\noutside of a loop. To do this, just give the ``{% cycle %}`` tag a name, using\n\"as\", like this::\n\n    {% cycle 'row1' 'row2' as rowcolors %}\n\nFrom then on, you can insert the current value of the cycle wherever you'd like\nin your template::\n\n    <tr class=\"{% cycle rowcolors %}\">...</tr>\n    <tr class=\"{% cycle rowcolors %}\">...</tr>\n\nYou can use any number of values in a ``{% cycle %}`` tag, separated by spaces.\nValues enclosed in single (``'``) or double quotes (``\"``) are treated as\nstring literals, while values without quotes are treated as template variables.\n\nFor backwards compatibility, the ``{% cycle %}`` tag supports the much inferior\nold syntax from previous Django versions. You shouldn't use this in any new\nprojects, but for the sake of the people who are still using it, here's what it\nlooks like::\n\n    {% cycle row1,row2,row3 %}\n\nIn this syntax, each value gets interpreted as a literal string, and there's no\nway to specify variable values. Or literal commas. Or spaces. Did we mention\nyou shouldn't use this syntax in any new projects?\n\ndebug\n-----\n\nOutput a whole load of debugging information, including the current context and\nimported modules.\n\nextends\n-------\n\nSignal that this template extends a parent template.\n\nThis tag can be used in two ways:\n\n* ``{% extends \"base.html\" %}`` (with quotes) uses the literal value\n  ``\"base.html\"`` as the name of the parent template to extend.\n\n* ``{% extends variable %}`` uses the value of ``variable``. If the variable\n  evaluates to a string, Django will use that string as the name of the\n  parent template. If the variable evaluates to a ``Template`` object,\n  Django will use that object as the parent template.\n\nSee Chapter 4 for more information on template inheritance.\n\nfilter\n------\n\nFilter the contents of the variable through variable filters.\n\nFilters can also be piped through each other, and they can have arguments --\njust like in variable syntax.\n\nSample usage::\n\n    {% filter force_escape|lower %}\n        This text will be HTML-escaped, and will appear in all lowercase.\n    {% endfilter %}\n\nfirstof\n-------\n\nOutputs the first variable passed that is not False.  Outputs nothing if all the\npassed variables are False.\n\nSample usage::\n\n    {% firstof var1 var2 var3 %}\n\nThis is equivalent to::\n\n    {% if var1 %}\n        {{ var1 }}\n    {% else %}{% if var2 %}\n        {{ var2 }}\n    {% else %}{% if var3 %}\n        {{ var3 }}\n    {% endif %}{% endif %}{% endif %}\n\nYou can also use a literal string as a fallback value in case all\npassed variables are False::\n\n    {% firstof var1 var2 var3 \"fallback value\" %}\n\nfor\n---\n\nLoop over each item in an array.  For example, to display a list of athletes\nprovided in ``athlete_list``::\n\n    <ul>\n    {% for athlete in athlete_list %}\n        <li>{{ athlete.name }}</li>\n    {% endfor %}\n    </ul>\n\nYou can loop over a list in reverse by using ``{% for obj in list reversed %}``.\n\nIf you need to loop over a list of lists, you can unpack the values\nin each sub-list into individual variables. For example, if your context\ncontains a list of (x,y) coordinates called ``points``, you could use the\nfollowing to output the list of points::\n\n    {% for x, y in points %}\n        There is a point at {{ x }},{{ y }}\n    {% endfor %}\n\nThis can also be useful if you need to access the items in a dictionary.\nFor example, if your context contained a dictionary ``data``, the following\nwould display the keys and values of the dictionary::\n\n    {% for key, value in data.items %}\n        {{ key }}: {{ value }}\n    {% endfor %}\n\nThe ``for`` loop sets a number of variables available within the loop (see\nTable E-1).\n\n.. table:: Table E-1. Variables Available Inside {% for %} Loops\n\n    ==========================  ================================================\n    Variable                    Description\n    ==========================  ================================================\n    ``forloop.counter``         The current iteration of the loop (1-indexed)\n    ``forloop.counter0``        The current iteration of the loop (0-indexed)\n    ``forloop.revcounter``      The number of iterations from the end of the\n                                loop (1-indexed)\n    ``forloop.revcounter0``     The number of iterations from the end of the\n                                loop (0-indexed)\n    ``forloop.first``           True if this is the first time through the loop\n    ``forloop.last``            True if this is the last time through the loop\n    ``forloop.parentloop``      For nested loops, this is the loop \"above\" the\n                                current one\n    ==========================  ================================================\n\nThe ``for`` tag can take an optional ``{% empty %}`` clause that will be\ndisplayed if the given array is empty or could not be found::\n\n    <ul>\n    {% for athlete in athlete_list %}\n        <li>{{ athlete.name }}</li>\n    {% empty %}\n        <li>Sorry, no athlete in this list!</li>\n    {% endfor %}\n    <ul>\n\nThe above is equivalent to -- but shorter, cleaner, and possibly faster\nthan -- the following::\n\n    <ul>\n      {% if athlete_list %}\n        {% for athlete in athlete_list %}\n          <li>{{ athlete.name }}</li>\n        {% endfor %}\n      {% else %}\n        <li>Sorry, no athletes in this list.</li>\n      {% endif %}\n    </ul>\n\nif\n--\n\nThe ``{% if %}`` tag evaluates a variable, and if that variable is \"true\" (i.e.\nexists, is not empty, and is not a false boolean value) the contents of the\nblock are output::\n\n    {% if athlete_list %}\n        Number of athletes: {{ athlete_list|length }}\n    {% else %}\n        No athletes.\n    {% endif %}\n\nIn the above, if ``athlete_list`` is not empty, the number of athletes will be\ndisplayed by the ``{{ athlete_list|length }}`` variable.\n\nAs you can see, the ``if`` tag can take an optional ``{% else %}`` clause that\nwill be displayed if the test fails.\n\n``if`` tags may use ``and``, ``or`` or ``not`` to test a number of variables or\nto negate a given variable::\n\n    {% if athlete_list and coach_list %}\n        Both athletes and coaches are available.\n    {% endif %}\n\n    {% if not athlete_list %}\n        There are no athletes.\n    {% endif %}\n\n    {% if athlete_list or coach_list %}\n        There are some athletes or some coaches.\n    {% endif %}\n\n    {% if not athlete_list or coach_list %}\n        There are no athletes or there are some coaches (OK, so\n        writing English translations of boolean logic sounds\n        stupid; it's not our fault).\n    {% endif %}\n\n    {% if athlete_list and not coach_list %}\n        There are some athletes and absolutely no coaches.\n    {% endif %}\n\n``if`` tags don't allow ``and`` and ``or`` clauses within the same tag, because\nthe order of logic would be ambiguous. For example, this is invalid::\n\n    {% if athlete_list and coach_list or cheerleader_list %}\n\nIf you need to combine ``and`` and ``or`` to do advanced logic, just use nested\n``if`` tags. For example::\n\n    {% if athlete_list %}\n        {% if coach_list or cheerleader_list %}\n            We have athletes, and either coaches or cheerleaders!\n        {% endif %}\n    {% endif %}\n\nMultiple uses of the same logical operator are fine, as long as you use the\nsame operator. For example, this is valid::\n\n    {% if athlete_list or coach_list or parent_list or teacher_list %}\n\nifchanged\n---------\n\nCheck if a value has changed from the last iteration of a loop.\n\nThe ``ifchanged`` tag is used within a loop. It has two possible uses.\n\n1. Checks its own rendered contents against its previous state and only\n   displays the content if it has changed. For example, this displays a list of\n   days, only displaying the month if it changes::\n\n        <h1>Archive for {{ year }}</h1>\n\n        {% for date in days %}\n            {% ifchanged %}<h3>{{ date|date:\"F\" }}</h3>{% endifchanged %}\n            <a href=\"{{ date|date:\"M/d\"|lower }}/\">{{ date|date:\"j\" }}</a>\n        {% endfor %}\n\n2. If given a variable, check whether that variable has changed. For\n   example, the following shows the date every time it changes, but\n   only shows the hour if both the hour and the date has changed::\n\n        {% for date in days %}\n            {% ifchanged date.date %} {{ date.date }} {% endifchanged %}\n            {% ifchanged date.hour date.date %}\n                {{ date.hour }}\n            {% endifchanged %}\n        {% endfor %}\n\nThe ``ifchanged`` tag can also take an optional ``{% else %}`` clause that\nwill be displayed if the value has not changed::\n\n        {% for match in matches %}\n            <div style=\"background-color:\n                {% ifchanged match.ballot_id %}\n                    {% cycle red,blue %}\n                {% else %}\n                    grey\n                {% endifchanged %}\n            \">{{ match }}</div>\n        {% endfor %}\n\nifequal\n-------\n\nOutput the contents of the block if the two arguments equal each other.\n\nExample::\n\n    {% ifequal user.id comment.user_id %}\n        ...\n    {% endifequal %}\n\nAs in the ``{% if %}`` tag, an ``{% else %}`` clause is optional.\n\nThe arguments can be hard-coded strings, so the following is valid::\n\n    {% ifequal user.username \"adrian\" %}\n        ...\n    {% endifequal %}\n\nIt is only possible to compare an argument to template variables or strings.\nYou cannot check for equality with Python objects such as ``True`` or\n``False``.  If you need to test if something is true or false, use the ``if``\ntag instead.\n\nifnotequal\n----------\n\nJust like ``ifequal``, except it tests that the two arguments are not equal.\n\ninclude\n-------\n\nLoads a template and renders it with the current context. This is a way of\n\"including\" other templates within a template.\n\nThe template name can either be a variable or a hard-coded (quoted) string,\nin either single or double quotes.\n\nThis example includes the contents of the template ``\"foo/bar.html\"``::\n\n    {% include \"foo/bar.html\" %}\n\nThis example includes the contents of the template whose name is contained in\nthe variable ``template_name``::\n\n    {% include template_name %}\n\nAn included template is rendered with the context of the template that's\nincluding it. This example produces the output ``\"Hello, John\"``:\n\n* Context: variable ``person`` is set to ``\"john\"``.\n* Template::\n\n    {% include \"name_snippet.html\" %}\n\n* The ``name_snippet.html`` template::\n\n    Hello, {{ person }}\n\nSee also: ``{% ssi %}``.\n\nload\n----\n\nLoad a custom template tag set. See Chapter 9 for more information on custom\ntemplate libraries.\n\nnow\n---\n\nDisplay the date, formatted according to the given string.\n\nUses the same format as PHP's ``date()`` function (http://php.net/date)\nwith some custom extensions.\n\nTable E-2 shows the available format strings.\n\n.. table:: Table E-2. Available Date Format Strings\n\n    ================  ========================================  =====================\n    Format character  Description                               Example output\n    ================  ========================================  =====================\n    a                 ``'a.m.'`` or ``'p.m.'`` (Note that       ``'a.m.'``\n                      this is slightly different than PHP's\n                      output, because this includes periods\n                      to match Associated Press style.)\n    A                 ``'AM'`` or ``'PM'``.                     ``'AM'``\n    b                 Month, textual, 3 letters, lowercase.     ``'jan'``\n    B                 Not implemented.\n    d                 Day of the month, 2 digits with           ``'01'`` to ``'31'``\n                      leading zeros.\n    D                 Day of the week, textual, 3 letters.      ``'Fri'``\n    f                 Time, in 12-hour hours and minutes,       ``'1'``, ``'1:30'``\n                      with minutes left off if they're zero.\n                      Proprietary extension.\n    F                 Month, textual, long.                     ``'January'``\n    g                 Hour, 12-hour format without leading      ``'1'`` to ``'12'``\n                      zeros.\n    G                 Hour, 24-hour format without leading      ``'0'`` to ``'23'``\n                      zeros.\n    h                 Hour, 12-hour format.                     ``'01'`` to ``'12'``\n    H                 Hour, 24-hour format.                     ``'00'`` to ``'23'``\n    i                 Minutes.                                  ``'00'`` to ``'59'``\n    I                 Not implemented.\n    j                 Day of the month without leading          ``'1'`` to ``'31'``\n                      zeros.\n    l                 Day of the week, textual, long.           ``'Friday'``\n    L                 Boolean for whether it's a leap year.     ``True`` or ``False``\n    m                 Month, 2 digits with leading zeros.       ``'01'`` to ``'12'``\n    M                 Month, textual, 3 letters.                ``'Jan'``\n    n                 Month without leading zeros.              ``'1'`` to ``'12'``\n    N                 Month abbreviation in Associated Press    ``'Jan.'``, ``'Feb.'``, ``'March'``, ``'May'``\n                      style. Proprietary extension.\n    O                 Difference to Greenwich time in hours.    ``'+0200'``\n    P                 Time, in 12-hour hours, minutes and       ``'1 a.m.'``, ``'1:30 p.m.'``, ``'midnight'``, ``'noon'``, ``'12:30 p.m.'``\n                      'a.m.'/'p.m.', with minutes left off\n                      if they're zero and the special-case\n                      strings 'midnight' and 'noon' if\n                      appropriate. Proprietary extension.\n    r                 RFC 2822 formatted date.                  ``'Thu, 21 Dec 2000 16:01:07 +0200'``\n    s                 Seconds, 2 digits with leading zeros.     ``'00'`` to ``'59'``\n    S                 English ordinal suffix for day of the     ``'st'``, ``'nd'``, ``'rd'`` or ``'th'``\n                      month, 2 characters.\n    t                 Number of days in the given month.        ``28`` to ``31``\n    T                 Time zone of this machine.                ``'EST'``, ``'MDT'``\n    U                 Not implemented.\n    w                 Day of the week, digits without           ``'0'`` (Sunday) to ``'6'`` (Saturday)\n                      leading zeros.\n    W                 ISO-8601 week number of year, with        ``1``, ``53``\n                      weeks starting on Monday.\n    y                 Year, 2 digits.                           ``'99'``\n    Y                 Year, 4 digits.                           ``'1999'``\n    z                 Day of the year.                          ``0`` to ``365``\n    Z                 Time zone offset in seconds. The          ``-43200`` to ``43200``\n                      offset for timezones west of UTC is\n                      always negative, and for those east of\n                      UTC is always positive.\n    ================  ========================================  =====================\n\nExample::\n\n    It is {% now \"jS F Y H:i\" %}\n\nNote that you can backslash-escape a format string if you want to use the\n\"raw\" value. In this example, \"f\" is backslash-escaped, because otherwise\n\"f\" is a format string that displays the time. The \"o\" doesn't need to be\nescaped, because it's not a format character::\n\n    It is the {% now \"jS o\\f F\" %}\n\nThis would display as \"It is the 4th of September\".\n\nregroup\n-------\n\nRegroup a list of alike objects by a common attribute.\n\nThis complex tag is best illustrated by use of an example: say that ``people``\nis a list of people represented by dictionaries with ``first_name``,\n``last_name``, and ``gender`` keys:\n\n.. code-block:: python\n\n    people = [\n        {'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'},\n        {'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'},\n        {'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'},\n        {'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'},\n        {'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'},\n    ]\n\n...and you'd like to display a hierarchical list that is ordered by gender,\nlike this::\n\n    * Male:\n        * George Bush\n        * Bill Clinton\n    * Female:\n        * Margaret Thatcher\n        * Condoleezza Rice\n    * Unknown:\n        * Pat Smith\n\nYou can use the ``{% regroup %}`` tag to group the list of people by gender.\nThe following snippet of template code would accomplish this::\n\n    {% regroup people by gender as gender_list %}\n\n    <ul>\n    {% for gender in gender_list %}\n        <li>{{ gender.grouper }}\n        <ul>\n            {% for item in gender.list %}\n            <li>{{ item.first_name }} {{ item.last_name }}</li>\n            {% endfor %}\n        </ul>\n        </li>\n    {% endfor %}\n    </ul>\n\nLet's walk through this example. ``{% regroup %}`` takes three arguments: the\nlist you want to regroup, the attribute to group by, and the name of the\nresulting list. Here, we're regrouping the ``people`` list by the ``gender``\nattribute and calling the result ``gender_list``.\n\n``{% regroup %}`` produces a list (in this case, ``gender_list``) of\n**group objects**. Each group object has two attributes:\n\n* ``grouper`` -- the item that was grouped by (e.g., the string \"Male\" or\n  \"Female\").\n* ``list`` -- a list of all items in this group (e.g., a list of all people\n  with gender='Male').\n\nNote that ``{% regroup %}`` does not order its input! Our example relies on\nthe fact that the ``people`` list was ordered by ``gender`` in the first place.\nIf the ``people`` list did *not* order its members by ``gender``, the regrouping\nwould naively display more than one group for a single gender. For example,\nsay the ``people`` list was set to this (note that the males are not grouped\ntogether):\n\n.. code-block:: python\n\n    people = [\n        {'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'},\n        {'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'},\n        {'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'},\n        {'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'},\n        {'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'},\n    ]\n\nWith this input for ``people``, the example ``{% regroup %}`` template code\nabove would result in the following output::\n\n    * Male:\n        * Bill Clinton\n    * Unknown:\n        * Pat Smith\n    * Female:\n        * Margaret Thatcher\n    * Male:\n        * George Bush\n    * Female:\n        * Condoleezza Rice\n\nThe easiest solution to this gotcha is to make sure in your view code that the\ndata is ordered according to how you want to display it.\n\nAnother solution is to sort the data in the template using the ``dictsort``\nfilter, if your data is in a list of dictionaries::\n\n    {% regroup people|dictsort:\"gender\" by gender as gender_list %}\n\nspaceless\n---------\n\nRemoves whitespace between HTML tags. This includes tab\ncharacters and newlines.\n\nExample usage::\n\n    {% spaceless %}\n        <p>\n            <a href=\"foo/\">Foo</a>\n        </p>\n    {% endspaceless %}\n\nThis example would return this HTML::\n\n    <p><a href=\"foo/\">Foo</a></p>\n\nOnly space between *tags* is removed -- not space between tags and text. In\nthis example, the space around ``Hello`` won't be stripped::\n\n    {% spaceless %}\n        <strong>\n            Hello\n        </strong>\n    {% endspaceless %}\n\nssi\n---\n\nOutput the contents of a given file into the page.\n\nLike a simple \"include\" tag, ``{% ssi %}`` includes the contents of another\nfile -- which must be specified using an absolute path -- in the current\npage::\n\n    {% ssi /home/html/ljworld.com/includes/right_generic.html %}\n\nIf the optional \"parsed\" parameter is given, the contents of the included\nfile are evaluated as template code, within the current context::\n\n    {% ssi /home/html/ljworld.com/includes/right_generic.html parsed %}\n\nNote that if you use ``{% ssi %}``, you'll need to define\n``ALLOWED_INCLUDE_ROOTS`` in your Django settings, as a security measure.\n\nSee also: ``{% include %}``.\n\ntemplatetag\n-----------\n\nOutput one of the syntax characters used to compose template tags.\n\nSince the template system has no concept of \"escaping\", to display one of the\nbits used in template tags, you must use the ``{% templatetag %}`` tag.\n\nSee Table E-3 for the available arguments.\n\n.. table:: Table E-3. Available Arguments for templatetag Filter\n\n    ==================  =======\n    Argument            Outputs\n    ==================  =======\n    ``openblock``       ``{%``\n    ``closeblock``      ``%}``\n    ``openvariable``    ``{{``\n    ``closevariable``   ``}}``\n    ``openbrace``       ``{``\n    ``closebrace``      ``}``\n    ``opencomment``     ``{#``\n    ``closecomment``    ``#}``\n    ==================  =======\n\nurl\n---\n\nReturns an absolute URL (i.e., a URL without the domain name) matching a given\nview function and optional parameters. This is a way to output links without\nviolating the DRY principle by having to hard-code URLs in your templates::\n\n    {% url path.to.some_view arg1,arg2,name1=value1 %}\n\nThe first argument is a path to a view function in the format\n``package.package.module.function``. Additional arguments are optional and\nshould be comma-separated values that will be used as positional and keyword\narguments in the URL. All arguments required by the URLconf should be present.\n\nFor example, suppose you have a view, ``app_views.client``, whose URLconf\ntakes a client ID (here, ``client()`` is a method inside the views file\n``app_views.py``). The URLconf line might look like this::\n\n    ('^client/(\\d+)/$', 'app_views.client')\n\nIf this app's URLconf is included into the project's URLconf under a path\nsuch as this::\n\n    ('^clients/', include('project_name.app_name.urls'))\n\n...then, in a template, you can create a link to this view like this::\n\n    {% url app_views.client client.id %}\n\nThe template tag will output the string ``/clients/client/123/``.\n\nwidthratio\n----------\n\nFor creating bar charts and such, this tag calculates the ratio of a given value\nto a maximum value, and then applies that ratio to a constant.\n\nFor example::\n\n    <img src=\"bar.gif\" height=\"10\" width=\"{% widthratio this_value max_value 100 %}\" />\n\nAbove, if ``this_value`` is 175 and ``max_value`` is 200, the image in the\nabove example will be 88 pixels wide (because 175/200 = .875; .875 * 100 = 87.5\nwhich is rounded up to 88).\n\nwith\n----\n\nCaches a complex variable under a simpler name. This is useful when accessing\nan \"expensive\" method (e.g., one that hits the database) multiple times.\n\nFor example::\n\n    {% with business.employees.count as total %}\n        {{ total }} employee{{ total|pluralize }}\n    {% endwith %}\n\nThe populated variable (in the example above, ``total``) is only available\nbetween the ``{% with %}`` and ``{% endwith %}`` tags.\n\nBuilt-in Filter Reference\n=========================\n\nadd\n---\n\nAdds the argument to the value.\n\nFor example::\n\n    {{ value|add:\"2\" }}\n\nIf ``value`` is ``4``, then the output will be ``6``.\n\naddslashes\n----------\n\nAdds slashes before quotes. Useful for escaping strings in CSV, for example.\n\ncapfirst\n--------\n\nCapitalizes the first character of the value.\n\ncenter\n------\n\nCenters the value in a field of a given width.\n\ncut\n---\n\nRemoves all values of arg from the given string.\n\nFor example::\n\n    {{ value|cut:\" \"}}\n\nIf ``value`` is ``\"String with spaces\"``, the output will be ``\"Stringwithspaces\"``.\n\ndate\n----\n\nFormats a date according to the given format (same as the ``{% now %}`` tag).\n\nFor example::\n\n    {{ value|date:\"D d M Y\" }}\n\nIf ``value`` is a ``datetime`` object (e.g., the result of\n``datetime.datetime.now()``), the output will be the string\n``'Wed 09 Jan 2008'``.\n\nWhen used without a format string::\n\n    {{ value|date }}\n\n...the formatting string defined in the ``DATE_FORMAT`` setting will be\nused.\n\ndefault\n-------\n\nIf value evaluates to ``False``, use given default. Otherwise, use the value.\n\nFor example::\n\n    {{ value|default:\"nothing\" }}\n\nIf ``value`` is ``\"\"`` (the empty string), the output will be ``nothing``.\n\ndefault_if_none\n---------------\n\nIf (and only if) value is ``None``, use given default. Otherwise, use the\nvalue.\n\nNote that if an empty string is given, the default value will *not* be used.\nUse the ``default`` filter if you want to fallback for empty strings.\n\nFor example::\n\n    {{ value|default_if_none:\"nothing\" }}\n\nIf ``value`` is ``None``, the output will be the string ``\"nothing\"``.\n\ndictsort\n--------\n\nTakes a list of dictionaries and returns that list sorted by the key given in\nthe argument.\n\nFor example::\n\n    {{ value|dictsort:\"name\" }}\n\nIf ``value`` is::\n\n    [\n        {'name': 'zed', 'age': 19},\n        {'name': 'amy', 'age': 22},\n        {'name': 'joe', 'age': 31},\n    ]\n\nthen the output would be::\n\n    [\n        {'name': 'amy', 'age': 22},\n        {'name': 'joe', 'age': 31},\n        {'name': 'zed', 'age': 19},\n    ]\n\ndictsortreversed\n----------------\n\nTakes a list of dictionaries and returns that list sorted in reverse order by\nthe key given in the argument. This works exactly the same as the above filter,\nbut the returned value will be in reverse order.\n\ndivisibleby\n-----------\n\nReturns ``True`` if the value is divisible by the argument.\n\nFor example::\n\n    {{ value|divisibleby:\"3\" }}\n\nIf ``value`` is ``21``, the output would be ``True``.\n\nescape\n------\n\nEscapes a string's HTML. Specifically, it makes these replacements:\n\n* ``<`` is converted to ``&lt;``\n* ``>`` is converted to ``&gt;``\n* ``'`` (single quote) is converted to ``&#39;``\n* ``\"`` (double quote) is converted to ``&quot;``\n* ``&`` is converted to ``&amp;``\n\nThe escaping is only applied when the string is output, so it does not matter\nwhere in a chained sequence of filters you put ``escape``: it will always be\napplied as though it were the last filter. If you want escaping to be applied\nimmediately, use the ``force_escape`` filter.\n\nApplying ``escape`` to a variable that would normally have auto-escaping\napplied to the result will only result in one round of escaping being done. So\nit is safe to use this function even in auto-escaping environments. If you want\nmultiple escaping passes to be applied, use the ``force_escape`` filter.\n\nescapejs\n--------\n\nEscapes characters for use in JavaScript strings. This does *not* make the\nstring safe for use in HTML, but does protect you from syntax errors when using\ntemplates to generate JavaScript/JSON.\n\nfilesizeformat\n--------------\n\nFormat the value like a 'human-readable' file size (i.e. ``'13 KB'``,\n``'4.1 MB'``, ``'102 bytes'``, etc).\n\nFor example::\n\n    {{ value|filesizeformat }}\n\nIf ``value`` is 123456789, the output would be ``117.7 MB``.\n\nfirst\n-----\n\nReturns the first item in a list.\n\nFor example::\n\n    {{ value|first }}\n\nIf ``value`` is the list ``['a', 'b', 'c']``, the output will be ``'a'``.\n\nfix_ampersands\n--------------\n\nReplaces ampersands with ``&amp;`` entities.\n\nFor example::\n\n    {{ value|fix_ampersands }}\n\nIf ``value`` is ``Tom & Jerry``, the output will be ``Tom &amp; Jerry``.\n\nfloatformat\n-----------\n\nWhen used without an argument, rounds a floating-point number to one decimal\nplace -- but only if there's a decimal part to be displayed. For example:\n\n============  ===========================  ========\n``value``     Template                     Output\n============  ===========================  ========\n``34.23234``  ``{{ value|floatformat }}``  ``34.2``\n``34.00000``  ``{{ value|floatformat }}``  ``34``\n``34.26000``  ``{{ value|floatformat }}``  ``34.3``\n============  ===========================  ========\n\nIf used with a numeric integer argument, ``floatformat`` rounds a number to\nthat many decimal places. For example:\n\n============  =============================  ==========\n``value``     Template                       Output\n============  =============================  ==========\n``34.23234``  ``{{ value|floatformat:3 }}``  ``34.232``\n``34.00000``  ``{{ value|floatformat:3 }}``  ``34.000``\n``34.26000``  ``{{ value|floatformat:3 }}``  ``34.260``\n============  =============================  ==========\n\nIf the argument passed to ``floatformat`` is negative, it will round a number\nto that many decimal places -- but only if there's a decimal part to be\ndisplayed. For example:\n\n============  ================================  ==========\n``value``     Template                          Output\n============  ================================  ==========\n``34.23234``  ``{{ value|floatformat:\"-3\" }}``  ``34.232``\n``34.00000``  ``{{ value|floatformat:\"-3\" }}``  ``34``\n``34.26000``  ``{{ value|floatformat:\"-3\" }}``  ``34.260``\n============  ================================  ==========\n\nUsing ``floatformat`` with no argument is equivalent to using ``floatformat``\nwith an argument of ``-1``.\n\nforce_escape\n------------\n\nApplies HTML escaping to a string (see the ``escape`` filter for details).\nThis filter is applied *immediately* and returns a new, escaped string. This\nis useful in the rare cases where you need multiple escaping or want to apply\nother filters to the escaped results. Normally, you want to use the ``escape``\nfilter.\n\nget_digit\n---------\n\nGiven a whole number, returns the requested digit, where 1 is the right-most\ndigit, 2 is the second-right-most digit, etc. Returns the original value for\ninvalid input (if input or argument is not an integer, or if argument is less\nthan 1). Otherwise, output is always an integer.\n\nFor example::\n\n    {{ value|get_digit:\"2\" }}\n\nIf ``value`` is ``123456789``, the output will be ``8``.\n\niriencode\n---------\n\nConverts an IRI (Internationalized Resource Identifier) to a string that is\nsuitable for including in a URL. This is necessary if you're trying to use\nstrings containing non-ASCII characters in a URL.\n\nIt's safe to use this filter on a string that has already gone through the\n``urlencode`` filter.\n\njoin\n----\n\nJoins a list with a string, like Python's ``str.join(list)``\n\nFor example::\n\n    {{ value|join:\" // \" }}\n\nIf ``value`` is the list ``['a', 'b', 'c']``, the output will be the string\n``\"a // b // c\"``.\n\nlast\n----\n\nReturns the last item in a list.\n\nFor example::\n\n    {{ value|last }}\n\nIf ``value`` is the list ``['a', 'b', 'c', 'd']``, the output will be the string\n``\"d\"``.\n\nlength\n------\n\nReturns the length of the value. This works for both strings and lists.\n\nFor example::\n\n    {{ value|length }}\n\nIf ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``4``.\n\nlength_is\n---------\n\nReturns ``True`` if the value's length is the argument, or ``False`` otherwise.\n\nFor example::\n\n    {{ value|length_is:\"4\" }}\n\nIf ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``True``.\n\nlinebreaks\n----------\n\nReplaces line breaks in plain text with appropriate HTML; a single\nnewline becomes an HTML line break (``<br />``) and a new line\nfollowed by a blank line becomes a paragraph break (``</p>``).\n\nFor example::\n\n    {{ value|linebreaks }}\n\nIf ``value`` is ``Joel\\nis a slug``, the output will be ``<p>Joel<br />is a\nslug</p>``.\n\nlinebreaksbr\n~~~~~~~~~~~~\n\nConverts all newlines in a piece of plain text to HTML line breaks\n(``<br />``).\n\nlinenumbers\n-----------\n\nDisplays text with line numbers.\n\nljust\n-----\n\nLeft-aligns the value in a field of a given width.\n\n**Argument:** field size\n\nlower\n-----\n\nConverts a string into all lowercase.\n\nFor example::\n\n    {{ value|lower }}\n\nIf ``value`` is ``Still MAD At Yoko``, the output will be ``still mad at yoko``.\n\nmake_list\n---------\n\nReturns the value turned into a list. For an integer, it's a list of\ndigits. For a string, it's a list of characters.\n\nFor example::\n\n    {{ value|make_list }}\n\nIf ``value`` is the string ``\"Joel\"``, the output would be the list\n``[u'J', u'o', u'e', u'l']``. If ``value`` is ``123``, the output will be the\nlist ``[1, 2, 3]``.\n\nphone2numeric\n-------------\n\nConverts a phone number (possibly containing letters) to its numerical\nequivalent. For example, ``'800-COLLECT'`` will be converted to\n``'800-2655328'``.\n\nThe input doesn't have to be a valid phone number. This will happily convert\nany string.\n\npluralize\n---------\n\nReturns a plural suffix if the value is not 1. By default, this suffix is ``'s'``.\n\nExample::\n\n    You have {{ num_messages }} message{{ num_messages|pluralize }}.\n\nFor words that require a suffix other than ``'s'``, you can provide an alternate\nsuffix as a parameter to the filter.\n\nExample::\n\n    You have {{ num_walruses }} walrus{{ num_walrus|pluralize:\"es\" }}.\n\nFor words that don't pluralize by simple suffix, you can specify both a\nsingular and plural suffix, separated by a comma.\n\nExample::\n\n    You have {{ num_cherries }} cherr{{ num_cherries|pluralize:\"y,ies\" }}.\n\npprint\n------\n\nA wrapper around the Python standard library's ``pprint.pprint`` function --\nfor debugging, really.\n\nrandom\n------\n\nReturns a random item from the given list.\n\nFor example::\n\n    {{ value|random }}\n\nIf ``value`` is the list ``['a', 'b', 'c', 'd']``, the output could be ``\"b\"``.\n\nremovetags\n----------\n\nRemoves a space-separated list of [X]HTML tags from the output.\n\nFor example::\n\n    {{ value|removetags:\"b span\"|safe }}\n\nIf ``value`` is ``\"<b>Joel</b> <button>is</button> a <span>slug</span>\"`` the\noutput will be ``\"Joel <button>is</button> a slug\"``.\n\nrjust\n-----\n\nRight-aligns the value in a field of a given width.\n\n**Argument:** field size\n\nsafe\n----\n\nMarks a string as not requiring further HTML escaping prior to output. When\nautoescaping is off, this filter has no effect.\n\nsafeseq\n-------\n\nApplies the ``safe`` filter to each element of a sequence.  Useful in\nconjunction with other filters that operate on sequences, such as\n``join``.  For example::\n\n    {{ some_list|safeseq|join:\", \" }}\n\nYou couldn't use the ``safe`` filter directly in this case, as it would\nfirst convert the variable into a string, rather than working with the\nindividual elements of the sequence.\n\nslice\n-----\n\nReturns a slice of the list.\n\nUses the same syntax as Python's list slicing. See\nhttp://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice\nfor an introduction.\n\nExample::\n\n    {{ some_list|slice:\":2\" }}\n\nslugify\n-------\n\nConverts to lowercase, removes non-word characters (only alphanumerics and\nunderscores are kept) and converts spaces to hyphens. Also strips leading and trailing\nwhitespace.\n\nFor example::\n\n    {{ value|slugify }}\n\nIf ``value`` is ``\"Joel is a slug\"``, the output will be ``\"joel-is-a-slug\"``.\n\nstringformat\n------------\n\nFormats the variable according to the argument, a string formatting specifier.\nThis specifier uses Python string formatting syntax, with the exception that\nthe leading \"%\" is dropped.\n\nSee http://docs.python.org/library/stdtypes.html#string-formatting-operations\nfor documentation of Python string formatting.\n\nFor example::\n\n    {{ value|stringformat:\"s\" }}\n\nIf ``value`` is ``\"Joel is a slug\"``, the output will be ``\"Joel is a slug\"``.\n\nstriptags\n---------\n\nStrips all [X]HTML tags.\n\nFor example::\n\n    {{ value|striptags }}\n\nIf ``value`` is ``\"<b>Joel</b> <button>is</button> a <span>slug</span>\"``, the\noutput will be ``\"Joel is a slug\"``.\n\ntime\n----\n\nFormats a time according to the given format (same as the `now`_ tag).\nThe time filter will only accept parameters in the format string that relate\nto the time of day, not the date (for obvious reasons). If you need to\nformat a date, use the `date`_ filter.\n\nFor example::\n\n    {{ value|time:\"H:i\" }}\n\nIf ``value`` is equivalent to ``datetime.datetime.now()``, the output will be\nthe string ``\"01:23\"``.\n\nWhen used without a format string::\n\n    {{ value|time }}\n\n...the formatting string defined in the ``TIME_FORMAT`` setting will be\nused.\n\ntimesince\n---------\n\nFormats a date as the time since that date (e.g., \"4 days, 6 hours\").\n\nTakes an optional argument that is a variable containing the date to use as\nthe comparison point (without the argument, the comparison point is *now*).\nFor example, if ``blog_date`` is a date instance representing midnight on 1\nJune 2006, and ``comment_date`` is a date instance for 08:00 on 1 June 2006,\nthen ``{{ blog_date|timesince:comment_date }}`` would return \"8 hours\".\n\nComparing offset-naive and offset-aware datetimes will return an empty string.\n\nMinutes is the smallest unit used, and \"0 minutes\" will be returned for any\ndate that is in the future relative to the comparison point.\n\ntimeuntil\n---------\n\nSimilar to ``timesince``, except that it measures the time from now until the\ngiven date or datetime. For example, if today is 1 June 2006 and\n``conference_date`` is a date instance holding 29 June 2006, then\n``{{ conference_date|timeuntil }}`` will return \"4 weeks\".\n\nTakes an optional argument that is a variable containing the date to use as\nthe comparison point (instead of *now*). If ``from_date`` contains 22 June\n2006, then ``{{ conference_date|timeuntil:from_date }}`` will return \"1 week\".\n\nComparing offset-naive and offset-aware datetimes will return an empty string.\n\nMinutes is the smallest unit used, and \"0 minutes\" will be returned for any\ndate that is in the past relative to the comparison point.\n\ntitle\n-----\n\nConverts a string into titlecase.\n\ntruncatewords\n-------------\n\nTruncates a string after a certain number of words.\n\n**Argument:** Number of words to truncate after\n\nFor example::\n\n    {{ value|truncatewords:2 }}\n\nIf ``value`` is ``\"Joel is a slug\"``, the output will be ``\"Joel is ...\"``.\n\ntruncatewords_html\n------------------\n\nSimilar to ``truncatewords``, except that it is aware of HTML tags. Any tags\nthat are opened in the string and not closed before the truncation point, are\nclosed immediately after the truncation.\n\nThis is less efficient than ``truncatewords``, so should only be used when it\nis being passed HTML text.\n\nunordered_list\n--------------\n\nRecursively takes a self-nested list and returns an HTML unordered list --\nWITHOUT opening and closing <ul> tags.\n\nThe list is assumed to be in the proper format. For example, if ``var`` contains\n``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``, then\n``{{ var|unordered_list }}`` would return::\n\n    <li>States\n    <ul>\n            <li>Kansas\n            <ul>\n                    <li>Lawrence</li>\n                    <li>Topeka</li>\n            </ul>\n            </li>\n            <li>Illinois</li>\n    </ul>\n    </li>\n\nupper\n-----\n\nConverts a string into all uppercase.\n\nFor example::\n\n    {{ value|upper }}\n\nIf ``value`` is ``\"Joel is a slug\"``, the output will be ``\"JOEL IS A SLUG\"``.\n\nurlencode\n---------\n\nEscapes a value for use in a URL.\n\nurlize\n------\n\nConverts URLs in plain text into clickable links.\n\nNote that if ``urlize`` is applied to text that already contains HTML markup,\nthings won't work as expected. Apply this filter only to *plain* text.\n\nFor example::\n\n    {{ value|urlize }}\n\nIf ``value`` is ``\"Check out www.djangoproject.com\"``, the output will be\n``\"Check out <a\nhref=\"http://www.djangoproject.com\">www.djangoproject.com</a>\"``.\n\nurlizetrunc\n-----------\n\nConverts URLs into clickable links, truncating URLs longer than the given\ncharacter limit.\n\nAs with urlize_, this filter should only be applied to *plain* text.\n\n**Argument:** Length to truncate URLs to\n\nFor example::\n\n    {{ value|urlizetrunc:15 }}\n\nIf ``value`` is ``\"Check out www.djangoproject.com\"``, the output would be\n``'Check out <a\nhref=\"http://www.djangoproject.com\">www.djangopr...</a>'``.\n\nwordcount\n---------\n\nReturns the number of words.\n\nwordwrap\n--------\n\nWraps words at specified line length.\n\n**Argument:** number of characters at which to wrap the text\n\nFor example::\n\n    {{ value|wordwrap:5 }}\n\nIf ``value`` is ``Joel is a slug``, the output would be::\n\n    Joel\n    is a\n    slug\n\nyesno\n-----\n\nGiven a string mapping values for ``True``, ``False``, and (optionally) ``None``,\nreturns one of those strings according to the value (see Table F-4).\n\n.. table:: Table E-4. Examples of the yesno Filter\n\n    ==========  ======================  ==================================\n    Value       Argument                Outputs\n    ==========  ======================  ==================================\n    ``True``    ``\"yeah,no,maybe\"``     ``yeah``\n    ``False``   ``\"yeah,no,maybe\"``     ``no``\n    ``None``    ``\"yeah,no,maybe\"``     ``maybe``\n    ``None``    ``\"yeah,no\"``           ``\"no\"`` (converts None to False\n                                        if no mapping for None is given)\n    ==========  ======================  ==================================\n"
  },
  {
    "path": "Python/DjangoBook/appendixF.rst",
    "content": "====================================\nAppendix F: The django-admin Utility\n====================================\n\n``django-admin.py`` is Django's command-line utility for administrative tasks.\nThis appendix explains its many powers.\n\nYou'll usually access ``django-admin.py`` through a project's ``manage.py``\nwrapper. ``manage.py`` is automatically created in each Django project and is a\nthin wrapper around ``django-admin.py``. It takes care of two things for you\nbefore delegating to ``django-admin.py``:\n\n* It puts your project's package on ``sys.path``.\n\n* It sets the ``DJANGO_SETTINGS_MODULE`` environment variable so that it\n  points to your project's ``settings.py`` file.\n\nThe ``django-admin.py`` script should be on your system path if you installed\nDjango via its ``setup.py`` utility. If it's not on your path, you can find it in\n``site-packages/django/bin`` within your Python installation. Consider\nsymlinking it from some place on your path, such as ``/usr/local/bin``.\n\nWindows users, who do not have symlinking functionality available,\ncan copy ``django-admin.py`` to a location on their existing path or edit the\n``PATH`` settings (under Settings ~TRA Control Panel ~TRA System ~TRA Advanced ~TRA\nEnvironment) to point to its installed location.\n\nGenerally, when working on a single Django project, it's easier to use\n``manage.py``. Use ``django-admin.py`` with ``DJANGO_SETTINGS_MODULE`` or the\n``--settings`` command-line option, if you need to switch between multiple\nDjango settings files.\n\nThe command-line examples throughout this appendix use ``django-admin.py`` to\nbe consistent, but any example can use ``manage.py`` just as well.\n\nUsage\n=====\n\nHere's how to use it::\n\n    django-admin.py <subcommand> [options]\n    manage.py <subcommand> [options]\n\n``subcommand`` should be one of the subcommands listed in this appendix.\n``options``, which is optional, should be zero or more of the options available\nfor the given subcommand.\n\nGetting runtime help\n--------------------\n\nRun ``django-admin.py help`` to display a list of all available subcommands.\nRun ``django-admin.py help <subcommand>`` to display a description of the\ngiven subcommand and a list of its available options.\n\nApp names\n---------\n\nMany subcommands take a list of \"app names.\" An \"app name\" is the basename of\nthe package containing your models. For example, if your ``INSTALLED_APPS``\ncontains the string ``'mysite.blog'``, the app name is ``blog``.\n\nDetermining the version\n-----------------------\n\nRun ``django-admin.py --version`` to display the current Django version.\n\nExamples of output::\n\n    1.1\n    1.0\n    0.96\n    0.97-pre-SVN-6069\n\nDisplaying debug output\n-----------------------\n\nUse ``--verbosity`` to specify the amount of notification and debug information\nthat ``django-admin.py`` should print to the console.\n\nAvailable subcommands\n=====================\n\ncleanup\n-------\n\nCan be run as a cronjob or directly to clean out old data from the database\n(only expired sessions at the moment).\n\ncompilemessages\n---------------\n\nCompiles .po files created with ``makemessages`` to .mo files for use with\nthe builtin gettext support. See Chapter 19.\n\n--locale\n~~~~~~~~\n\nUse the ``--locale`` or ``-l`` option to specify the locale to process.\nIf not provided all locales are processed.\n\nExample usage::\n\n    django-admin.py compilemessages --locale=br_PT\n\ncreatecachetable\n----------------\n\nCreates a cache table with a given name for use with the database cache\nbackend. See Chapter 15.\n\nExample usage::\n\n    django-admin.py createcachetable my_cache_table\n\ncreatesuperuser\n---------------\n\nCreates a superuser account (a user who has all permissions). This is\nuseful if you need to create an initial superuser account but did not\ndo so during ``syncdb``, or if you need to programmatically generate\nsuperuser accounts for your site(s).\n\nWhen run interactively, this command will prompt for a password for\nthe new superuser account. When run non-interactively, no password\nwill be set, and the superuser account will not be able to log in until\na password has been manually set for it.\n\nThe username and e-mail address for the new account can be supplied by\nusing the ``--username`` and ``--email`` arguments on the command\nline. If either of those is not supplied, ``createsuperuser`` will prompt for\nit when running interactively.\n\nThis command is only available if Django's authentication system\n(``django.contrib.auth``) is in ``INSTALLED_APPS``. See Chapter 14.\n\ndbshell\n-------\n\nRuns the command-line client for the database engine specified in your\n``DATABASE_ENGINE`` setting, with the connection parameters specified in your\n``DATABASE_USER``, ``DATABASE_PASSWORD``, etc., settings.\n\n* For PostgreSQL, this runs the ``psql`` command-line client.\n* For MySQL, this runs the ``mysql`` command-line client.\n* For SQLite, this runs the ``sqlite3`` command-line client.\n\nThis command assumes the programs are on your ``PATH`` so that a simple call to\nthe program name (``psql``, ``mysql``, ``sqlite3``) will find the program in\nthe right place. There's no way to specify the location of the program\nmanually.\n\ndiffsettings\n------------\n\nDisplays differences between the current settings file and Django's default\nsettings.\n\nSettings that don't appear in the defaults are followed by ``\"###\"``. For\nexample, the default settings don't define ``ROOT_URLCONF``, so\n``ROOT_URLCONF`` is followed by ``\"###\"`` in the output of ``diffsettings``.\n\nNote that Django's default settings live in ``django/conf/global_settings.py``,\nif you're ever curious to see the full list of defaults.\n\ndumpdata\n--------\n\nOutputs to standard output all data in the database associated with the named\napplication(s).\n\nIf no application name is provided, all installed applications will be dumped.\n\nThe output of ``dumpdata`` can be used as input for ``loaddata``.\n\nNote that ``dumpdata`` uses the default manager on the model for selecting the\nrecords to dump. If you're using a custom manager as the default manager and it\nfilters some of the available records, not all of the objects will be dumped.\n\nExample usage::\n\n    django-admin.py dumpdata books\n\nUse the ``--exclude`` option to exclude a specific application from the\napplications whose contents are output. For example, to specifically exclude\nthe `auth` application from the output, you would call::\n\n    django-admin.py dumpdata --exclude=auth\n\nIf you want to exclude multiple applications, use multiple ``--exclude``\ndirectives::\n\n    django-admin.py dumpdata --exclude=auth --exclude=contenttypes\n\nBy default, ``dumpdata`` will format its output in JSON, but you can use the\n``--format`` option to specify another format. Currently supported formats\nare listed in :ref:`serialization-formats`.\n\nBy default, ``dumpdata`` will output all data on a single line. This isn't\neasy for humans to read, so you can use the ``--indent`` option to\npretty-print the output with a number of indentation spaces.\n\nIn addition to specifying application names, you can provide a list of\nindividual models, in the form of ``appname.Model``. If you specify a model\nname to ``dumpdata``, the dumped output will be restricted to that model,\nrather than the entire application. You can also mix application names and\nmodel names.\n\nflush\n-----\n\nReturns the database to the state it was in immediately after syncdb was\nexecuted. This means that all data will be removed from the database, any\npost-synchronization handlers will be re-executed, and the ``initial_data``\nfixture will be re-installed.\n\nUse the ``--noinput`` option to suppress all user prompting, such as \"Are\nyou sure?\" confirmation messages. This is useful if ``django-admin.py`` is\nbeing executed as an unattended, automated script.\n\ninspectdb\n---------\n\nIntrospects the database tables in the database pointed-to by the\n``DATABASE_NAME`` setting and outputs a Django model module (a ``models.py``\nfile) to standard output.\n\nUse this if you have a legacy database with which you'd like to use Django.\nThe script will inspect the database and create a model for each table within\nit.\n\nAs you might expect, the created models will have an attribute for every field\nin the table. Note that ``inspectdb`` has a few special cases in its field-name\noutput:\n\n* If ``inspectdb`` cannot map a column's type to a model field type, it'll\n  use ``TextField`` and will insert the Python comment\n  ``'This field type is a guess.'`` next to the field in the generated\n  model.\n\n* If the database column name is a Python reserved word (such as\n  ``'pass'``, ``'class'`` or ``'for'``), ``inspectdb`` will append\n  ``'_field'`` to the attribute name. For example, if a table has a column\n  ``'for'``, the generated model will have a field ``'for_field'``, with\n  the ``db_column`` attribute set to ``'for'``. ``inspectdb`` will insert\n  the Python comment\n  ``'Field renamed because it was a Python reserved word.'`` next to the\n  field.\n\nThis feature is meant as a shortcut, not as definitive model generation. After\nyou run it, you'll want to look over the generated models yourself to make\ncustomizations. In particular, you'll need to rearrange models' order, so that\nmodels that refer to other models are ordered properly.\n\nPrimary keys are automatically introspected for PostgreSQL, MySQL and\nSQLite, in which case Django puts in the ``primary_key=True`` where\nneeded.\n\n``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection\nonly works in PostgreSQL and with certain types of MySQL tables.\n\nloaddata <fixture fixture ...>\n------------------------------\n\nSearches for and loads the contents of the named fixture into the database.\n\nWhat's a \"fixture\"?\n~~~~~~~~~~~~~~~~~~~\n\nA *fixture* is a collection of files that contain the serialized contents of\nthe database. Each fixture has a unique name, and the files that comprise the\nfixture can be distributed over multiple directories, in multiple applications.\n\nDjango will search in three locations for fixtures:\n\n1. In the ``fixtures`` directory of every installed application\n2. In any directory named in the ``FIXTURE_DIRS`` setting\n3. In the literal path named by the fixture\n\nDjango will load any and all fixtures it finds in these locations that match\nthe provided fixture names.\n\nIf the named fixture has a file extension, only fixtures of that type\nwill be loaded. For example::\n\n    django-admin.py loaddata mydata.json\n\nwould only load JSON fixtures called ``mydata``. The fixture extension\nmust correspond to the registered name of a\nserializer (e.g., ``json`` or ``xml``). For more on serializers, see the Django\ndocs.\n\nIf you omit the extensions, Django will search all available fixture types\nfor a matching fixture. For example::\n\n    django-admin.py loaddata mydata\n\nwould look for any fixture of any fixture type called ``mydata``. If a fixture\ndirectory contained ``mydata.json``, that fixture would be loaded\nas a JSON fixture.\n\nThe fixtures that are named can include directory components. These\ndirectories will be included in the search path. For example::\n\n    django-admin.py loaddata foo/bar/mydata.json\n\nwould search ``<appname>/fixtures/foo/bar/mydata.json`` for each installed\napplication,  ``<dirname>/foo/bar/mydata.json`` for each directory in\n``FIXTURE_DIRS``, and the literal path ``foo/bar/mydata.json``.\n\nWhen fixture files are processed, the data is saved to the database as is.\nModel defined ``save`` methods and ``pre_save`` signals are not called.\n\nNote that the order in which fixture files are processed is undefined. However,\nall fixture data is installed as a single transaction, so data in\none fixture can reference data in another fixture. If the database backend\nsupports row-level constraints, these constraints will be checked at the\nend of the transaction.\n\nThe ``dumpdata`` command can be used to generate input for ``loaddata``.\n\nCompressed fixtures\n~~~~~~~~~~~~~~~~~~~\n\nFixtures may be compressed in ``zip``, ``gz``, or ``bz2`` format. For example::\n\n    django-admin.py loaddata mydata.json\n\nwould look for any of ``mydata.json``, ``mydata.json.zip``,\n``mydata.json.gz``, or ``mydata.json.bz2``.  The first file contained within a\nzip-compressed archive is used.\n\nNote that if two fixtures with the same name but different\nfixture type are discovered (for example, if ``mydata.json`` and\n``mydata.xml.gz`` were found in the same fixture directory), fixture\ninstallation will be aborted, and any data installed in the call to\n``loaddata`` will be removed from the database.\n\n.. admonition:: MySQL and Fixtures\n\n    Unfortunately, MySQL isn't capable of completely supporting all the\n    features of Django fixtures. If you use MyISAM tables, MySQL doesn't\n    support transactions or constraints, so you won't get a rollback if\n    multiple fixture files are found, or validation of fixture data fails.\n\n    If you use InnoDB tables, you won't be able to have any forward\n    references in your data files -- MySQL doesn't provide a mechanism to\n    defer checking of row constraints until a transaction is committed.\n\nmakemessages\n------------\n\nRuns over the entire source tree of the current directory and pulls out all\nstrings marked for translation. It creates (or updates) a message file in the\nconf/locale (in the django tree) or locale (for project and application)\ndirectory. After making changes to the messages files you need to compile them\nwith ``compilemessages`` for use with the builtin gettext support. See Chapter\n19 for details.\n\n--all\n~~~~~\n\nUse the ``--all`` or ``-a`` option to update the message files for all\navailable languages.\n\nExample usage::\n\n    django-admin.py makemessages --all\n\n--extension\n~~~~~~~~~~~\n\nUse the ``--extension`` or ``-e`` option to specify a list of file extensions\nto examine (default: \".html\").\n\nExample usage::\n\n    django-admin.py makemessages --locale=de --extension xhtml\n\nSeparate multiple extensions with commas or use -e or --extension multiple times::\n\n    django-admin.py makemessages --locale=de --extension=html,txt --extension xml\n\n--locale\n~~~~~~~~\n\nUse the ``--locale`` or ``-l`` option to specify the locale to process.\n\nExample usage::\n\n    django-admin.py makemessages --locale=br_PT\n\n--domain\n~~~~~~~~\n\nUse the ``--domain`` or ``-d`` option to change the domain of the messages files.\nCurrently supported:\n\n* ``django`` for all ``*.py`` and ``*.html`` files (default)\n* ``djangojs`` for ``*.js`` files\n\n.. _django-admin-reset:\n\nreset <appname appname ...>\n---------------------------\n\nExecutes the equivalent of ``sqlreset`` for the given app name(s).\n\n--noinput\n~~~~~~~~~\n\nUse the ``--noinput`` option to suppress all user prompting, such as\n\"Are you sure?\" confirmation messages. This is useful if ``django-admin.py``\nis being executed as an unattended, automated script.\n\nrunfcgi [options]\n-----------------\n\nStarts a set of FastCGI processes suitable for use with any Web server that\nsupports the FastCGI protocol. See Chapter 12 for details. Requires the Python\nFastCGI module from flup: http://www.saddi.com/software/flup/\n\nrunserver\n---------\n\nStarts a lightweight development Web server on the local machine. By default,\nthe server runs on port 8000 on the IP address 127.0.0.1. You can pass in an\nIP address and port number explicitly.\n\nIf you run this script as a user with normal privileges (recommended), you\nmight not have access to start a port on a low port number. Low port numbers\nare reserved for the superuser (root).\n\nDO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through\nsecurity audits or performance tests. (And that's how it's gonna stay. We're in\nthe business of making Web frameworks, not Web servers, so improving this\nserver to be able to handle a production environment is outside the scope of\nDjango.)\n\nThe development server automatically reloads Python code for each request, as\nneeded. You don't need to restart the server for code changes to take effect.\n\nWhen you start the server, and each time you change Python code while the\nserver is running, the server will validate all of your installed models. (See\nthe ``validate`` command below.) If the validator finds errors, it will print\nthem to standard output, but it won't stop the server.\n\nYou can run as many servers as you want, as long as they're on separate ports.\nJust execute ``django-admin.py runserver`` more than once.\n\nNote that the default IP address, 127.0.0.1, is not accessible from other\nmachines on your network. To make your development server viewable to other\nmachines on the network, use its own IP address (e.g. ``192.168.2.1``) or\n``0.0.0.0`` (which you can use if you don't know what your IP address is\non the network).\n\nUse the ``--adminmedia`` option to tell Django where to find the various CSS\nand JavaScript files for the Django admin interface. Normally, the development\nserver serves these files out of the Django source tree magically, but you'd\nwant to use this if you made any changes to those files for your own site.\n\nExample usage::\n\n    django-admin.py runserver --adminmedia=/tmp/new-admin-style/\n\nUse the ``--noreload`` option to disable the use of the auto-reloader. This\nmeans any Python code changes you make while the server is running will *not*\ntake effect if the particular Python modules have already been loaded into\nmemory.\n\nExample usage::\n\n    django-admin.py runserver --noreload\n\nExamples of using different ports and addresses\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nPort 8000 on IP address 127.0.0.1::\n\n\tdjango-admin.py runserver\n\nPort 8000 on IP address 1.2.3.4::\n\n\tdjango-admin.py runserver 1.2.3.4:8000\n\nPort 7000 on IP address 127.0.0.1::\n\n    django-admin.py runserver 7000\n\nPort 7000 on IP address 1.2.3.4::\n\n    django-admin.py runserver 1.2.3.4:7000\n\nServing static files with the development server\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nBy default, the development server doesn't serve any static files for your site\n(such as CSS files, images, things under ``MEDIA_URL`` and so forth).\n\nshell\n-----\n\nStarts the Python interactive interpreter.\n\nDjango will use IPython (http://ipython.scipy.org/), if it's installed. If you\nhave IPython installed and want to force use of the \"plain\" Python interpreter,\nuse the ``--plain`` option, like so::\n\n    django-admin.py shell --plain\n\nsql <appname appname ...>\n-------------------------\n\nPrints the CREATE TABLE SQL statements for the given app name(s).\n\nsqlall <appname appname ...>\n----------------------------\n\nPrints the CREATE TABLE and initial-data SQL statements for the given app name(s).\n\nRefer to the description of ``sqlcustom`` for an explanation of how to\nspecify initial data.\n\nsqlclear <appname appname ...>\n------------------------------\n\nPrints the DROP TABLE SQL statements for the given app name(s).\n\nsqlcustom <appname appname ...>\n-------------------------------\n\nPrints the custom SQL statements for the given app name(s).\n\nFor each model in each specified app, this command looks for the file\n``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given app name and\n``<modelname>`` is the model's name in lowercase. For example, if you have an\napp ``news`` that includes a ``Story`` model, ``sqlcustom`` will attempt\nto read a file ``news/sql/story.sql`` and append it to the output of this\ncommand.\n\nEach of the SQL files, if given, is expected to contain valid SQL. The SQL\nfiles are piped directly into the database after all of the models'\ntable-creation statements have been executed. Use this SQL hook to make any\ntable modifications, or insert any SQL functions into the database.\n\nNote that the order in which the SQL files are processed is undefined.\n\nsqlflush\n--------\n\nPrints the SQL statements that would be executed for the `flush`_ command.\n\nsqlindexes <appname appname ...>\n--------------------------------\n\nPrints the CREATE INDEX SQL statements for the given app name(s).\n\nsqlreset <appname appname ...>\n------------------------------\n\nPrints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s).\n\nsqlsequencereset <appname appname ...>\n--------------------------------------\n\nPrints the SQL statements for resetting sequences for the given app name(s).\n\nstartapp <appname>\n------------------\n\nCreates a Django app directory structure for the given app name in the current\ndirectory.\n\nstartproject <projectname>\n--------------------------\n\nCreates a Django project directory structure for the given project name in the\ncurrent directory.\n\nThis command is disabled when the ``--settings`` option to\n``django-admin.py`` is used, or when the environment variable\n``DJANGO_SETTINGS_MODULE`` has been set. To re-enable it in these\nsituations, either omit the ``--settings`` option or unset\n``DJANGO_SETTINGS_MODULE``.\n\nsyncdb\n------\n\nCreates the database tables for all apps in ``INSTALLED_APPS`` whose tables\nhave not already been created.\n\nUse this command when you've added new applications to your project and want to\ninstall them in the database. This includes any apps shipped with Django that\nmight be in ``INSTALLED_APPS`` by default. When you start a new project, run\nthis command to install the default apps.\n\n.. admonition:: Syncdb will not alter existing tables\n\n   ``syncdb`` will only create tables for models which have not yet been\n   installed. It will *never* issue ``ALTER TABLE`` statements to match\n   changes made to a model class after installation. Changes to model classes\n   and database schemas often involve some form of ambiguity and, in those\n   cases, Django would have to guess at the correct changes to make. There is\n   a risk that critical data would be lost in the process.\n\n   If you have made changes to a model and wish to alter the database tables\n   to match, use the ``sql`` command to display the new SQL structure and\n   compare that to your existing table schema to work out the changes.\n\nIf you're installing the ``django.contrib.auth`` application, ``syncdb`` will\ngive you the option of creating a superuser immediately.\n\n``syncdb`` will also search for and install any fixture named ``initial_data``\nwith an appropriate extension (e.g. ``json`` or ``xml``). See the\ndocumentation for ``loaddata`` for details on the specification of fixture\ndata files.\n\n--noinput\n~~~~~~~~~\n\nUse the ``--noinput`` option to suppress all user prompting, such as\n\"Are you sure?\" confirmation messages. This is useful if ``django-admin.py``\nis being executed as an unattended, automated script.\n\ntest\n----\n\nRuns tests for all installed models. See the Django documentation for more\non testing.\n\n--noinput\n~~~~~~~~~\n\nUse the ``--noinput`` option to suppress all user prompting, such as\n\"Are you sure?\" confirmation messages. This is useful if ``django-admin.py``\nis being executed as an unattended, automated script.\n\ntestserver <fixture fixture ...>\n--------------------------------\n\nRuns a Django development server (as in ``runserver``) using data from the\ngiven fixture(s).\n\nFor more, see the Django documentation.\n\nvalidate\n--------\n\nValidates all installed models (according to the ``INSTALLED_APPS`` setting)\nand prints validation errors to standard output.\n\nDefault options\n===============\n\nAlthough some subcommands may allow their own custom options, every subcommand\nallows for the following options:\n\n--pythonpath\n------------\n\nExample usage::\n\n    django-admin.py syncdb --pythonpath='/home/djangoprojects/myproject'\n\nAdds the given filesystem path to the Python import search path. If this\nisn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment\nvariable.\n\nNote that this option is unnecessary in ``manage.py``, because it takes care of\nsetting the Python path for you.\n\n--settings\n----------\n\nExample usage::\n\n    django-admin.py syncdb --settings=mysite.settings\n\nExplicitly specifies the settings module to use. The settings module should be\nin Python package syntax, e.g. ``mysite.settings``. If this isn't provided,\n``django-admin.py`` will use the ``DJANGO_SETTINGS_MODULE`` environment\nvariable.\n\nNote that this option is unnecessary in ``manage.py``, because it uses\n``settings.py`` from the current project by default.\n\n--traceback\n-----------\n\nExample usage::\n\n    django-admin.py syncdb --traceback\n\nBy default, ``django-admin.py`` will show a simple error message whenever an\nerror occurs. If you specify ``--traceback``, ``django-admin.py``  will\noutput a full stack trace whenever an exception is raised.\n\n--verbosity\n-----------\n\nExample usage::\n\n    django-admin.py syncdb --verbosity 2\n\nUse ``--verbosity`` to specify the amount of notification and debug information\nthat ``django-admin.py`` should print to the console.\n\n* ``0`` means no output.\n* ``1`` means normal output (default).\n* ``2`` means verbose output.\n\nExtra niceties\n==============\n\nSyntax coloring\n---------------\n\nThe ``django-admin.py`` / ``manage.py`` commands that output SQL to standard\noutput will use pretty color-coded output if your terminal supports\nANSI-colored output. It won't use the color codes if you're piping the\ncommand's output to another program.\n\nBash completion\n---------------\n\nIf you use the Bash shell, consider installing the Django bash completion\nscript, which lives in ``extras/django_bash_completion`` in the Django\ndistribution. It enables tab-completion of ``django-admin.py`` and\n``manage.py`` commands, so you can, for instance...\n\n* Type ``django-admin.py``.\n* Press [TAB] to see all available options.\n* Type ``sql``, then [TAB], to see all available options whose names start\n  with ``sql``.\n"
  },
  {
    "path": "Python/DjangoBook/appendixG.rst",
    "content": "========================================\nAppendix G: Request and Response Objects\n========================================\n\nDjango uses request and response objects to pass state through the system.\n\nWhen a page is requested, Django creates an ``HttpRequest`` object that\ncontains metadata about the request. Then Django loads the appropriate view,\npassing the ``HttpRequest`` as the first argument to the view function. Each\nview is responsible for returning an ``HttpResponse`` object.\n\nWe've used these objects often throughout the book; this appendix explains the\ncomplete APIs for ``HttpRequest`` and ``HttpResponse`` objects.\n\nHttpRequest\n===========\n\n``HttpRequest`` represents a single HTTP request from some user-agent.\n\nMuch of the important information about the request is available as attributes\non the ``HttpRequest`` instance (see Table G-1). All attributes except\n``session`` should be considered read-only.\n\n.. table:: Table G-1. Attributes of HttpRequest Objects\n\n    ==================  =======================================================\n    Attribute           Description\n    ==================  =======================================================\n    ``path``            A string representing the full path to the requested\n                        page, not including the domain -- for example,\n                        ``\"/music/bands/the_beatles/\"``.\n\n    ``method``          A string representing the HTTP method used in the\n                        request. This is guaranteed to be uppercase. For\n                        example::\n\n                            if request.method == 'GET':\n                                do_something()\n                            elif request.method == 'POST':\n                                do_something_else()\n\n    ``encoding``        A string representing the current encoding used to\n                        decode form submission data (or ``None``, which means\n                        the ``DEFAULT_CHARSET`` setting is used).\n\n                        You can write to this attribute to change the encoding\n                        used when accessing the form data. Any subsequent\n                        attribute accesses (such as reading from ``GET`` or\n                        ``POST``) will use the new ``encoding`` value.  Useful\n                        if you know the form data is not in the\n                        ``DEFAULT_CHARSET`` encoding.\n\n    ``GET``             A dictionary-like object containing all given HTTP GET\n                        parameters. See the upcoming ``QueryDict`` documentation.\n\n    ``POST``            A dictionary-like object containing all given HTTP POST\n                        parameters. See the upcoming ``QueryDict`` documentation.\n\n                        It's possible that a request can come in via POST with\n                        an empty ``POST`` dictionary -- if, say, a form is\n                        requested via the POST HTTP method but does not\n                        include form data. Therefore, you shouldn't use ``if\n                        request.POST`` to check for use of the POST method;\n                        instead, use ``if request.method == \"POST\"`` (see\n                        the ``method`` entry in this table).\n\n                        Note: ``POST`` does *not* include file-upload\n                        information. See ``FILES``.\n\n    ``REQUEST``         For convenience, a dictionary-like object that searches\n                        ``POST`` first, and then ``GET``. Inspired by PHP's\n                        ``$_REQUEST``.\n\n                        For example, if ``GET = {\"name\": \"john\"}`` and ``POST\n                        = {\"age\": '34'}``, ``REQUEST[\"name\"]`` would be\n                        ``\"john\"``, and ``REQUEST[\"age\"]`` would be ``\"34\"``.\n\n                        It's strongly suggested that you use ``GET`` and\n                        ``POST`` instead of ``REQUEST``, because the former\n                        are more explicit.\n\n    ``COOKIES``         A standard Python dictionary containing all cookies.\n                        Keys and values are strings. See Chapter 14 for more\n                        on using cookies.\n\n    ``FILES``           A dictionary-like object that maps filenames to\n                        ``UploadedFile`` objects. See the Django\n                        documentation for more.\n\n    ``META``            A standard Python dictionary containing all available\n                        HTTP headers. Available headers depend on the client\n                        and server, but here are some examples:\n\n                        * ``CONTENT_LENGTH``\n                        * ``CONTENT_TYPE``\n                        * ``QUERY_STRING``: The raw unparsed query string\n                        * ``REMOTE_ADDR``: The IP address of the client\n                        * ``REMOTE_HOST``: The hostname of the client\n                        * ``SERVER_NAME``: The hostname of the server.\n                        * ``SERVER_PORT``: The port of the server\n\n                        Any HTTP headers are available in ``META`` as keys\n                        prefixed with ``HTTP_``, converted to uppercase and\n                        substituting underscores for hyphens. For example:\n\n                        * ``HTTP_ACCEPT_ENCODING``\n                        * ``HTTP_ACCEPT_LANGUAGE``\n                        * ``HTTP_HOST``: The HTTP ``Host`` header sent by\n                          the client\n                        * ``HTTP_REFERER``: The referring page, if any\n                        * ``HTTP_USER_AGENT``: The client's user-agent string\n                        * ``HTTP_X_BENDER``: The value of the ``X-Bender``\n                          header, if set\n\n    ``user``            A ``django.contrib.auth.models.User`` object\n                        representing the currently logged-in user. If the user\n                        isn't currently logged in, ``user`` will be set to an\n                        instance of\n                        ``django.contrib.auth.models.AnonymousUser``. You can\n                        tell them apart with ``is_authenticated()``, like so::\n\n                            if request.user.is_authenticated():\n                                # Do something for logged-in users.\n                            else:\n                                # Do something for anonymous users.\n\n                        ``user`` is available only if your Django installation\n                        has the ``AuthenticationMiddleware`` activated.\n\n                        For the complete details of authentication and users,\n                        see Chapter 14.\n\n    ``session``         A readable and writable, dictionary-like object that\n                        represents the current session. This is available only\n                        if your Django installation has session support\n                        activated. See Chapter 14.\n\n    ``raw_post_data``   The raw HTTP POST data. This is useful for advanced\n                        processing.\n    ==================  =======================================================\n\nRequest objects also have a few useful methods, as shown in Table G-2.\n\n.. table:: Table G-2. HttpRequest Methods\n\n    ======================  ===================================================\n    Method                  Description\n    ======================  ===================================================\n    ``__getitem__(key)``    Returns the GET/POST value for the given key,\n                            checking POST first, and then GET. Raises\n                            ``KeyError`` if the key doesn't exist.\n\n                            This lets you use dictionary-accessing syntax on\n                            an ``HttpRequest`` instance.\n\n                            For example, ``request[\"foo\"]`` is the same as\n                            checking ``request.POST[\"foo\"]`` and then\n                            ``request.GET[\"foo\"]``.\n\n    ``has_key()``           Returns ``True`` or ``False``, designating whether\n                            ``request.GET`` or ``request.POST`` has the given\n                            key.\n\n    ``get_host()``          Returns the originating host of the request using\n                            information from the ``HTTP_X_FORWARDED_HOST`` and\n                            ``HTTP_HOST`` headers (in that order). If they\n                            don't provide a value, the method uses a\n                            combination of ``SERVER_NAME`` and\n                            ``SERVER_PORT``.\n\n    ``get_full_path()``     Returns the ``path``, plus an appended query\n                            string, if applicable. For example,\n                            ``\"/music/bands/the_beatles/?print=true\"``\n\n    ``is_secure()``         Returns ``True`` if the request is secure; that\n                            is, if it was made with HTTPS.\n    ======================  ===================================================\n\nQueryDict Objects\n-----------------\n\nIn an ``HttpRequest`` object, the ``GET`` and ``POST`` attributes are\ninstances of ``django.http.QueryDict``. ``QueryDict`` is a dictionary-like\nclass customized to deal with multiple values for the same key. This is\nnecessary because some HTML form elements, notably ``<select\nmultiple=\"multiple\">``, pass multiple values for the same key.\n\n``QueryDict`` instances are immutable, unless you create a ``copy()`` of them.\nThat means you can't change attributes of ``request.POST`` and ``request.GET``\ndirectly.\n\n``QueryDict`` implements the all standard dictionary methods, because it's a\nsubclass of dictionary. Exceptions are outlined in Table G-3.\n\n.. table:: Table G-3. How QueryDicts Differ from Standard Dictionaries.\n\n    ==================  =======================================================\n    Method              Differences from Standard dict Implementation\n    ==================  =======================================================\n    ``__getitem__``     Works just like a dictionary. However, if the key\n                        has more than one value, ``__getitem__()`` returns the\n                        last value.\n\n    ``__setitem__``     Sets the given key to ``[value]`` (a Python list whose\n                        single element is ``value``). Note that this, as other\n                        dictionary functions that have side effects, can\n                        be called only on a mutable ``QueryDict`` (one that was\n                        created via ``copy()``).\n\n    ``get()``           If the key has more than one value, ``get()`` returns\n                        the last value just like ``__getitem__``.\n\n    ``update()``        Takes either a ``QueryDict`` or standard dictionary.\n                        Unlike the standard dictionary's ``update`` method,\n                        this method *appends* to the current dictionary items\n                        rather than replacing them::\n\n                            >>> q = QueryDict('a=1')\n                            >>> q = q.copy() # to make it mutable\n                            >>> q.update({'a': '2'})\n                            >>> q.getlist('a')\n                            ['1', '2']\n                            >>> q['a'] # returns the last\n                            ['2']\n\n    ``items()``         Just like the standard dictionary ``items()`` method,\n                        except this uses the same last-value logic as\n                        ``__getitem()__``::\n\n                             >>> q = QueryDict('a=1&a=2&a=3')\n                             >>> q.items()\n                             [('a', '3')]\n\n    ``values()``        Just like the standard dictionary ``values()`` method,\n                        except this uses the same last-value logic as\n                        ``__getitem()__``.\n    ==================  =======================================================\n\nIn addition, ``QueryDict`` has the methods shown in Table G-4.\n\n.. table:: G-4. Extra (Nondictionary) QueryDict Methods\n\n    ==========================  ===============================================\n    Method                      Description\n    ==========================  ===============================================\n    ``copy()``                  Returns a copy of the object, using\n                                ``copy.deepcopy()`` from the Python standard\n                                library. The copy will be mutable -- that is,\n                                you can change its values.\n\n    ``getlist(key)``            Returns the data with the requested key, as a\n                                Python list. Returns an empty list if the key\n                                doesn't exist. It's guaranteed to return a\n                                list of some sort.\n\n    ``setlist(key, list_)``     Sets the given key to ``list_`` (unlike\n                                ``__setitem__()``).\n\n    ``appendlist(key, item)``   Appends an item to the internal list associated\n                                with ``key``.\n\n    ``setlistdefault(key, a)``  Just like ``setdefault``, except it takes a\n                                list of values instead of a single value.\n\n    ``lists()``                 Like ``items()``, except it includes all\n                                values, as a list, for each member of the\n                                dictionary. For example::\n\n                                    >>> q = QueryDict('a=1&a=2&a=3')\n                                    >>> q.lists()\n                                    [('a', ['1', '2', '3'])]\n\n\n    ``urlencode()``             Returns a string of the data in query-string\n                                format (e.g., ``\"a=2&b=3&b=5\"``).\n    ==========================  ===============================================\n\nA Complete Example\n------------------\n\nFor example, given this HTML form::\n\n    <form action=\"/foo/bar/\" method=\"post\">\n    <input type=\"text\" name=\"your_name\" />\n    <select multiple=\"multiple\" name=\"bands\">\n        <option value=\"beatles\">The Beatles</option>\n        <option value=\"who\">The Who</option>\n        <option value=\"zombies\">The Zombies</option>\n    </select>\n    <input type=\"submit\" />\n    </form>\n\nif the user enters ``\"John Smith\"`` in the ``your_name`` field and selects\nboth \"The Beatles\" and \"The Zombies\" in the multiple select box, here's what\nDjango's request object would have::\n\n    >>> request.GET\n    {}\n    >>> request.POST\n    {'your_name': ['John Smith'], 'bands': ['beatles', 'zombies']}\n    >>> request.POST['your_name']\n    'John Smith'\n    >>> request.POST['bands']\n    'zombies'\n    >>> request.POST.getlist('bands')\n    ['beatles', 'zombies']\n    >>> request.POST.get('your_name', 'Adrian')\n    'John Smith'\n    >>> request.POST.get('nonexistent_field', 'Nowhere Man')\n    'Nowhere Man'\n\n.. admonition:: Implementation Note:\n\n    The ``GET``, ``POST``, ``COOKIES``, ``FILES``, ``META``, ``REQUEST``,\n    ``raw_post_data``, and ``user`` attributes are all lazily loaded. That means\n    Django doesn't spend resources calculating the values of those attributes until\n    your code requests them.\n\nHttpResponse\n============\n\nIn contrast to ``HttpRequest`` objects, which are created automatically by\nDjango, ``HttpResponse`` objects are your responsibility. Each view you write\nis responsible for instantiating, populating, and returning an\n``HttpResponse``.\n\nThe ``HttpResponse`` class lives at ``django.http.HttpResponse``.\n\nConstruction HttpResponses\n--------------------------\n\nTypically, you'll construct an ``HttpResponse`` to pass the contents of the\npage, as a string, to the ``HttpResponse`` constructor::\n\n    >>> response = HttpResponse(\"Here's the text of the Web page.\")\n    >>> response = HttpResponse(\"Text only, please.\", mimetype=\"text/plain\")\n\nBut if you want to add content incrementally, you can use ``response`` as a\nfilelike object::\n\n    >>> response = HttpResponse()\n    >>> response.write(\"<p>Here's the text of the Web page.</p>\")\n    >>> response.write(\"<p>Here's another paragraph.</p>\")\n\nYou can pass ``HttpResponse`` an iterator rather than passing it\nhard-coded strings. If you use this technique, follow these guidelines:\n\n* The iterator should return strings.\n\n* If an ``HttpResponse`` has been initialized with an iterator as its\n  content, you can't use the ``HttpResponse`` instance as a filelike\n  object. Doing so will raise ``Exception``.\n\nFinally, note that ``HttpResponse`` implements a ``write()`` method, which\nmakes is suitable for use anywhere that Python expects a filelike object. See\nChapter 8 for some examples of using this technique.\n\nSetting Headers\n---------------\n\nYou can add and delete headers using dictionary syntax::\n\n    >>> response = HttpResponse()\n    >>> response['X-DJANGO'] = \"It's the best.\"\n    >>> del response['X-PHP']\n    >>> response['X-DJANGO']\n    \"It's the best.\"\n\nYou can also use ``has_header(header)`` to check for the existence of a header.\n\nAvoid setting ``Cookie`` headers by hand; instead, see Chapter 14 for\ninstructions on how cookies work in Django.\n\nHttpResponse Subclasses\n-----------------------\n\nDjango includes a number of ``HttpResponse`` subclasses that handle different\ntypes of HTTP responses (see Table G-5). Like ``HttpResponse``, these subclasses live in\n``django.http``.\n\n.. table:: Table G-5. HttpResponse Subclasses\n\n    ==================================  =======================================\n    Class                               Description\n    ==================================  =======================================\n    ``HttpResponseRedirect``            The constructor takes a single argument:\n                                        the path to redirect to. This can\n                                        be a fully qualified URL (e.g.,\n                                        ``'http://search.yahoo.com/'``) or\n                                        an absolute URL with no domain (e.g.,\n                                        ``'/search/'``). Note that this\n                                        returns an HTTP status code 302.\n\n    ``HttpResponsePermanentRedirect``   Like ``HttpResponseRedirect``, but it\n                                        returns a permanent redirect (HTTP\n                                        status code 301) instead of a \"found\"\n                                        redirect (status code 302).\n\n    ``HttpResponseNotModified``         The constructor doesn't take any\n                                        arguments. Use this to designate that\n                                        a page hasn't been modified since the\n                                        user's last request.\n\n    ``HttpResponseBadRequest``          Acts just like ``HttpResponse`` but\n                                        uses a 400 status code.\n\n    ``HttpResponseNotFound``            Acts just like ``HttpResponse`` but\n                                        uses a 404 status code.\n\n    ``HttpResponseForbidden``           Acts just like ``HttpResponse`` but\n                                        uses a 403 status code.\n\n    ``HttpResponseNotAllowed``          Like ``HttpResponse``, but uses a 405\n                                        status code. It takes a single, required\n                                        argument: a list of permitted methods\n                                        (e.g., ``['GET', 'POST']``).\n\n    ``HttpResponseGone``                Acts just like ``HttpResponse`` but\n                                        uses a 410 status code.\n\n    ``HttpResponseServerError``         Acts just like ``HttpResponse`` but\n                                        uses a 500 status code.\n    ==================================  =======================================\n\nYou can, of course, define your own ``HttpResponse`` subclass to support\ndifferent types of responses not supported out of the box.\n\nReturning Errors\n----------------\n\nReturning HTTP error codes in Django is easy. We've already mentioned the\n``HttpResponseNotFound``, ``HttpResponseForbidden``,\n``HttpResponseServerError``, and other subclasses. Just return an instance of one\nof those subclasses instead of a normal ``HttpResponse`` in order to signify\nan error, for example::\n\n    def my_view(request):\n        # ...\n        if foo:\n            return HttpResponseNotFound('<h1>Page not found</h1>')\n        else:\n            return HttpResponse('<h1>Page was found</h1>')\n\nBecause a 404 error is by far the most common HTTP error, there's an easier\nway to handle it.\n\nWhen you return an error such as ``HttpResponseNotFound``, you're responsible\nfor defining the HTML of the resulting error page::\n\n    return HttpResponseNotFound('<h1>Page not found</h1>')\n\nFor convenience, and because it's a good idea to have a consistent 404 error page\nacross your site, Django provides an ``Http404`` exception. If you raise\n``Http404`` at any point in a view function, Django will catch it and return the\nstandard error page for your application, along with an HTTP error code 404.\n\nHere's an example::\n\n    from django.http import Http404\n\n    def detail(request, poll_id):\n        try:\n            p = Poll.objects.get(pk=poll_id)\n        except Poll.DoesNotExist:\n            raise Http404\n        return render(request, 'polls/detail.html', {'poll': p})\n\nIn order to use the ``Http404`` exception to its fullest, you should create a\ntemplate that is displayed when a 404 error is raised. This template should be\ncalled ``404.html``, and it should be located in the top level of your template tree.\n\nCustomizing the 404 (Not Found) View\n------------------------------------\n\nWhen you raise an ``Http404`` exception, Django loads a special view devoted\nto handling 404 errors. By default, it's the view\n``django.views.defaults.page_not_found``, which loads and renders the template\n``404.html``.\n\nThis means you need to define a ``404.html`` template in your root template\ndirectory. This template will be used for all 404 errors.\n\nThis ``page_not_found`` view should suffice for 99% of Web applications, but\nif you want to override the 404 view, you can specify ``handler404`` in your\nURLconf, like so::\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        ...\n    )\n\n    handler404 = 'mysite.views.my_custom_404_view'\n\nBehind the scenes, Django determines the 404 view by looking for\n``handler404``. By default, URLconfs contain the following line::\n\n    from django.conf.urls.defaults import *\n\nThat takes care of setting ``handler404`` in the current module. As you can\nsee in ``django/conf/urls/defaults.py``, ``handler404`` is set to\n``'django.views.defaults.page_not_found'`` by default.\n\nThere are three things to note about 404 views:\n\n* The 404 view is also called if Django doesn't find a match after checking\n  every regular expression in the URLconf.\n\n* If you don't define your own 404 view -- and simply use the default,\n  which is recommended -- you still have one obligation: to create a\n  ``404.html`` template in the root of your template directory. The default\n  404 view will use that template for all 404 errors.\n\n* If ``DEBUG`` is set to ``True`` (in your settings module), then your 404\n  view will never be used, and the traceback will be displayed instead.\n\nCustomizing the 500 (Server Error) View\n---------------------------------------\n\nSimilarly, Django executes special-case behavior in the case of runtime errors\nin view code. If a view results in an exception, Django will, by default, call\nthe view ``django.views.defaults.server_error``, which loads and renders the\ntemplate ``500.html``.\n\nThis means you need to define a ``500.html`` template in your root template\ndirectory. This template will be used for all server errors.\n\nThis ``server_error`` view should suffice for 99% of Web applications, but if\nyou want to override the view, you can specify ``handler500`` in your\nURLconf, like so::\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        ...\n    )\n\n    handler500 = 'mysite.views.my_custom_error_view'\n"
  },
  {
    "path": "Python/DjangoBook/bin/post_compile",
    "content": "#!/bin/bash\n\nsphinx-build -q -b html -d _build/doctrees . _build/html\n"
  },
  {
    "path": "Python/DjangoBook/chapter01.rst",
    "content": "=================================\nChapter 1: Introduction to Django\n=================================\n\nThis book is about Django, a Web development framework that saves you time\nand makes Web development a joy. Using Django, you can build and maintain\nhigh-quality Web applications with minimal fuss.\n\nAt its best, Web development is an exciting, creative act; at its worst,\nit can be a repetitive, frustrating nuisance. Django lets you focus on the fun\nstuff -- the crux of your Web application -- while easing the pain of the\nrepetitive bits. In doing so, it provides high-level abstractions of common\nWeb development patterns, shortcuts for frequent programming tasks, and\nclear conventions for how to solve problems. At the same time, Django tries to\nstay out of your way, letting you work outside the scope of the framework as\nneeded.\n\nThe goal of this book is to make you a Django expert. The focus is twofold.\nFirst, we explain, in depth, what Django does and how to build Web\napplications with it. Second, we discuss higher-level concepts where\nappropriate, answering the question \"How can I apply these tools effectively\nin my own projects?\" By reading this book, you'll learn the skills needed to\ndevelop powerful Web sites quickly, with code that is clean and easy to\nmaintain.\n\nWhat Is a Web Framework?\n========================\n\nDjango is a prominent member of a new generation of *Web frameworks* -- but\nwhat does that term mean, precisely?\n\nTo answer that question, let's consider the design of a Web application written\nin Python *without* a framework. Throughout this book, we'll take this approach\nof showing you basic ways of getting work done *without* shortcuts, in the hope\nthat you'll recognize why shortcuts are so helpful. (It's also valuable to know\nhow to get things done without shortcuts because shortcuts aren't always\navailable. And most importantly, knowing *why* things work the way they do\nmakes you a better Web developer.)\n\nOne of the simplest, most direct ways to build a Python Web app from scratch is\nto use the Common Gateway Interface (CGI) standard, which was a popular\ntechnique circa 1998. Here's a high-level explanation of how it works: just\ncreate a Python script that outputs HTML, then save the script to a Web server\nwith a \".cgi\" extension and visit the page in your Web browser. That's it.\n\nHere's an example Python CGI script that displays the ten most recently\npublished books from a database. Don't worry about syntax details; just get a\nfeel for the basic things it's doing::\n\n    #!/usr/bin/env python\n\n    import MySQLdb\n\n    print \"Content-Type: text/html\\n\"\n    print \"<html><head><title>Books</title></head>\"\n    print \"<body>\"\n    print \"<h1>Books</h1>\"\n    print \"<ul>\"\n\n    connection = MySQLdb.connect(user='me', passwd='letmein', db='my_db')\n    cursor = connection.cursor()\n    cursor.execute(\"SELECT name FROM books ORDER BY pub_date DESC LIMIT 10\")\n\n    for row in cursor.fetchall():\n        print \"<li>%s</li>\" % row[0]\n\n    print \"</ul>\"\n    print \"</body></html>\"\n\n    connection.close()\n\nFirst, to fulfill the requirements of CGI, this code prints a \"Content-Type\"\nline, followed by a blank line. It prints some introductory HTML, connects to a\ndatabase and runs a query to retrieve the names of the latest ten books.\nLooping over those books, it generates an HTML list of the titles. Finally, it\nprints the closing HTML and closes the database connection.\n\nWith a one-off page like this one, the write-it-from-scratch approach isn't\nnecessarily bad. For one thing, this code is simple to comprehend -- even a\nnovice developer can read these 16 lines of Python and understand everything it\ndoes, from start to finish. There's nothing else to learn, no other code to\nread. It's also simple to deploy: just save this code in a file that ends with\n\".cgi\", upload that file to a Web server, and visit that page with a browser.\n\nBut despite its simplicity, this approach has a number of problems and\nannoyances. Ask yourself these questions:\n\n* What happens when multiple parts of your application need to connect to\n  the database? Surely that database-connecting code shouldn't need to be\n  duplicated in each individual CGI script. The pragmatic thing to do would\n  be to refactor it into a shared function.\n\n* Should a developer really have to worry about printing the\n  \"Content-Type\" line and remembering to close the database connection?\n  This sort of boilerplate reduces programmer productivity and introduces\n  opportunities for mistakes. These setup- and teardown-related tasks would\n  best be handled by some common infrastructure.\n\n* What happens when this code is reused in multiple environments, each with\n  a separate database and password? At this point, some\n  environment-specific configuration becomes essential.\n\n* What happens when a Web designer who has no experience coding Python\n  wishes to redesign the page? One wrong character could crash the entire\n  application. Ideally, the logic of the page -- the retrieval of book\n  titles from the database -- would be separate from the HTML display of\n  the page, so that a designer could edit the latter without affecting the\n  former.\n\nThese problems are precisely what a Web framework intends to solve. A Web\nframework provides a programming infrastructure for your applications, so that\nyou can focus on writing clean, maintainable code without having to reinvent\nthe wheel. In a nutshell, that's what Django does.\n\nThe MVC Design Pattern\n======================\n\nLet's dive in with a quick example that demonstrates the difference between the\nprevious approach and a Web framework's approach. Here's how you might write\nthe previous CGI code using Django. The first thing to note is that that we\nsplit it over four Python files (``models.py``, ``views.py``, ``urls.py``) and\nan HTML template (``latest_books.html``)::\n\n    # models.py (the database tables)\n\n    from django.db import models\n\n    class Book(models.Model):\n        name = models.CharField(max_length=50)\n        pub_date = models.DateField()\n\n\n    # views.py (the business logic)\n\n    from django.shortcuts import render\n    from models import Book\n\n    def latest_books(request):\n        book_list = Book.objects.order_by('-pub_date')[:10]\n        return render(request, 'latest_books.html', {'book_list': book_list})\n\n\n    # urls.py (the URL configuration)\n\n    from django.conf.urls.defaults import *\n    import views\n\n    urlpatterns = patterns('',\n        (r'^latest/$', views.latest_books),\n    )\n\n\n    # latest_books.html (the template)\n\n    <html><head><title>Books</title></head>\n    <body>\n    <h1>Books</h1>\n    <ul>\n    {% for book in book_list %}\n    <li>{{ book.name }}</li>\n    {% endfor %}\n    </ul>\n    </body></html>\n\nAgain, don't worry about the particulars of syntax; just get a feel for the\noverall design. The main thing to note here is the *separation of concerns*:\n\n* The ``models.py`` file contains a description of the database table,\n  represented by a Python class. This class is called a *model*. Using it,\n  you can create, retrieve, update and delete records in your database\n  using simple Python code rather than writing repetitive SQL statements.\n\n* The ``views.py`` file contains the business logic for the page. The\n  ``latest_books()`` function is called a *view*.\n\n* The ``urls.py`` file specifies which view is called for a given URL\n  pattern. In this case, the URL ``/latest/`` will be handled by the\n  ``latest_books()`` function. In other words, if your domain is\n  example.com, any visit to the URL http://example.com/latest/ will call\n  the ``latest_books()`` function.\n\n* The ``latest_books.html`` file is an HTML template that describes the\n  design of the page. It uses a template language with basic logic\n  statements -- e.g., ``{% for book in book_list %}``.\n\nTaken together, these pieces loosely follow a pattern called\nModel-View-Controller (MVC). Simply put, MVC is way of developing software so\nthat the code for defining and accessing data (the model) is separate from\nrequest-routing logic (the controller), which in turn is separate from the user\ninterface (the view). (We'll discuss MVC in more depth in Chapter 5.)\n\nA key advantage of such an approach is that components are *loosely coupled*.\nEach distinct piece of a Django-powered Web application has a single key\npurpose and can be changed independently without affecting the other pieces.\nFor example, a developer can change the URL for a given part of the application\nwithout affecting the underlying implementation. A designer can change a page's\nHTML without having to touch the Python code that renders it. A database\nadministrator can rename a database table and specify the change in a single\nplace, rather than having to search and replace through a dozen files.\n\nIn this book, each component of MVC gets its own chapter. Chapter 3 covers\nviews, Chapter 4 covers templates, and Chapter 5 covers models.\n\nDjango's History\n================\n\nBefore we dive into more code, we should take a moment to explain Django's\nhistory. We noted above that we'll be showing you how to do things *without*\nshortcuts so that you more fully understand the shortcuts. Similarly, it's\nuseful to understand *why* Django was created, because knowledge of the history\nwill put into context why Django works the way it does.\n\nIf you've been building Web applications for a while, you're probably familiar\nwith the problems in the CGI example we presented earlier. The classic Web\ndeveloper's path goes something like this:\n\n1. Write a Web application from scratch.\n2. Write another Web application from scratch.\n3. Realize the application from step 1 shares much in common with the\n   application from step 2.\n4. Refactor the code so that application 1 shares code with application 2.\n5. Repeat steps 2-4 several times.\n6. Realize you've invented a framework.\n\nThis is precisely how Django itself was created!\n\nDjango grew organically from real-world applications written by a Web\ndevelopment team in Lawrence, Kansas, USA. It was born in the fall of 2003,\nwhen the Web programmers at the *Lawrence Journal-World* newspaper, Adrian\nHolovaty and Simon Willison, began using Python to build applications.\n\nThe World Online team, responsible for the production and maintenance of\nseveral local news sites, thrived in a development environment dictated by\njournalism deadlines. For the sites -- including LJWorld.com, Lawrence.com and\nKUsports.com -- journalists (and management) demanded that features be added\nand entire applications be built on an intensely fast schedule, often with only\ndays' or hours' notice. Thus, Simon and Adrian developed a time-saving Web\ndevelopment framework out of necessity -- it was the only way they could build\nmaintainable applications under the extreme deadlines.\n\nIn summer 2005, after having developed this framework to a point where it was\nefficiently powering most of World Online's sites, the team, which now included\nJacob Kaplan-Moss, decided to release the framework as open source software.\nThey released it in July 2005 and named it Django, after the jazz guitarist\nDjango Reinhardt.\n\nNow, several years later, Django is a well-established open source project with\ntens of thousands of users and contributors spread across the planet. Two of\nthe original World Online developers (the \"Benevolent Dictators for Life,\"\nAdrian and Jacob) still provide central guidance for the framework's growth,\nbut it's much more of a collaborative team effort.\n\nThis history is relevant because it helps explain two key things. The first is\nDjango's \"sweet spot.\" Because Django was born in a news environment, it offers\nseveral features (such as its admin site, covered in Chapter 6) that are\nparticularly well suited for \"content\" sites -- sites like Amazon.com,\ncraigslist.org, and washingtonpost.com that offer dynamic, database-driven\ninformation. Don't let that turn you off, though -- although Django is\nparticularly good for developing those sorts of sites, that doesn't preclude it\nfrom being an effective tool for building any sort of dynamic Web site.\n(There's a difference between being *particularly effective* at something and\nbeing *ineffective* at other things.)\n\nThe second matter to note is how Django's origins have shaped the culture of\nits open source community. Because Django was extracted from real-world code,\nrather than being an academic exercise or commercial product, it is acutely\nfocused on solving Web development problems that Django's developers themselves\nhave faced -- and continue to face. As a result, Django itself is actively\nimproved on an almost daily basis. The framework's maintainers have a vested\ninterest in making sure Django saves developers time, produces applications\nthat are easy to maintain and performs well under load. If nothing else, the\ndevelopers are motivated by their own selfish desires to save themselves time\nand enjoy their jobs. (To put it bluntly, they eat their own dog food.)\n\n.. AH The following sections are the type of content that typically appears\n.. AH in a book's Introduction section, but we include it here because this\n.. AH chapter serves as an introduction.\n\nHow to Read This Book\n=====================\n\nIn writing this book, we tried to strike a balance between readability and\nreference, with a bias toward readability. Our goal with this book, as stated\nearlier, is to make you a Django expert, and we believe the best way to teach is\nthrough prose and plenty of examples, rather than providing an exhaustive\nbut bland catalog of Django features. (As the saying goes, you can't expect to\nteach somebody how to speak a language merely by teaching them the alphabet.)\n\nWith that in mind, we recommend that you read Chapters 1 through 12 in order.\nThey form the foundation of how to use Django; once you've read them, you'll be\nable to build and deploy Django-powered Web sites. Specifically, Chapters 1\nthrough 7 are the \"core curriculum,\" Chapters 8 through 11 cover more advanced\nDjango usage, and Chapter 12 covers deployment. The remaining chapters, 13\nthrough 20, focus on specific Django features and can be read in any order.\n\nThe appendixes are for reference. They, along with the free documentation at\nhttp://www.djangoproject.com/, are probably what you'll flip back to occasionally to\nrecall syntax or find quick synopses of what certain parts of Django do.\n\nRequired Programming Knowledge\n------------------------------\n\nReaders of this book should understand the basics of procedural and\nobject-oriented programming: control structures (e.g., ``if``, ``while``,\n``for``), data structures (lists, hashes/dictionaries), variables, classes and\nobjects.\n\nExperience in Web development is, as you may expect, very helpful, but it's\nnot required to understand this book. Throughout the book, we try to promote\nbest practices in Web development for readers who lack this experience.\n\nRequired Python Knowledge\n-------------------------\n\nAt its core, Django is simply a collection of libraries written in the Python\nprogramming language. To develop a site using Django, you write Python code\nthat uses these libraries. Learning Django, then, is a matter of learning how\nto program in Python and understanding how the Django libraries work.\n\nIf you have experience programming in Python, you should have no trouble diving\nin. By and large, the Django code doesn't perform a lot of \"magic\" (i.e.,\nprogramming trickery whose implementation is difficult to explain or\nunderstand). For you, learning Django will be a matter of learning Django's\nconventions and APIs.\n\nIf you don't have experience programming in Python, you're in for a treat.\nIt's easy to learn and a joy to use! Although this book doesn't include a full\nPython tutorial, it highlights Python features and functionality where\nappropriate, particularly when code doesn't immediately make sense. Still, we\nrecommend you read the official Python tutorial, available online at\nhttp://docs.python.org/tut/. We also recommend Mark Pilgrim's free book\n*Dive Into Python*, available at http://www.diveintopython.net/ and published in\nprint by Apress.\n\nRequired Django Version\n-----------------------\n\nThis book covers Django 1.4.\n\nDjango's developers maintain backwards compatibility as much as possible, but\noccasionally introduce some backwards incompatible changes.  The changes in each\nrelease are always covered in the release notes, which you can find here:\nhttps://docs.djangoproject.com/en/dev/releases/1.X\n\n\nGetting Help\n------------\n\nOne of the greatest benefits of Django is its kind and helpful user community.\nFor help with any aspect of Django -- from installation, to application design,\nto database design, to deployment -- feel free to ask questions online.\n\n* The django-users mailing list is where thousands of Django users hang out\n  to ask and answer questions. Sign up for free at http://www.djangoproject.com/r/django-users.\n\n* The Django IRC channel is where Django users hang out to chat and help\n  each other in real time. Join the fun by logging on to #django on the\n  Freenode IRC network.\n\nWhat's Next\n-----------\n\nIn :doc:`chapter02`, we'll get started with Django, covering installation and\ninitial setup.\n"
  },
  {
    "path": "Python/DjangoBook/chapter02.rst",
    "content": "==========================\nChapter 2: Getting Started\n==========================\n\nInstalling Django is a multi-step process, due to the multiple moving parts in\nmodern Web development environments. In this chapter, we'll walk you through\nhow to install the framework and its few dependencies.\n\nBecause Django is \"just\" Python code, it runs anywhere Python does -- including\non some cell phones! But this chapter just covers the common scenarios for\nDjango installations. We'll assume you're installing it either on a\ndesktop/laptop machine or a server.\n\nLater, in Chapter 12, we'll cover how to deploy Django to a production site.\n\nInstalling Python\n=================\n\nDjango itself is written purely in Python, so the first step in installing the\nframework is to make sure you have Python installed.\n\nPython Versions\n---------------\n\nThe core Django framework (version 1.4+) works with any Python version from 2.5\nto 2.7, inclusive. Django's optional GIS (Geographic Information Systems)\nsupport requires Python 2.5 to 2.7.\n\nIf you're not sure which version of Python to install and you have complete\nfreedom over the decision, pick the latest one in the 2.x series: version 2.7.\nAlthough Django works equally well with any version from 2.5 to 2.7, the later\nversions of Python have performance improvements and additional language\nfeatures you might like to use in your applications. Plus, certain third-party\nDjango add-ons that you might want to use might require a version newer than\nPython 2.5, so using a later version of Python keeps your options open.\n\n.. admonition:: Django and Python 3.0\n\n    At the time of writing, Python 3.0 had been released, but Django\n    only supported it experimentally. Python 3.0 introduced a\n    substantial number of backwards-incompatible changes to the\n    language itself, and, as a result, many major Python libraries and\n    frameworks, including Django, had not yet caught up.\n\n    Django 1.5 will support Python 2.6, 2.7, and 3.2.  However,\n    support for Python 3.2 is considered a \"preview\", which means the\n    Django developers are not yet confident enough to promise\n    stability in production.  For that, they suggest you wait until\n    Django 1.6.\n\nInstallation\n------------\n\nIf you're on Linux or Mac OS X, you probably have Python already installed.\nType ``python`` at a command prompt (or in Applications/Utilities/Terminal, in\nOS X). If you see something like this, then Python is installed::\n\n    Python 2.7.3rc2 (default, Apr 22 2012, 22:30:17)\n    [GCC 4.6.3] on linux2\n    Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n    >>>\n\nOtherwise, you'll need to download and install Python. It's fast and easy, and\ndetailed instructions are available at http://www.python.org/download/\n\nInstalling Django\n=================\n\nAt any given time, two distinct versions of Django are available to you: the\nlatest official release and the bleeding-edge development version. The version you\ndecide to install depends on your priorities. Do you want a stable and tested\nversion of Django, or do you want a version containing the latest features,\nperhaps so you can contribute to Django itself, at the expense of stability?\n\nWe'd recommend sticking with an official release, but it's important to know\nthat the development version exists, because you'll find it mentioned\nin the documentation and by members of the community.\n\nInstalling an Official Release\n------------------------------\n\nOfficial releases have a version number, such as 1.4.2, 1.4.1 or 1.4, and the latest\none is always available at http://www.djangoproject.com/download/.\n\nIf you're on a Linux distribution that includes a package of Django, it's a\ngood idea to use the distributor's version. That way, you'll get security\nupdates along with the rest of your system packages.\n\nIf you don't have access to a prepackaged version, you can download and install\nthe framework manually. To do so, first download the tarball, which will be\nnamed something like ``Django-1.4.2.tar.gz``. (It doesn't matter which\nlocal directory you download this file into; the installation process will put\nDjango's files in the right place.) Then, unzip it and run ``setup.py install``,\nas you do with most Python libraries.\n\nHere's how that process looks on Unix systems:\n\n#. ``tar xzvf Django-1.4.2.tar.gz``\n#. ``cd Django-*``\n#. ``sudo python setup.py install``\n\nOn Windows, we recommend using 7-Zip (http://www.djangoproject.com/r/7zip/)\nto unzip ``.tar.gz`` files. Once you've unzipped the file, start up a DOS\nshell (the \"Command Prompt\") with administrator privileges and run the\nfollowing command from within the directory whose name starts with ``Django-``::\n\n    python setup.py install\n\nIn case you're curious: Django's files will be installed into your Python\ninstallation's ``site-packages`` directory -- a directory where Python looks\nfor third-party libraries. Usually it's in a place like\n``/usr/lib/python2.7/site-packages``.\n\nInstalling the \"Development\" Version\n------------------------------------\n\nDjango uses Git (http://git-scm.com) for its source control. The latest and\ngreatest Django development version available from Django's official Git\nrepository (https://github.com/django/django). You should consider installing\nthis version if you want to work on the bleeding edge, or if you want to\ncontribute code to Django itself.\n\nGit is a free, open source distributed revision-control system, and the Django\nteam uses it to manage changes to the Django codebase. You can download and\ninstall Git from http://git-scm.com/download but it is easier to install with\nyour operating system's package manager. You can use Git to grab the very latest\nDjango source code and, at any given time, you can update your local version of\nthe Django code to get the latest changes and improvements made by Django\ndevelopers.\n\nWhen using the development version, keep in mind there's no guarantee things\nwon't be broken at any given moment. With that said, though, some members of the\nDjango team run production sites on the development version, so they have an\nincentive to keep it stable.\n\nTo grab the latest Django, follow these steps:\n\n#. Make sure you have Git installed. You can get the\n   software free from http://git-scm.com/, and you can find\n   excellent documentation at http://git-scm.com/documentation.\n\n#. Clone the repository using the command ``git clone https://github.com/django/django djmaster``\n\n#. Locate your Python installation's ``site-packages`` directory. Usually\n   it's in a place like ``/usr/lib/python2.7/site-packages``. If you have\n   no idea, type this command from a command prompt::\n\n       python -c 'import sys, pprint; pprint.pprint(sys.path)'\n\n   The resulting output should include your ``site-packages`` directory.\n\n#. Within the ``site-packages`` directory, create a file called\n   ``djmaster.pth`` and edit it to contain the full path to your ``djmaster``\n   directory to it. For example, the file could just contain this line::\n\n       /path/to/djmaster\n\n#. Place ``djmaster/django/bin`` on your system PATH. This directory\n   includes management utilities such as ``django-admin.py``.\n\n.. admonition:: Tip:\n\n    If ``.pth`` files are new to you, you can learn more about them at\n    http://www.djangoproject.com/r/python/site-module/.\n\nAfter downloading from Git and following the preceding steps, there's no\nneed to run ``python setup.py install``-- you've just done the work by hand!\n\nBecause the Django code changes often with bug fixes and feature additions,\nyou'll probably want to update it every once in a while. To update the code,\njust run the command ``git pull origin master`` from within the ``djmaster``\ndirectory. When you run that command, Git will contact\nhttps://github.com/django/django, determine whether any of Django's code has\nchanged, and update your local version of the code with any changes that have\nbeen made since you last updated. It's quite slick.\n\nFinally, if you use Django development version, you should know how to figure\nout which version of Django you're running. Knowing your version number is\nimportant if you ever need to reach out to the community for help, or if you\nsubmit improvements to the framework. In these cases, you should tell people the\nrevision, also known as a \"commit,\" that you're using. To find out your current\ncommit, type \"git log -1\" from within the ``django`` directory, and look for the\nidentifier after \"commit\". This number changes each time Django is changed,\nwhether through a bug fix, feature addition, documentation improvement or\nanything else.\n\nTesting the Django installation\n===============================\n\nFor some post-installation positive feedback, take a moment to test whether the\ninstallation worked. In a command shell, change into another directory (e.g.,\n*not* the directory that contains the ``django`` directory) and start the\nPython interactive interpreter by typing ``python``. If the installation was\nsuccessful, you should be able to import the module ``django``:\n\n    >>> import django\n    >>> django.VERSION\n    (1, 4, 2, 'final', 0)\n\n.. admonition:: Interactive Interpreter Examples\n\n    The Python interactive interpreter is a command-line program that lets you\n    write a Python program interactively. To start it, run the command\n    ``python`` at the command line.\n\n    Throughout this book, we feature example Python interactive interpreter\n    sessions. You can recognize these examples by the triple\n    greater-than signs (``>>>``), which designate the interpreter's prompt. If\n    you're copying examples from this book, don't copy those greater-than signs.\n\n    Multiline statements in the interactive interpreter are padded with three\n    dots (``...``). For example::\n\n        >>> print \"\"\"This is a\n        ... string that spans\n        ... three lines.\"\"\"\n        This is a\n        string that spans\n        three lines.\n        >>> def my_function(value):\n        ...     print value\n        >>> my_function('hello')\n        hello\n\n    Those three dots at the start of the additional lines are inserted by the\n    Python shell -- they're not part of our input. We include them here to be\n    faithful to the actual output of the interpreter. If you copy our examples\n    to follow along, don't copy those dots.\n\nSetting Up a Database\n=====================\n\nAt this point, you could very well begin writing a Web application with Django,\nbecause Django's only hard-and-fast prerequisite is a working Python\ninstallation. However, odds are you'll be developing a *database-driven* Web\nsite, in which case you'll need to configure a database server.\n\nIf you just want to start playing with Django, skip ahead to the\n\"Starting a Project\" section -- but keep in mind that all the examples in this\nbook assume you have a working database set up.\n\nDjango supports four database engines:\n\n* PostgreSQL (http://www.postgresql.org/)\n* SQLite 3 (http://www.sqlite.org/)\n* MySQL (http://www.mysql.com/)\n* Oracle (http://www.oracle.com/)\n\nFor the most part, all the engines here work equally well with the core Django\nframework. (A notable exception is Django's optional GIS support, which is much\nmore powerful with PostgreSQL than with other databases.) If you're not tied to\nany legacy system and have the freedom to choose a database backend, we\nrecommend PostgreSQL, which achieves a fine balance between cost, features,\nspeed and stability.\n\nSetting up the database is a two-step process:\n\n* First, you'll need to install and configure the database server itself.\n  This process is beyond the scope of this book, but each of the four\n  database backends has rich documentation on its Web site. (If you're on\n  a shared hosting provider, odds are that they've set this up for you\n  already.)\n\n* Second, you'll need to install the Python library for your particular\n  database backend. This is a third-party bit of code that allows Python to\n  interface with the database. We outline the specific, per-database\n  requirements in the following sections.\n\nIf you're just playing around with Django and don't want to install a database\nserver, consider using SQLite. SQLite is unique in the list of supported\ndatabases in that it doesn't require either of the above steps. It merely reads\nand writes its data to a single file on your filesystem, and Python versions 2.5\nand higher include built-in support for it.\n\nOn Windows, obtaining database driver binaries can be frustrating. If you're\neager to jump in, we recommend using Python 2.7 and its built-in support for\nSQLite.\n\nUsing Django with PostgreSQL\n----------------------------\n\nIf you're using PostgreSQL, you'll need to install either the ``psycopg`` or\n``psycopg2`` package from http://www.djangoproject.com/r/python-pgsql/. We\nrecommend ``psycopg2``, as it's newer, more actively developed and can be\neasier to install. Either way, take note of whether you're using version 1 or\n2; you'll need this information later.\n\nIf you're using PostgreSQL on Windows, you can find precompiled binaries of\n``psycopg`` at http://www.djangoproject.com/r/python-pgsql/windows/.\n\nIf you're on Linux, check whether your distribution's package-management\nsystem offers a package called \"python-psycopg2\", \"psycopg2-python\",\n\"python-postgresql\" or something similar.\n\nUsing Django with SQLite 3\n--------------------------\n\nYou're in luck: no database-specific installation is required, because Python\nships with SQLite support. Skip ahead to the next section.\n\nUsing Django with MySQL\n-----------------------\n\nDjango requires MySQL 4.0 or above. The 3.x versions don't support nested\nsubqueries and some other fairly standard SQL statements.\n\nYou'll also need to install the ``MySQLdb`` package from\nhttp://www.djangoproject.com/r/python-mysql/.\n\nIf you're on Linux, check whether your distribution's package-management system\noffers a package called \"python-mysql\", \"python-mysqldb\", \"mysql-python\" or\nsomething similar.\n\nUsing Django with Oracle\n------------------------\n\nDjango works with Oracle Database Server versions 9i and higher.\n\nIf you're using Oracle, you'll need to install the ``cx_Oracle`` library,\navailable at http://cx-oracle.sourceforge.net/. Use version 4.3.1 or higher, but\navoid version 5.0 due to a bug in that version of the driver.  Version 5.0.1\nresolved the bug, however, so you can choose a higher version as well.\n\nUsing Django Without a Database\n-------------------------------\n\nAs mentioned earlier, Django doesn't actually require a database. If you just\nwant to use it to serve dynamic pages that don't hit a database, that's\nperfectly fine.\n\nWith that said, bear in mind that some of the extra tools bundled with Django\n*do* require a database, so if you choose not to use a database, you'll miss\nout on those features. (We highlight these features throughout this book.)\n\nStarting a Project\n==================\n\nOnce you've installed Python, Django and (optionally) your database\nserver/library, you can take the first step in developing a Django application\nby creating a *project*.\n\nA project is a collection of settings for an instance of Django, including\ndatabase configuration, Django-specific options and application-specific\nsettings.\n\nIf this is your first time using Django, you'll have to take care of some\ninitial setup. Create a new directory to start working in, perhaps something\nlike ``/home/username/djcode/``.\n\n.. admonition:: Where Should This Directory Live?\n\n    If your background is in PHP, you're probably used to putting code under the\n    Web server's document root (in a place such as ``/var/www``). With Django,\n    you don't do that. It's not a good idea to put any of this Python code\n    within your Web server's document root, because in doing so you risk the\n    possibility that people will be able to view your raw source code over the\n    Web. That's not good.\n\n    Put your code in some directory **outside** of the document root.\n\nChange into the directory you created, and run the command\n``django-admin.py startproject mysite``. This will create a ``mysite``\ndirectory in your current directory.\n\n.. note::\n\n    ``django-admin.py`` should be on your system path if you installed Django\n    via its ``setup.py`` utility.\n\n    If you're using the development version, you'll find ``django-admin.py`` in\n    ``djmaster/django/bin``. Because you'll be using ``django-admin.py``\n    often, consider adding it to your system path. On Unix, you can do so by\n    symlinking from ``/usr/local/bin``, using a command such as ``sudo ln -s\n    /path/to/django/bin/django-admin.py /usr/local/bin/django-admin.py``. On\n    Windows, you'll need to update your ``PATH`` environment variable.\n\n    If you installed Django from a packaged version for your Linux\n    distribution, ``django-admin.py`` might be called ``django-admin`` instead.\n\nIf you see a \"permission denied\" message when running\n``django-admin.py startproject``, you'll need to change the file's permissions.\nTo do this, navigate to the directory where ``django-admin.py`` is installed\n(e.g., ``cd /usr/local/bin``) and run the command ``chmod +x django-admin.py``.\n\nThe ``startproject`` command creates a directory containing five files::\n\n    mysite/\n        manage.py\n        mysite/\n            __init__.py\n            settings.py\n            urls.py\n            wsgi.py\n\n.. note:: Doesn't match what you see?\n\n    The default project layout recently changed. If you're seeing a\n    \"flat\" layout (with no inner ``mysite/`` directory), you're probably using\n    a version of Django that doesn't match this tutorial version. This book covers\n    Django 1.4 and above, so if you're using an older version you probably want to\n    consult Django's official documentation.\n\n    The documentation for Django 1.X version is available at https://docs.djangoproject.com/en/1.X/.\n\nThese files are as follows:\n\n* ``mysite/``: The outer ``mysite/`` directory is just a container for your project.\n  Its name doesn't matter to Django; you can rename it to anything you like.\n\n* ``manage.py``: A command-line utility that lets you interact with this\n  Django project in various ways. Type ``python manage.py help`` to get a\n  feel for what it can do. You should never have to edit this file; it's\n  created in this directory purely for convenience.\n\n* ``mysite/mysite/``: The inner ``mysite/`` directory is the actual Python package\n  for your project. Its name is the Python package name you'll need to use to\n  import anything inside it (e.g. ``import mysite.settings``).\n\n* ``__init__.py``: A file required for Python to treat the ``mysite``\n  directory as a package (i.e., a group of Python modules). It's an empty\n  file, and generally you won't add anything to it.\n\n* ``settings.py``: Settings/configuration for this Django project. Take a\n  look at it to get an idea of the types of settings available, along with\n  their default values.\n\n* ``urls.py``: The URLs for this Django project. Think of this as the\n  \"table of contents\" of your Django-powered site.\n\n* ``wsgi.py``: An entry-point for WSGI-compatible webservers to serve your project.\n  See How to deploy with WSGI (https://docs.djangoproject.com/en/1.4/howto/deployment/wsgi/) for more details.\n\nDespite their small size, these files already constitute a working Django\napplication.\n\nRunning the Development Server\n------------------------------\n\nFor some more post-installation positive feedback, let's run the Django\ndevelopment server to see our barebones application in action.\n\nThe Django development server (also called the \"runserver\" after the command\nthat launches it) is a built-in, lightweight Web server you can use while\ndeveloping your site. It's included with Django so you can develop your site\nrapidly, without having to deal with configuring your production server (e.g.,\nApache) until you're ready for production. The development server watches your\ncode and automatically reloads it, making it easy for you to change your code\nwithout needing to restart anything.\n\nTo start the server, change into your project container directory (``cd mysite``),\nif you haven't already, and run this command::\n\n    python manage.py runserver\n\nYou'll see something like this::\n\n    Validating models...\n    0 errors found.\n\n    Django version 1.4.2, using settings 'mysite.settings'\n    Development server is running at http://127.0.0.1:8000/\n    Quit the server with CONTROL-C.\n\nThis launches the server locally, on port 8000, accessible only to connections\nfrom your own computer. Now that it's running, visit http://127.0.0.1:8000/\nwith your Web browser. You might see a different Django version depending on\nwhich version of Django you have installed. You'll see a \"Welcome to Django\" page shaded in a\npleasant pastel blue. It worked!\n\nOne final, important note about the development server is worth mentioning\nbefore proceeding. Although this server is convenient for development, resist\nthe temptation to use it in anything resembling a production environment. The\ndevelopment server can handle only a single request at a time reliably, and it\nhas not gone through a security audit of any sort. When the time comes to\nlaunch your site, see Chapter 12 for information on how to deploy Django.\n\n.. admonition:: Changing the Development Server's Host or Port\n\n    By default, the ``runserver`` command starts the development server on port\n    8000, listening only for local connections. If you want to change the\n    server's port, pass it as a command-line argument::\n\n        python manage.py runserver 8080\n\n    By specifying an IP address, you can tell the server to allow non-local\n    connections. This is especially helpful if you'd like to share a\n    development site with other members of your team. The IP address\n    ``0.0.0.0`` tells the server to listen on any network interface::\n\n        python manage.py runserver 0.0.0.0:8000\n\n    When you've done this, other computers on your local network will be able\n    to view your Django site by visiting your IP address in their Web browsers,\n    e.g., http://192.168.1.103:8000/ . (Note that you'll have to consult your\n    network settings to determine your IP address on the local network. Unix\n    users, try running \"ifconfig\" in a command prompt to get this information.\n    Windows users, try \"ipconfig\".)\n\nWhat's Next?\n============\n\nNow that you have everything installed and the development server running,\nyou're ready to :doc:`learn the basics <chapter03>` of serving Web pages with Django.\n"
  },
  {
    "path": "Python/DjangoBook/chapter03.rst",
    "content": "=============================\nChapter 3: Views and URLconfs\n=============================\n\nIn the previous chapter, we explained how to set up a Django project and run the\nDjango development server. In this chapter, you'll learn the basics of creating\ndynamic Web pages with Django.\n\nYour First Django-Powered Page: Hello World\n===========================================\n\nAs our first goal, let's create a Web page that outputs that famous example\nmessage: \"Hello world.\"\n\nIf you were publishing a simple \"Hello world\" Web page without a Web framework,\nyou'd simply type \"Hello world\" into a text file, call it ``hello.html``,\nand upload it to a directory on a Web server somewhere. Notice, in that\nprocess, you've specified two key pieces of information about that Web page:\nits contents (the string ``\"Hello world\"``) and its URL (\n``http://www.example.com/hello.html``, or maybe ``http://www.example.com/files/hello.html``\nif you put it in a subdirectory).\n\nWith Django, you specify those same two things, but in a different way. The\ncontents of the page are produced by a *view function*, and the URL is\nspecified in a *URLconf*. First, let's write our \"Hello world\" view function.\n\nYour First View\n---------------\n\nWithin the ``mysite`` directory that ``django-admin.py startproject`` made in\nthe last chapter, create an empty file called ``views.py``. This Python module\nwill contain our views for this chapter. Note that there's nothing special\nabout the name ``views.py`` -- Django doesn't care what the file is called, as\nyou'll see in a bit -- but it's a good idea to call it ``views.py`` as a\nconvention, for the benefit of other developers reading your code.\n\nOur \"Hello world\" view is simple. Here's the entire function, plus import\nstatements, which you should type into the ``views.py`` file::\n\n    from django.http import HttpResponse\n\n    def hello(request):\n        return HttpResponse(\"Hello world\")\n\nLet's step through this code one line at a time:\n\n* First, we import the class ``HttpResponse``, which lives in the\n  ``django.http`` module. We need to import this class because it's used\n  later in our code.\n\n* Next, we define a function called ``hello`` -- the view function.\n\n  Each view function takes at least one parameter, called ``request`` by\n  convention. This is an object that contains information about the\n  current Web request that has triggered this view, and it's an instance of\n  the class ``django.http.HttpRequest``. In this example, we don't do\n  anything with ``request``, but it must be the first parameter of the view\n  nonetheless.\n\n  Note that the name of the view function doesn't matter; it doesn't have\n  to be named in a certain way in order for Django to recognize it. We're\n  calling it ``hello`` here, because that name clearly indicates the gist\n  of the view, but it could just as well be named\n  ``hello_wonderful_beautiful_world``, or something equally revolting. The\n  next section, \"Your First URLconf\", will shed light on how Django finds\n  this function.\n\n* The function is a simple one-liner: it merely returns an ``HttpResponse``\n  object that has been instantiated with the text ``\"Hello world\"``.\n\nThe main lesson here is this: a view is just a Python function that takes an\n``HttpRequest`` as its first parameter and returns an instance of\n``HttpResponse``. In order for a Python function to be a Django view, it must\ndo these two things. (There are exceptions, but we'll get to those later.)\n\nYour First URLconf\n------------------\n\nIf, at this point, you ran ``python manage.py runserver`` again, you'd still\nsee the \"Welcome to Django\" message, with no trace of our \"Hello world\" view\nanywhere. That's because our ``mysite`` project doesn't yet know about the\n``hello`` view; we need to tell Django explicitly that we're activating this\nview at a particular URL. (Continuing our previous analogy of publishing\nstatic HTML files, at this point we've created the HTML file but haven't\nuploaded it to a directory on the server yet.) To hook a view function to a\nparticular URL with Django, use a URLconf.\n\nA *URLconf* is like a table of contents for your Django-powered Web site.\nBasically, it's a mapping between URLs and the view functions that\nshould be called for those URLs. It's how you tell Django, \"For this\nURL, call this code, and for that URL, call that code.\" For example, \"When\nsomebody visits the URL ``/foo/``, call the view function ``foo_view()``, which\nlives in the Python module ``views.py``.\"\n\nWhen you executed ``django-admin.py startproject`` in the previous chapter, the\nscript created a URLconf for you automatically: the file ``urls.py``. By\ndefault, it looks something like this::\n\n    from django.conf.urls import patterns, include, url\n\n    # Uncomment the next two lines to enable the admin:\n    # from django.contrib import admin\n    # admin.autodiscover()\n\n    urlpatterns = patterns('',\n        # Examples:\n        # url(r'^$', 'mysite.views.home', name='home'),\n        # url(r'^mysite/', include('mysite.foo.urls')),\n\n        # Uncomment the admin/doc line below to enable admin documentation:\n        # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),\n\n        # Uncomment the next line to enable the admin:\n        # url(r'^admin/', include(admin.site.urls)),\n    )\n\nThis default URLconf includes some commonly used Django features commented out,\nso that activating those features is as easy as uncommenting the appropriate\nlines. If we ignore the commented-out code, here's the essence of a URLconf::\n\n    from django.conf.urls.defaults import patterns, include, url\n\n    urlpatterns = patterns('',\n    )\n\nLet's step through this code one line at a time:\n\n* The first line imports three functions from the ``django.conf.urls.defaults``\n  module, which is Django's URLconf infrastructure: ``patterns``, ``include``,\n  and ``urls``.\n\n* The second line calls the function ``patterns`` and saves the result\n  into a variable called ``urlpatterns``. The ``patterns`` function gets\n  passed only a single argument -- the empty string. (The string can be\n  used to supply a common prefix for view functions, which we'll cover in\n  :doc:`chapter08`.)\n\nThe main thing to note here is the variable ``urlpatterns``, which Django\nexpects to find in your URLconf module. This variable defines the mapping\nbetween URLs and the code that handles those URLs. By default, as we can see,\nthe URLconf is empty -- your Django application is a blank slate. (As a side\nnote, that's how Django knew to show you the \"Welcome to Django\" page in the\nlast chapter. If your URLconf is empty, Django assumes you just started a new\nproject and, hence, displays that message.)\n\nTo add a URL and view to the URLconf, just add a mapping between a URL\npattern and the view function. Here's how to hook in our ``hello`` view::\n\n    from django.conf.urls.defaults import patterns, include, url\n    from mysite.views import hello\n\n    urlpatterns = patterns('',\n        url(r'^hello/$', hello),\n    )\n\n(Note that we've removed the commented-out code for brevity. You can choose\nto leave those lines in, if you'd like.)\n\nWe made two changes here:\n\n* First, we imported the ``hello`` view from its module --\n  ``mysite/views.py``, which translates into ``mysite.views`` in Python\n  import syntax. (This assumes ``mysite/views.py`` is on your Python path;\n  see the sidebar for details.)\n\n* Next, we added the line ``url(r'^hello/$', hello),`` to ``urlpatterns``. This\n  line is referred to as a *URLpattern*. The ``url()`` function tells Django how\n  to handle the url that you are configuring. The first argument is a\n  pattern-matching string (a regular expression; more on this in a bit) and the\n  second argument is the view function to use for that pattern. ``url()`` can\n  take other optional arguments as well, which we'll cover in more depth in\n  :doc:`chapter08`.\n\n.. note::\n\n  One more important detail we've introduced here is that ``r`` character in\n  front of the regular expression string. This tells Python that the string is a\n  \"raw string\" -- its contents should not interpret backslashes. In normal\n  Python strings, backslashes are used for escaping special characters -- such\n  as in the string ``'\\n'``, which is a one-character string containing a\n  newline. When you add the ``r`` to make it a raw string, Python does not apply\n  its backslash escaping -- so, ``r'\\n'`` is a two-character string containing a\n  literal backslash and a lowercase \"n\". There's a natural collision between\n  Python's usage of backslashes and the backslashes that are found in regular\n  expressions, so it's strongly suggested that you use raw strings any time\n  you're defining a regular expression in Python. All of the URLpatterns in this\n  book will be raw strings.\n\nIn a nutshell, we just told Django that any request to the URL ``/hello/`` should\nbe handled by the ``hello`` view function.\n\n.. admonition:: Your Python Path\n\n    Your *Python path* is the list of directories on your system where Python\n    looks when you use the Python ``import`` statement.\n\n    For example, let's say your Python path is set to ``['',\n    '/usr/lib/python2.7/site-packages', '/home/username/djcode']``. If you\n    execute the Python statement ``from foo import bar``, Python will look for\n    a module called ``foo.py`` in the current directory. (The first entry in the\n    Python path, an empty string, means \"the current directory.\") If that file\n    doesn't exist, Python will look for the file\n    ``/usr/lib/python2.7/site-packages/foo.py``. If that file doesn't exist, it\n    will try ``/home/username/djcode/foo.py``. Finally, if *that* file doesn't\n    exist, it will raise ``ImportError``.\n\n    If you're interested in seeing the value of your Python path, start the\n    Python interactive interpreter and type this::\n\n        >>> import sys\n        >>> print sys.path\n\n    Generally you don't have to worry about setting your Python path -- Python\n    and Django take care of things for you automatically behind the scenes.\n    (Setting the Python path is one of the things that the ``manage.py`` script\n    does.)\n\nIt's worth discussing the syntax of this URLpattern, as it may not be\nimmediately obvious. Although we want to match the URL ``/hello/``, the pattern\nlooks a bit different than that. Here's why:\n\n* Django removes the slash from the front of every incoming URL before it\n  checks the URLpatterns. This means that our URLpattern doesn't include\n  the leading slash in ``/hello/``. (At first, this may seem unintuitive,\n  but this requirement simplifies things -- such as the inclusion of\n  URLconfs within other URLconfs, which we'll cover in Chapter 8.)\n\n* The pattern includes a caret (``^``) and a dollar sign (``$``). These are\n  regular expression characters that have a special meaning: the caret\n  means \"require that the pattern matches the start of the string,\" and the\n  dollar sign means \"require that the pattern matches the end of the\n  string.\"\n\n  This concept is best explained by example. If we had instead used the\n  pattern ``'^hello/'`` (without a dollar sign at the end), then *any* URL\n  starting with ``/hello/`` would match, such as ``/hello/foo`` and\n  ``/hello/bar``, not just ``/hello/``. Similarly, if we had left off the\n  initial caret character (i.e., ``'hello/$'``), Django would match *any*\n  URL that ends with ``hello/``, such as ``/foo/bar/hello/``. If we had\n  simply used ``hello/``, without a caret *or* dollar sign, then any URL\n  containing ``hello/`` would match, such as ``/foo/hello/bar``. Thus, we\n  use both the caret and dollar sign to ensure that only the URL\n  ``/hello/`` matches -- nothing more, nothing less.\n\n  Most of your URLpatterns will start with carets and end with dollar\n  signs, but it's nice to have the flexibility to perform more\n  sophisticated matches.\n\n  You may be wondering what happens if someone requests the URL ``/hello``\n  (that is, *without* a trailing slash). Because our URLpattern requires a\n  trailing slash, that URL would *not* match. However, by default, any\n  request to a URL that *doesn't* match a URLpattern and *doesn't* end with\n  a slash will be redirected to the same URL with a trailing slash. (This\n  is regulated by the ``APPEND_SLASH`` Django setting, which is covered in\n  Appendix D.)\n\n  If you're the type of person who likes all URLs to end with slashes\n  (which is the preference of Django's developers), all you'll need to do\n  is add a trailing slash to each URLpattern and leave ``APPEND_SLASH`` set\n  to ``True``. If you prefer your URLs *not* to have trailing slashes, or\n  if you want to decide it on a per-URL basis, set ``APPEND_SLASH`` to\n  ``False`` and put trailing slashes in your URLpatterns as you see fit.\n\nThe other thing to note about this URLconf is that we've passed the\n``hello`` view function as an object without calling the function. This is a\nkey feature of Python (and other dynamic languages): functions are first-class\nobjects, which means you can pass them around just like any other variables.\nCool stuff, eh?\n\nTo test our changes to the URLconf, start the Django development server, as you\ndid in Chapter 2, by running the command ``python manage.py runserver``. (If you\nleft it running, that's fine, too. The development server automatically detects\nchanges to your Python code and reloads as necessary, so you don't have to\nrestart the server between changes.) The server is running at the address\n``http://127.0.0.1:8000/``, so open up a Web browser and go to\n``http://127.0.0.1:8000/hello/``. You should see the text \"Hello world\" -- the\noutput of your Django view.\n\nHooray! You've made your first Django-powered Web page.\n\n.. admonition:: Regular Expressions\n\n    *Regular expressions* (or *regexes*) are a compact way of specifying\n    patterns in text. While Django URLconfs allow arbitrary regexes for\n    powerful URL matching, you'll probably only use a few regex symbols in\n    practice. Here's a selection of common symbols:\n\n    ============  ==========================================================\n    Symbol        Matches\n    ============  ==========================================================\n    ``.`` (dot)   Any single character\n\n    ``\\d``        Any single digit\n\n    ``[A-Z]``     Any character between ``A`` and ``Z`` (uppercase)\n\n    ``[a-z]``     Any character between ``a`` and ``z`` (lowercase)\n\n    ``[A-Za-z]``  Any character between ``a`` and ``z`` (case-insensitive)\n\n    ``+``         One or more of the previous expression (e.g., ``\\d+``\n                  matches one or more digits)\n\n    ``[^/]+``     One or more characters until (and not including) a\n                  forward slash\n\n    ``?``         Zero or one of the previous expression (e.g., ``\\d?``\n                  matches zero or one digits)\n\n    ``*``         Zero or more of the previous expression (e.g., ``\\d*``\n                  matches zero, one or more than one digit)\n\n    ``{1,3}``     Between one and three (inclusive) of the previous\n                  expression (e.g., ``\\d{1,3}`` matches one, two or three\n                  digits)\n    ============  ==========================================================\n\n    For more on regular expressions, see http://www.djangoproject.com/r/python/re-module/.\n\nA Quick Note About 404 Errors\n-----------------------------\n\nAt this point, our URLconf defines only a single URLpattern: the one that\nhandles requests to the URL ``/hello/``. What happens when you request a\ndifferent URL?\n\nTo find out, try running the Django development server and visiting a page such\nas ``http://127.0.0.1:8000/goodbye/`` or\n``http://127.0.0.1:8000/hello/subdirectory/``, or even ``http://127.0.0.1:8000/``\n(the site \"root\"). You should see a \"Page not found\" message (see Figure 3-1).\nDjango displays this message because you requested a URL that's not defined in\nyour URLconf.\n\n.. figure:: graphics/chapter03/404.png\n   :alt: Screenshot of Django's 404 page.\n\n   Figure 3-1. Django's 404 page\n\nThe utility of this page goes beyond the basic 404 error message. It also tells\nyou precisely which URLconf Django used and every pattern in that URLconf. From\nthat information, you should be able to tell why the requested URL threw a 404.\n\nNaturally, this is sensitive information intended only for you, the Web\ndeveloper. If this were a production site deployed live on the Internet, you\nwouldn't want to expose that information to the public. For that reason, this\n\"Page not found\" page is only displayed if your Django project is in *debug\nmode*. We'll explain how to deactivate debug mode later. For now, just know\nthat every Django project is in debug mode when you first create it, and if the\nproject is not in debug mode, Django outputs a different 404 response.\n\nA Quick Note About The Site Root\n--------------------------------\n\nAs explained in the last section, you'll see a 404 error message if you view\nthe site root -- ``http://127.0.0.1:8000/``. Django doesn't add magically\nanything to the site root; that URL is not special-cased in any way. It's up to\nyou to assign it to a URLpattern, just like every other entry in your URLconf.\n\nThe URLpattern to match the site root is a bit unintuitive, though, so it's\nworth mentioning. When you're ready to implement a view for the site root, use\nthe URLpattern ``'^$'``, which matches an empty string. For example::\n\n    from mysite.views import hello, my_homepage_view\n\n    urlpatterns = patterns('',\n        url(r'^$', my_homepage_view),\n        # ...\n    )\n\nHow Django Processes a Request\n==============================\n\nBefore continuing to our second view function, let's pause to learn a little\nmore about how Django works. Specifically, when you view your \"Hello world\"\nmessage by visiting ``http://127.0.0.1:8000/hello/`` in your Web browser, what\ndoes Django do behind the scenes?\n\nIt all starts with the *settings file*. When you run ``python manage.py\nrunserver``, the script looks for a file called ``settings.py`` in the inner\n``mysite`` directory. This file contains all sorts of configuration for this\nparticular Django project, all in uppercase: ``TEMPLATE_DIRS``, ``DATABASES``,\netc. The most important setting is called ``ROOT_URLCONF``. ``ROOT_URLCONF``\ntells Django which Python module should be used as the URLconf for this Web\nsite.\n\nRemember when ``django-admin.py startproject`` created the files\n``settings.py`` and ``urls.py``? The autogenerated ``settings.py`` contains a\n``ROOT_URLCONF`` setting that points to the autogenerated ``urls.py``. Open the\n``settings.py`` file and see for yourself; it should look like this::\n\n    ROOT_URLCONF = 'mysite.urls'\n\nThis corresponds to the file ``mysite/urls.py``.\n\nWhen a request comes in for a particular URL -- say, a request for ``/hello/``\n-- Django loads the URLconf pointed to by the ``ROOT_URLCONF`` setting. Then it\nchecks each of the URLpatterns in that URLconf, in order, comparing the\nrequested URL with the patterns one at a time, until it finds one that matches.\nWhen it finds one that matches, it calls the view function associated with that\npattern, passing it an ``HttpRequest`` object as the first parameter. (We'll\ncover the specifics of ``HttpRequest`` later.)\n\nAs we saw in our first view example, a view function must return an\n``HttpResponse``. Once it does this, Django does the rest, converting the\nPython object to a proper Web response with the appropriate HTTP headers and\nbody (i.e., the content of the Web page).\n\nIn summary:\n\n1. A request comes in to ``/hello/``.\n2. Django determines the root URLconf by looking at the ``ROOT_URLCONF``\n   setting.\n3. Django looks at all of the URLpatterns in the URLconf for the first one\n   that matches ``/hello/``.\n4. If it finds a match, it calls the associated view function.\n5. The view function returns an ``HttpResponse``.\n6. Django converts the ``HttpResponse`` to the proper HTTP response, which\n   results in a Web page.\n\nYou now know the basics of how to make Django-powered pages. It's quite simple,\nreally -- just write view functions and map them to URLs via URLconfs.\n\nYour Second View: Dynamic Content\n=================================\n\nOur \"Hello world\" view was instructive in demonstrating the basics of how\nDjango works, but it wasn't an example of a *dynamic* Web page, because the\ncontent of the page are always the same. Every time you view ``/hello/``,\nyou'll see the same thing; it might as well be a static HTML file.\n\nFor our second view, let's create something more dynamic -- a Web page that\ndisplays the current date and time. This is a nice, simple next step, because\nit doesn't involve a database or any user input -- just the output of your\nserver's internal clock. It's only marginally more exciting than \"Hello world,\"\nbut it'll demonstrate a few new concepts.\n\nThis view needs to do two things: calculate the current date and time, and\nreturn an ``HttpResponse`` containing that value. If you have experience with\nPython, you know that Python includes a ``datetime`` module for calculating\ndates. Here's how to use it::\n\n    >>> import datetime\n    >>> now = datetime.datetime.now()\n    >>> now\n    datetime.datetime(2008, 12, 13, 14, 9, 39, 2731)\n    >>> print now\n    2008-12-13 14:09:39.002731\n\nThat's simple enough, and it has nothing to do with Django. It's just Python\ncode. (We want to emphasize that you should be aware of what code is \"just\nPython\" vs. code that is Django-specific. As you learn Django, we want you to\nbe able to apply your knowledge to other Python projects that don't necessarily\nuse Django.)\n\nTo make a Django view that displays the current date and time, then, we just\nneed to hook this ``datetime.datetime.now()`` statement into a view and return\nan ``HttpResponse``. Here's how that looks::\n\n    from django.http import HttpResponse\n    import datetime\n\n    def current_datetime(request):\n        now = datetime.datetime.now()\n        html = \"<html><body>It is now %s.</body></html>\" % now\n        return HttpResponse(html)\n\nAs with our ``hello`` view function, this should live in ``views.py``. Note\nthat we've hidden the ``hello`` function from this example for brevity, but for\nthe sake of completeness, here's what the entire ``views.py`` looks like::\n\n    from django.http import HttpResponse\n    import datetime\n\n    def hello(request):\n        return HttpResponse(\"Hello world\")\n\n    def current_datetime(request):\n        now = datetime.datetime.now()\n        html = \"<html><body>It is now %s.</body></html>\" % now\n        return HttpResponse(html)\n\n(From now on, we won't display previous code in code examples, except when\nnecessary. You should be able to tell from context which parts of an example\nare new vs. old.)\n\nLet's step through the changes we've made to ``views.py`` to accommodate\nthe ``current_datetime`` view.\n\n* We've added an ``import datetime`` to the top of the module, so we can\n  calculate dates.\n\n* The new ``current_datetime`` function calculates the current date and\n  time, as a ``datetime.datetime`` object, and stores that as the local\n  variable ``now``.\n\n* The second line of code within the view constructs an HTML response using\n  Python's \"format-string\" capability. The ``%s`` within the string is a\n  placeholder, and the percent sign after the string means \"Replace the\n  ``%s`` in the preceding string with the value of the variable ``now``.\"\n  The ``now`` variable is technically a ``datetime.datetime`` object, not\n  a string, but the ``%s`` format character converts it to its string\n  representation, which is something like ``\"2008-12-13 14:09:39.002731\"``.\n  This will result in an HTML string such as\n  ``\"<html><body>It is now 2008-12-13 14:09:39.002731.</body></html>\"``.\n\n  (Yes, our HTML is invalid, but we're trying to keep the example simple\n  and short.)\n\n* Finally, the view returns an ``HttpResponse`` object that contains the\n  generated response -- just as we did in ``hello``.\n\nAfter adding that to ``views.py``, add the URLpattern to ``urls.py`` to tell\nDjango which URL should handle this view. Something like ``/time/`` would make\nsense::\n\n    from django.conf.urls.defaults import patterns, include, url\n    from mysite.views import hello, current_datetime\n\n    urlpatterns = patterns('',\n        url(r'^hello/$', hello),\n        url(r'^time/$', current_datetime),\n    )\n\nWe've made two changes here. First, we imported the ``current_datetime``\nfunction at the top. Second, and more importantly, we added a URLpattern\nmapping the URL ``/time/`` to that new view. Getting the hang of this?\n\nWith the view written and URLconf updated, fire up the ``runserver`` and visit\n``http://127.0.0.1:8000/time/`` in your browser. You should see the current\ndate and time.\n\n.. admonition:: Django's Time Zone\n\n    Depending on your computer, the date and time may be a few hours off.\n    That's because Django is time zone-aware and defaults to the\n    ``America/Chicago`` time zone. (It has to default to *something*, and that's\n    the time zone where the original developers live.) If you live elsewhere,\n    you'll want to change it in ``settings.py``. See the comment in that file\n    for a link to an up-to-date list of worldwide time zone options.\n\nURLconfs and Loose Coupling\n===========================\n\nNow's a good time to highlight a key philosophy behind URLconfs and behind\nDjango in general: the principle of *loose coupling*. Simply put, loose coupling\nis a software-development approach that values the importance of making pieces\ninterchangeable. If two pieces of code are loosely coupled, then changes made to\none of the pieces will have little or no effect on the other.\n\nDjango's URLconfs are a good example of this principle in practice. In a Django\nweb application, the URL definitions and the view functions they call are\nloosely coupled; that is, the decision of what the URL should be for a given\nfunction, and the implementation of the function itself, reside in two separate\nplaces. This lets you switch out one piece without affecting the other.\n\nFor example, consider our ``current_datetime`` view. If we wanted to change the\nURL for the application -- say, to move it from ``/time/`` to\n``/current-time/`` -- we could make a quick change to the URLconf, without\nhaving to worry about the view itself. Similarly, if we wanted to change the\nview function -- altering its logic somehow -- we could do that without\naffecting the URL to which the function is bound.\n\nFurthermore, if we wanted to expose the current-date functionality at\n*several* URLs, we could easily take care of that by editing the URLconf,\nwithout having to touch the view code. In this example, our\n``current_datetime`` is available at two URLs. It's a contrived example, but\nthis technique can come in handy::\n\n    urlpatterns = patterns('',\n        url(r'^hello/$', hello),\n        url(r'^time/$', current_datetime),\n        url(r'^another-time-page/$', current_datetime),\n    )\n\nURLconfs and views are loose coupling in action. We'll continue to point out\nexamples of this important philosophy throughout this book.\n\nYour Third View: Dynamic URLs\n=============================\n\nIn our ``current_datetime`` view, the contents of the page -- the current\ndate/time -- were dynamic, but the URL (``/time/``) was static. In most dynamic\nWeb applications, though, a URL contains parameters that influence the output\nof the page. For example, an online bookstore might give each book its own URL,\nlike ``/books/243/`` and ``/books/81196/``.\n\nLet's create a third view that displays the current date and time offset by a\ncertain number of hours. The goal is to craft a site in such a way that the page\n``/time/plus/1/`` displays the date/time one hour into the future, the page\n``/time/plus/2/`` displays the date/time two hours into the future, the page\n``/time/plus/3/`` displays the date/time three hours into the future, and so\non.\n\nA novice might think to code a separate view function for each hour offset,\nwhich might result in a URLconf like this::\n\n    urlpatterns = patterns('',\n        url(r'^time/$', current_datetime),\n        url(r'^time/plus/1/$', one_hour_ahead),\n        url(r'^time/plus/2/$', two_hours_ahead),\n        url(r'^time/plus/3/$', three_hours_ahead),\n        url(r'^time/plus/4/$', four_hours_ahead),\n    )\n\nClearly, this line of thought is flawed. Not only would this result in redundant\nview functions, but also the application is fundamentally limited to supporting\nonly the predefined hour ranges -- one, two, three or four hours. If we decided\nto create a page that displayed the time *five* hours into the future, we'd\nhave to create a separate view and URLconf line for that, furthering the\nduplication. We need to do some abstraction here.\n\n.. admonition:: A Word About Pretty URLs\n\n    If you're experienced in another Web development platform, such as PHP or\n    Java, you may be thinking, \"Hey, let's use a query string parameter!\" --\n    something like ``/time/plus?hours=3``, in which the hours would be\n    designated by the ``hours`` parameter in the URL's query string (the part\n    after the ``?``).\n\n    You *can* do that with Django (and we'll tell you how in Chapter 7), but\n    one of Django's core philosophies is that URLs should be beautiful. The URL\n    ``/time/plus/3/`` is far cleaner, simpler, more readable, easier to recite\n    to somebody aloud and . . . just plain prettier than its query string\n    counterpart. Pretty URLs are a characteristic of a quality Web application.\n\n    Django's URLconf system encourages pretty URLs by making it easier to use\n    pretty URLs than *not* to.\n\nHow, then do we design our application to handle arbitrary hour offsets? The\nkey is to use *wildcard URLpatterns*. As we mentioned previously, a URLpattern\nis a regular expression; hence, we can use the regular expression pattern\n``\\d+`` to match one or more digits::\n\n    urlpatterns = patterns('',\n        # ...\n        url(r'^time/plus/\\d+/$', hours_ahead),\n        # ...\n    )\n\n(We're using the ``# ...`` to imply there might be other URLpatterns that we\ntrimmed from this example.)\n\nThis new URLpattern will match any URL such as ``/time/plus/2/``,\n``/time/plus/25/``, or even ``/time/plus/100000000000/``. Come to think of it,\nlet's limit it so that the maximum allowed offset is 99 hours. That means we\nwant to allow either one- or two-digit numbers -- and in regular expression\nsyntax, that translates into ``\\d{1,2}``::\n\n    url(r'^time/plus/\\d{1,2}/$', hours_ahead),\n\n.. note::\n\n    When building Web applications, it's always important to consider the most\n    outlandish data input possible, and decide whether or not the application\n    should support that input. We've curtailed the outlandishness here by\n    limiting the offset to 99 hours.\n\nNow that we've designated a wildcard for the URL, we need a way of passing that\nwildcard data to the view function, so that we can use a single view function\nfor any arbitrary hour offset. We do this by placing parentheses around the\ndata in the URLpattern that we want to save. In the case of our example, we\nwant to save whatever number was entered in the URL, so let's put parentheses\naround the ``\\d{1,2}``, like this::\n\n    url(r'^time/plus/(\\d{1,2})/$', hours_ahead),\n\nIf you're familiar with regular expressions, you'll be right at home here;\nwe're using parentheses to *capture* data from the matched text.\n\nThe final URLconf, including our previous two views, looks like this::\n\n    from django.conf.urls.defaults import *\n    from mysite.views import hello, current_datetime, hours_ahead\n\n    urlpatterns = patterns('',\n        url(r'^hello/$', hello),\n        url(r'^time/$', current_datetime),\n        url(r'^time/plus/(\\d{1,2})/$', hours_ahead),\n    )\n\nWith that taken care of, let's write the ``hours_ahead`` view.\n\n``hours_ahead`` is very similar to the ``current_datetime`` view we wrote\nearlier, with a key difference: it takes an extra argument, the number of hours\nof offset. Here's the view code::\n\n    from django.http import Http404, HttpResponse\n    import datetime\n\n    def hours_ahead(request, offset):\n        try:\n            offset = int(offset)\n        except ValueError:\n            raise Http404()\n        dt = datetime.datetime.now() + datetime.timedelta(hours=offset)\n        html = \"<html><body>In %s hour(s), it will be %s.</body></html>\" % (offset, dt)\n        return HttpResponse(html)\n\nLet's step through this code one line at a time:\n\n* The view function, ``hours_ahead``, takes *two* parameters: ``request``\n  and ``offset``.\n\n  * ``request`` is an ``HttpRequest`` object, just as in ``hello`` and\n    ``current_datetime``. We'll say it again: each view *always* takes an\n    ``HttpRequest`` object as its first parameter.\n\n  * ``offset`` is the string captured by the parentheses in the\n    URLpattern. For example, if the requested URL were ``/time/plus/3/``,\n    then ``offset`` would be the string ``'3'``. If the requested URL were\n    ``/time/plus/21/``, then ``offset`` would be the string ``'21'``. Note\n    that captured values will always be *strings*, not integers, even if\n    the string is composed of only digits, such as ``'21'``.\n\n    (Technically, captured values will always be *Unicode objects*, not\n    plain Python bytestrings, but don't worry about this distinction at\n    the moment.)\n\n    We decided to call the variable ``offset``, but you can call it\n    whatever you'd like, as long as it's a valid Python identifier. The\n    variable name doesn't matter; all that matters is that it's the second\n    argument to the function, after ``request``. (It's also possible to\n    use keyword, rather than positional, arguments in an URLconf. We cover\n    that in Chapter 8.)\n\n* The first thing we do within the function is call ``int()`` on ``offset``.\n  This converts the string value to an integer.\n\n  Note that Python will raise a ``ValueError`` exception if you call\n  ``int()`` on a value that cannot be converted to an integer, such as the\n  string ``'foo'``. In this example, if we encounter the ``ValueError``, we\n  raise the exception ``django.http.Http404``, which, as you can imagine,\n  results in a 404 \"Page not found\" error.\n\n  Astute readers will wonder: how could we ever reach the ``ValueError``\n  case, anyway, given that the regular expression in our URLpattern --\n  ``(\\d{1,2})`` -- captures only digits, and therefore ``offset`` will only\n  ever be a string composed of digits? The answer is, we won't, because\n  the URLpattern provides a modest but useful level of input validation,\n  *but* we still check for the ``ValueError`` in case this view function\n  ever gets called in some other way. It's good practice to implement view\n  functions such that they don't make any assumptions about their\n  parameters. Loose coupling, remember?\n\n* In the next line of the function, we calculate the current date/time and\n  add the appropriate number of hours. We've already seen\n  ``datetime.datetime.now()`` from the ``current_datetime`` view; the new\n  concept here is that you can perform date/time arithmetic by creating a\n  ``datetime.timedelta`` object and adding to a ``datetime.datetime``\n  object. Our result is stored in the variable ``dt``.\n\n  This line also shows why we called ``int()`` on ``offset`` -- the\n  ``datetime.timedelta`` function requires the ``hours`` parameter to be an\n  integer.\n\n* Next, we construct the HTML output of this view function, just as we did\n  in ``current_datetime``. A small difference in this line from the previous\n  line is that it uses Python's format-string capability with *two* values,\n  not just one. Hence, there are two ``%s`` symbols in the string and a\n  tuple of values to insert: ``(offset, dt)``.\n\n* Finally, we return an ``HttpResponse`` of the HTML. By now, this is old\n  hat.\n\nWith that view function and URLconf written, start the Django development server\n(if it's not already running), and visit ``http://127.0.0.1:8000/time/plus/3/``\nto verify it works. Then try ``http://127.0.0.1:8000/time/plus/5/``. Then\n``http://127.0.0.1:8000/time/plus/24/``. Finally, visit\n``http://127.0.0.1:8000/time/plus/100/`` to verify that the pattern in your\nURLconf only accepts one- or two-digit numbers; Django should display a \"Page\nnot found\" error in this case, just as we saw in the section \"A Quick Note\nAbout 404 Errors\" earlier. The URL ``http://127.0.0.1:8000/time/plus/`` (with\n*no* hour designation) should also throw a 404.\n\n.. admonition:: Coding Order\n\n    In this example, we wrote the URLpattern first and the view second, but in\n    the previous examples, we wrote the view first, then the URLpattern. Which\n    technique is better?\n\n    Well, every developer is different.\n\n    If you're a big-picture type of person, it may make the most sense to you\n    to write all of the URLpatterns for your application at the same time, at\n    the start of your project, and then code up the views. This has the\n    advantage of giving you a clear to-do list, and it essentially defines the\n    parameter requirements for the view functions you'll need to write.\n\n    If you're more of a bottom-up developer, you might prefer to write the\n    views first, and then anchor them to URLs afterward. That's OK, too.\n\n    In the end, it comes down to which technique fits your brain the best. Both\n    approaches are valid.\n\nDjango's Pretty Error Pages\n===========================\n\nTake a moment to admire the fine Web application we've made so far . . . now\nlet's break it! Let's deliberately introduce a Python error into our\n``views.py`` file by commenting out the ``offset = int(offset)`` lines in the\n``hours_ahead`` view::\n\n    def hours_ahead(request, offset):\n        # try:\n        #     offset = int(offset)\n        # except ValueError:\n        #     raise Http404()\n        dt = datetime.datetime.now() + datetime.timedelta(hours=offset)\n        html = \"<html><body>In %s hour(s), it will be %s.</body></html>\" % (offset, dt)\n        return HttpResponse(html)\n\nLoad up the development server and navigate to ``/time/plus/3/``. You'll see an\nerror page with a significant amount of information, including a ``TypeError``\nmessage displayed at the very top: ``\"unsupported type for timedelta hours\ncomponent: unicode\"``.\n\nWhat happened? Well, the ``datetime.timedelta`` function expects the ``hours``\nparameter to be an integer, and we commented out the bit of code that converted\n``offset`` to an integer. That caused ``datetime.timedelta`` to raise the\n``TypeError``. It's the typical kind of small bug that every programmer runs\ninto at some point.\n\nThe point of this example was to demonstrate Django's error pages. Take some\ntime to explore the error page and get to know the various bits of information\nit gives you.\n\nHere are some things to notice:\n\n* At the top of the page, you get the key information about the exception:\n  the type of exception, any parameters to the exception (the ``\"unsupported\n  type\"`` message in this case), the file in which the exception was raised,\n  and the offending line number.\n\n* Under the key exception information, the page displays the full Python\n  traceback for this exception. This is similar to the standard traceback\n  you get in Python's command-line interpreter, except it's more\n  interactive. For each level (\"frame\") in the stack, Django displays the\n  name of the file, the function/method name, the line number, and the\n  source code of that line.\n\n  Click the line of source code (in dark gray), and you'll see several\n  lines from before and after the erroneous line, to give you context.\n\n  Click \"Local vars\" under any frame in the stack to view a table of all\n  local variables and their values, in that frame, at the exact point in the\n  code at which the exception was raised. This debugging information can be\n  a great help.\n\n* Note the \"Switch to copy-and-paste view\" text under the \"Traceback\"\n  header. Click those words, and the traceback will switch to a alternate\n  version that can be easily copied and pasted. Use this when you want to\n  share your exception traceback with others to get technical support --\n  such as the kind folks in the Django IRC chat room or on the Django users\n  mailing list.\n\n  Underneath, the \"Share this traceback on a public Web site\" button will\n  do this work for you in just one click. Click it to post the traceback to\n  http://www.dpaste.com/, where you'll get a distinct URL that you can\n  share with other people.\n\n* Next, the \"Request information\" section includes a wealth of information\n  about the incoming Web request that spawned the error: GET and POST\n  information, cookie values, and meta information, such as CGI headers.\n  Appendix G has a complete reference of all the information a request\n  object contains.\n\n  Below the \"Request information\" section, the \"Settings\" section lists all\n  of the settings for this particular Django installation. (We've already\n  mentioned ``ROOT_URLCONF``, and we'll show you various Django settings\n  throughout the book. All the available settings are covered in detail in\n  Appendix D.)\n\nThe Django error page is capable of displaying more information in certain\nspecial cases, such as the case of template syntax errors. We'll get to those\nlater, when we discuss the Django template system. For now, uncomment the\n``offset = int(offset)`` lines to get the view function working properly again.\n\nAre you the type of programmer who likes to debug with the help of carefully\nplaced ``print`` statements? You can use the Django error page to do so -- just\nwithout the ``print`` statements. At any point in your view, temporarily insert\nan ``assert False`` to trigger the error page. Then, you can view the local\nvariables and state of the program. Here's an example, using the\n``hours_ahead`` view::\n\n    def hours_ahead(request, offset):\n        try:\n            offset = int(offset)\n        except ValueError:\n            raise Http404()\n        dt = datetime.datetime.now() + datetime.timedelta(hours=offset)\n        assert False\n        html = \"<html><body>In %s hour(s), it will be %s.</body></html>\" % (offset, dt)\n        return HttpResponse(html)\n\nFinally, it's obvious that much of this information is sensitive -- it exposes\nthe innards of your Python code and Django configuration -- and it would be\nfoolish to show this information on the public Internet. A malicious person\ncould use it to attempt to reverse-engineer your Web application and do nasty\nthings. For that reason, the Django error page is only displayed when your\nDjango project is in debug mode. We'll explain how to deactivate debug mode\nin Chapter 12. For now, just know that every Django project is in debug mode\nautomatically when you start it. (Sound familiar? The \"Page not found\" errors,\ndescribed earlier in this chapter, work the same way.)\n\nWhat's next?\n============\n\nSo far, we've been writing our view functions with HTML hard-coded directly\nin the Python code. We've done that to keep things simple while we demonstrated\ncore concepts, but in the real world, this is nearly always a bad idea.\n\nDjango ships with a simple yet powerful template engine that allows you to\nseparate the design of the page from the underlying code. We'll dive into\nDjango's template engine in the :doc:`next chapter <chapter04>`.\n"
  },
  {
    "path": "Python/DjangoBook/chapter04.rst",
    "content": "====================\nChapter 4: Templates\n====================\n\nIn the previous chapter, you may have noticed something peculiar in how we\nreturned the text in our example views. Namely, the HTML was hard-coded directly\nin our Python code, like this::\n\n    def current_datetime(request):\n        now = datetime.datetime.now()\n        html = \"<html><body>It is now %s.</body></html>\" % now\n        return HttpResponse(html)\n\nAlthough this technique was convenient for the purpose of explaining how views\nwork, it's not a good idea to hard-code HTML directly in your views. Here's\nwhy:\n\n* Any change to the design of the page requires a change to\n  the Python code. The design of a site tends to change far more frequently\n  than the underlying Python code, so it would be convenient if\n  the design could change without needing to modify the Python code.\n\n* Writing Python code and designing HTML are two different disciplines, and\n  most professional Web development environments split these\n  responsibilities between separate people (or even separate departments).\n  Designers and HTML/CSS coders shouldn't be required to edit Python code\n  to get their job done.\n\n* It's most efficient if programmers can work on Python code and designers\n  can work on templates at the same time, rather than one person waiting\n  for the other to finish editing a single file that contains both Python\n  and HTML.\n\nFor these reasons, it's much cleaner and more maintainable to separate the\ndesign of the page from the Python code itself. We can do this with Django's\n*template system*, which we discuss in this chapter.\n\nTemplate System Basics\n======================\n\nA Django template is a string of text that is intended to separate the\npresentation of a document from its data. A template defines placeholders and\nvarious bits of basic logic (template tags) that regulate how the document\nshould be displayed. Usually, templates are used for producing HTML, but Django\ntemplates are equally capable of generating any text-based format.\n\nLet's start with a simple example template. This Django template describes an\nHTML page that thanks a person for placing an order with a company. Think of it\nas a form letter::\n\n    <html>\n    <head><title>Ordering notice</title></head>\n\n    <body>\n\n    <h1>Ordering notice</h1>\n\n    <p>Dear {{ person_name }},</p>\n\n    <p>Thanks for placing an order from {{ company }}. It's scheduled to\n    ship on {{ ship_date|date:\"F j, Y\" }}.</p>\n\n    <p>Here are the items you've ordered:</p>\n\n    <ul>\n    {% for item in item_list %}\n        <li>{{ item }}</li>\n    {% endfor %}\n    </ul>\n\n    {% if ordered_warranty %}\n        <p>Your warranty information will be included in the packaging.</p>\n    {% else %}\n        <p>You didn't order a warranty, so you're on your own when\n        the products inevitably stop working.</p>\n    {% endif %}\n\n    <p>Sincerely,<br />{{ company }}</p>\n\n    </body>\n    </html>\n\nThis template is basic HTML with some variables and template tags thrown in.\nLet's step through it:\n\n* Any text surrounded by a pair of braces (e.g., ``{{ person_name }}``) is a\n  *variable*. This means \"insert the value of the variable with the given\n  name.\" (How do we specify the values of the variables? We'll get to that in\n  a moment.)\n\n* Any text that's surrounded by curly braces and percent signs (e.g., ``{%\n  if ordered_warranty %}``) is a *template tag*. The definition of a tag is\n  quite broad: a tag just tells the template system to \"do something.\"\n\n  This example template contains a ``for`` tag (``{% for item in item_list\n  %}``) and an ``if`` tag (``{% if ordered_warranty %}``).\n\n  A ``for`` tag works very much like a ``for`` statement in Python, letting\n  you loop over each item in a sequence. An ``if`` tag, as you may expect,\n  acts as a logical \"if\" statement. In this particular case, the tag checks\n  whether the value of the ``ordered_warranty`` variable evaluates to\n  ``True``. If it does, the template system will display everything between\n  the ``{% if ordered_warranty %}`` and ``{% else %}``. If not, the\n  template system will display everything between ``{% else %}`` and\n  ``{% endif %}``. Note that the ``{% else %}`` is optional.\n\n* Finally, the second paragraph of this template contains an example of a\n  *filter*, which is the most convenient way to alter the formatting of a\n  variable. In this example, ``{{ ship_date|date:\"F j, Y\" }}``, we're passing the\n  ``ship_date`` variable to the ``date`` filter, giving the ``date`` filter\n  the argument ``\"F j, Y\"``. The ``date`` filter formats dates in a given\n  format, as specified by that argument. Filters are attached using a pipe\n  character (``|``), as a reference to Unix pipes.\n\nEach Django template has access to several built-in tags and filters, many of\nwhich are discussed in the sections that follow. Appendix E contains the full\nlist of tags and filters, and it's a good idea to familiarize yourself with that\nlist so you know what's possible. It's also possible to create your own filters\nand tags; we'll cover that in Chapter 9.\n\nUsing the Template System\n=========================\n\nLet's dive into Django's template system so you can see how it works -- but\nwe're *not* yet going to integrate it with the views that we created in the\nprevious chapter. Our goal here is to show you how the system works\nindependently of the rest of Django. (Put another way: usually you'll be using\nthe template system within a Django view, but we want to make it clear that the\ntemplate system is just a Python library that you can use *anywhere*, not just\nin Django views.)\n\nHere is the most basic way you can use Django's template system in Python code:\n\n1. Create a ``Template`` object by providing the raw template code as a\n   string.\n\n2. Call the ``render()`` method of the ``Template`` object with a given\n   set of variables (the *context*). This returns a fully rendered\n   template as a string, with all of the variables and template tags\n   evaluated according to the context.\n\nIn code, here's what that looks like::\n\n    >>> from django import template\n    >>> t = template.Template('My name is {{ name }}.')\n    >>> c = template.Context({'name': 'Adrian'})\n    >>> print t.render(c)\n    My name is Adrian.\n    >>> c = template.Context({'name': 'Fred'})\n    >>> print t.render(c)\n    My name is Fred.\n\nThe following sections describe each step in much more detail.\n\nCreating Template Objects\n-------------------------\n\nThe easiest way to create a ``Template`` object is to instantiate it directly.\nThe ``Template`` class lives in the ``django.template`` module, and the\nconstructor takes one argument, the raw template code. Let's dip into the Python\ninteractive interpreter to see how this works in code.\n\nFrom the ``mysite`` project directory created by ``django-admin.py\nstartproject`` (as covered in Chapter 2), type ``python manage.py shell`` to\nstart the interactive interpreter.\n\n.. admonition:: A special Python prompt\n\n    If you've used Python before, you may be wondering why we're running\n    ``python manage.py shell`` instead of just ``python``. Both commands will\n    start the interactive interpreter, but the ``manage.py shell`` command has\n    one key difference: before starting the interpreter, it tells Django which\n    settings file to use. Many parts of Django, including the template system,\n    rely on your settings, and you won't be able to use them unless the\n    framework knows which settings to use.\n\n    If you're curious, here's how it works behind the scenes. Django looks for\n    an environment variable called ``DJANGO_SETTINGS_MODULE``, which should be\n    set to the import path of your ``settings.py``. For example,\n    ``DJANGO_SETTINGS_MODULE`` might be set to ``'mysite.settings'``, assuming\n    ``mysite`` is on your Python path.\n\n    When you run ``python manage.py shell``, the command takes care of setting\n    ``DJANGO_SETTINGS_MODULE`` for you. We're encouraging you to use\n    ``python manage.py shell`` in these examples so as to minimize the amount\n    of tweaking and configuring you have to do.\n\nLet's go through some template system basics::\n\n    >>> from django.template import Template\n    >>> t = Template('My name is {{ name }}.')\n    >>> print t\n\nIf you're following along interactively, you'll see something like this::\n\n    <django.template.Template object at 0xb7d5f24c>\n\nThat ``0xb7d5f24c`` will be different every time, and it isn't relevant; it's a\nPython thing (the Python \"identity\" of the ``Template`` object, if you must\nknow).\n\nWhen you create a ``Template`` object, the template system compiles the raw\ntemplate code into an internal, optimized form, ready for rendering. But if your\ntemplate code includes any syntax errors, the call to ``Template()`` will cause\na ``TemplateSyntaxError`` exception::\n\n    >>> from django.template import Template\n    >>> t = Template('{% notatag %}')\n    Traceback (most recent call last):\n      File \"<stdin>\", line 1, in ?\n      ...\n    django.template.TemplateSyntaxError: Invalid block tag: 'notatag'\n\nThe term \"block tag\" here refers to ``{% notatag %}``. \"Block tag\" and\n\"template tag\" are synonymous.\n\nThe system raises a ``TemplateSyntaxError`` exception for any of the following\ncases:\n\n* Invalid tags\n* Invalid arguments to valid tags\n* Invalid filters\n* Invalid arguments to valid filters\n* Invalid template syntax\n* Unclosed tags (for tags that require closing tags)\n\nRendering a Template\n--------------------\n\nOnce you have a ``Template`` object, you can pass it data by giving it a\n*context*. A context is simply a set of template variable names and their\nassociated values. A template uses this to populate its variables and\nevaluate its tags.\n\nA context is represented in Django by the ``Context`` class, which lives in the\n``django.template`` module. Its constructor takes one optional argument: a\ndictionary mapping variable names to variable values. Call the ``Template``\nobject's ``render()`` method with the context to \"fill\" the template::\n\n    >>> from django.template import Context, Template\n    >>> t = Template('My name is {{ name }}.')\n    >>> c = Context({'name': 'Stephane'})\n    >>> t.render(c)\n    u'My name is Stephane.'\n\nOne thing we should point out here is that the return value of ``t.render(c)``\nis a Unicode object -- not a normal Python string. You can tell this by the\n``u`` in front of the string. Django uses Unicode objects instead of normal\nstrings throughout the framework. If you understand the repercussions of that,\nbe thankful for the sophisticated things Django does behind the scenes to make\nit work. If you don't understand the repercussions of that, don't worry for\nnow; just know that Django's Unicode support makes it relatively painless for\nyour applications to support a wide variety of character sets beyond the basic\n\"A-Z\" of the English language.\n\n.. admonition:: Dictionaries and Contexts\n\n   A Python dictionary is a mapping between known keys and variable\n   values. A ``Context`` is similar to a dictionary, but a ``Context``\n   provides additional functionality, as covered in Chapter 9.\n\nVariable names must begin with a letter (A-Z or a-z) and may contain more\nletters, digits, underscores, and dots. (Dots are a special case we'll get to in a moment.)\nVariable names are case sensitive.\n\nHere's an example of template compilation and rendering, using a template\nsimilar to the example in the beginning of this chapter::\n\n    >>> from django.template import Template, Context\n    >>> raw_template = \"\"\"<p>Dear {{ person_name }},</p>\n    ...\n    ... <p>Thanks for placing an order from {{ company }}. It's scheduled to\n    ... ship on {{ ship_date|date:\"F j, Y\" }}.</p>\n    ...\n    ... {% if ordered_warranty %}\n    ... <p>Your warranty information will be included in the packaging.</p>\n    ... {% else %}\n    ... <p>You didn't order a warranty, so you're on your own when\n    ... the products inevitably stop working.</p>\n    ... {% endif %}\n    ...\n    ... <p>Sincerely,<br />{{ company }}</p>\"\"\"\n    >>> t = Template(raw_template)\n    >>> import datetime\n    >>> c = Context({'person_name': 'John Smith',\n    ...     'company': 'Outdoor Equipment',\n    ...     'ship_date': datetime.date(2009, 4, 2),\n    ...     'ordered_warranty': False})\n    >>> t.render(c)\n    u\"<p>Dear John Smith,</p>\\n\\n<p>Thanks for placing an order from Outdoor\n    Equipment. It's scheduled to\\nship on April 2, 2009.</p>\\n\\n\\n<p>You\n    didn't order a warranty, so you're on your own when\\nthe products\n    inevitably stop working.</p>\\n\\n\\n<p>Sincerely,<br />Outdoor Equipment\n    </p>\"\n\nLet's step through this code one statement at a time:\n\n* First, we import the classes ``Template`` and ``Context``, which both\n  live in the module ``django.template``.\n\n* We save the raw text of our template into the variable\n  ``raw_template``. Note that we use triple quote marks to designate the\n  string, because it wraps over multiple lines; in contrast, strings\n  within single quote marks cannot be wrapped over multiple lines.\n\n* Next, we create a template object, ``t``, by passing ``raw_template`` to\n  the ``Template`` class constructor.\n\n* We import the ``datetime`` module from Python's standard library,\n  because we'll need it in the following statement.\n\n* Then, we create a ``Context`` object, ``c``. The ``Context``\n  constructor takes a Python dictionary, which maps variable names to\n  values. Here, for example, we specify that the ``person_name``\n  is ``'John Smith'``, ``company`` is ``'Outdoor Equipment'``, and so forth.\n\n* Finally, we call the ``render()`` method on our template object, passing\n  it the context. This returns the rendered template -- i.e., it replaces\n  template variables with the actual values of the variables, and it\n  executes any template tags.\n\n  Note that the \"You didn't order a warranty\" paragraph was displayed\n  because the ``ordered_warranty`` variable evaluated to ``False``. Also\n  note the date, ``April 2, 2009``, which is displayed according to the\n  format string ``'F j, Y'``. (We'll explain format strings for the\n  ``date`` filter in a little while.)\n\n  If you're new to Python, you may wonder why this output includes\n  newline characters (``'\\n'``) rather than displaying the line breaks.\n  That's happening because of a subtlety in the Python interactive\n  interpreter: the call to ``t.render(c)`` returns a string, and by default\n  the interactive interpreter displays the *representation* of the string,\n  rather than the printed value of the string. If you want to see the\n  string with line breaks displayed as true line breaks rather than ``'\\n'``\n  characters, use the ``print`` statement: ``print t.render(c)``.\n\nThose are the fundamentals of using the Django template system: just write a\ntemplate string, create a ``Template`` object, create a ``Context``, and call\nthe ``render()`` method.\n\nMultiple Contexts, Same Template\n--------------------------------\n\nOnce you have a ``Template`` object, you can render multiple contexts through\nit. For example::\n\n    >>> from django.template import Template, Context\n    >>> t = Template('Hello, {{ name }}')\n    >>> print t.render(Context({'name': 'John'}))\n    Hello, John\n    >>> print t.render(Context({'name': 'Julie'}))\n    Hello, Julie\n    >>> print t.render(Context({'name': 'Pat'}))\n    Hello, Pat\n\nWhenever you're using the same template source to render multiple\ncontexts like this, it's more efficient to create the ``Template``\nobject *once*, and then call ``render()`` on it multiple times::\n\n    # Bad\n    for name in ('John', 'Julie', 'Pat'):\n        t = Template('Hello, {{ name }}')\n        print t.render(Context({'name': name}))\n\n    # Good\n    t = Template('Hello, {{ name }}')\n    for name in ('John', 'Julie', 'Pat'):\n        print t.render(Context({'name': name}))\n\nDjango's template parsing is quite fast. Behind the scenes, most of the parsing\nhappens via a call to a single regular expression. This is in stark\ncontrast to XML-based template engines, which incur the overhead of an XML\nparser and tend to be orders of magnitude slower than Django's template\nrendering engine.\n\nContext Variable Lookup\n-----------------------\n\nIn the examples so far, we've passed simple values in the contexts -- mostly\nstrings, plus a ``datetime.date`` example. However, the template system\nelegantly handles more complex data structures, such as lists, dictionaries, and\ncustom objects.\n\nThe key to traversing complex data structures in Django templates is the dot\ncharacter (``.``). Use a dot to access dictionary keys, attributes, methods,\nor indices of an object.\n\nThis is best illustrated with a few examples. For instance, suppose\nyou're passing a Python dictionary to a template. To access the values\nof that dictionary by dictionary key, use a dot::\n\n    >>> from django.template import Template, Context\n    >>> person = {'name': 'Sally', 'age': '43'}\n    >>> t = Template('{{ person.name }} is {{ person.age }} years old.')\n    >>> c = Context({'person': person})\n    >>> t.render(c)\n    u'Sally is 43 years old.'\n\nSimilarly, dots also allow access of object attributes. For example, a Python\n``datetime.date`` object has ``year``, ``month``, and ``day`` attributes, and\nyou can use a dot to access those attributes in a Django template::\n\n    >>> from django.template import Template, Context\n    >>> import datetime\n    >>> d = datetime.date(1993, 5, 2)\n    >>> d.year\n    1993\n    >>> d.month\n    5\n    >>> d.day\n    2\n    >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')\n    >>> c = Context({'date': d})\n    >>> t.render(c)\n    u'The month is 5 and the year is 1993.'\n\nThis example uses a custom class, demonstrating that variable dots also allow\nattribute access on arbitrary objects::\n\n    >>> from django.template import Template, Context\n    >>> class Person(object):\n    ...     def __init__(self, first_name, last_name):\n    ...         self.first_name, self.last_name = first_name, last_name\n    >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')\n    >>> c = Context({'person': Person('John', 'Smith')})\n    >>> t.render(c)\n    u'Hello, John Smith.'\n\nDots can also refer to *methods* on objects. For example, each Python string\nhas the methods ``upper()`` and ``isdigit()``, and you can call those in Django\ntemplates using the same dot syntax::\n\n    >>> from django.template import Template, Context\n    >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')\n    >>> t.render(Context({'var': 'hello'}))\n    u'hello -- HELLO -- False'\n    >>> t.render(Context({'var': '123'}))\n    u'123 -- 123 -- True'\n\nNote that you do *not* include parentheses in the method calls. Also, it's not\npossible to pass arguments to the methods; you can only call methods that have\nno required arguments. (We explain this philosophy later in this chapter.)\n\nFinally, dots are also used to access list indices, for example::\n\n    >>> from django.template import Template, Context\n    >>> t = Template('Item 2 is {{ items.2 }}.')\n    >>> c = Context({'items': ['apples', 'bananas', 'carrots']})\n    >>> t.render(c)\n    u'Item 2 is carrots.'\n\nNegative list indices are not allowed. For example, the template variable\n``{{ items.-1 }}`` would cause a ``TemplateSyntaxError``.\n\n.. admonition:: Python Lists\n\n   A reminder: Python lists have 0-based indices. The first item is at index 0,\n   the second is at index 1, and so on.\n\nDot lookups can be summarized like this: when the template system\nencounters a dot in a variable name, it tries the following lookups, in this\norder:\n\n* Dictionary lookup (e.g., ``foo[\"bar\"]``)\n* Attribute lookup (e.g., ``foo.bar``)\n* Method call (e.g., ``foo.bar()``)\n* List-index lookup (e.g., ``foo[2]``)\n\nThe system uses the first lookup type that works. It's short-circuit logic.\n\nDot lookups can be nested multiple levels deep. For instance, the following\nexample uses ``{{ person.name.upper }}``, which translates into a dictionary\nlookup (``person['name']``) and then a method call (``upper()``)::\n\n    >>> from django.template import Template, Context\n    >>> person = {'name': 'Sally', 'age': '43'}\n    >>> t = Template('{{ person.name.upper }} is {{ person.age }} years old.')\n    >>> c = Context({'person': person})\n    >>> t.render(c)\n    u'SALLY is 43 years old.'\n\nMethod Call Behavior\n~~~~~~~~~~~~~~~~~~~~\n\nMethod calls are slightly more complex than the other lookup types. Here are\nsome things to keep in mind:\n\n* If, during the method lookup, a method raises an exception, the exception\n  will be propagated, unless the exception has an attribute\n  ``silent_variable_failure`` whose value is ``True``. If the exception\n  *does* have a ``silent_variable_failure`` attribute, the variable will\n  render as an empty string, for example::\n\n        >>> t = Template(\"My name is {{ person.first_name }}.\")\n        >>> class PersonClass3:\n        ...     def first_name(self):\n        ...         raise AssertionError, \"foo\"\n        >>> p = PersonClass3()\n        >>> t.render(Context({\"person\": p}))\n        Traceback (most recent call last):\n        ...\n        AssertionError: foo\n\n        >>> class SilentAssertionError(AssertionError):\n        ...     silent_variable_failure = True\n        >>> class PersonClass4:\n        ...     def first_name(self):\n        ...         raise SilentAssertionError\n        >>> p = PersonClass4()\n        >>> t.render(Context({\"person\": p}))\n        u'My name is .'\n\n* A method call will only work if the method has no required arguments.\n  Otherwise, the system will move to the next lookup type (list-index\n  lookup).\n\n* Obviously, some methods have side effects, and it would be foolish at\n  best, and possibly even a security hole, to allow the template system to\n  access them.\n\n  Say, for instance, you have a ``BankAccount`` object that has a\n  ``delete()`` method. If a template includes something like\n  ``{{ account.delete }}``, where ``account`` is a ``BankAccount`` object,\n  the object would be deleted when the template is rendered!\n\n  To prevent this, set the function attribute ``alters_data`` on the\n  method::\n\n      def delete(self):\n          # Delete the account\n      delete.alters_data = True\n\n  The template system won't execute any method marked in this way.\n  Continuing the above example, if a template includes\n  ``{{ account.delete }}`` and the ``delete()`` method has the\n  ``alters_data=True``, then the ``delete()`` method will not be executed\n  when the template is rendered. Instead, it will fail silently.\n\nHow Invalid Variables Are Handled\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nBy default, if a variable doesn't exist, the template system renders it as an\nempty string, failing silently. For example::\n\n    >>> from django.template import Template, Context\n    >>> t = Template('Your name is {{ name }}.')\n    >>> t.render(Context())\n    u'Your name is .'\n    >>> t.render(Context({'var': 'hello'}))\n    u'Your name is .'\n    >>> t.render(Context({'NAME': 'hello'}))\n    u'Your name is .'\n    >>> t.render(Context({'Name': 'hello'}))\n    u'Your name is .'\n\nThe system fails silently rather than raising an exception because it's\nintended to be resilient to human error. In this case, all of the\nlookups failed because variable names have the wrong case or name. In the real\nworld, it's unacceptable for a Web site to become inaccessible due to a\nsmall template syntax error.\n\nPlaying with Context Objects\n----------------------------\n\nMost of the time, you'll instantiate ``Context`` objects by passing in a\nfully populated dictionary to ``Context()``. But you can add and delete items\nfrom a ``Context`` object once it's been instantiated, too, using standard\nPython dictionary syntax::\n\n    >>> from django.template import Context\n    >>> c = Context({\"foo\": \"bar\"})\n    >>> c['foo']\n    'bar'\n    >>> del c['foo']\n    >>> c['foo']\n    Traceback (most recent call last):\n      ...\n    KeyError: 'foo'\n    >>> c['newvariable'] = 'hello'\n    >>> c['newvariable']\n    'hello'\n\nBasic Template Tags and Filters\n===============================\n\nAs we've mentioned already, the template system ships with built-in tags and\nfilters. The sections that follow provide a rundown of the most common tags and\nfilters.\n\nTags\n----\n\nif/else\n~~~~~~~\n\nThe ``{% if %}`` tag evaluates a variable, and if that variable is \"True\"\n(i.e., it exists, is not empty, and is not a false Boolean value), the system\nwill display everything between ``{% if %}`` and ``{% endif %}``, for example::\n\n    {% if today_is_weekend %}\n        <p>Welcome to the weekend!</p>\n    {% endif %}\n\nAn ``{% else %}`` tag is optional::\n\n    {% if today_is_weekend %}\n        <p>Welcome to the weekend!</p>\n    {% else %}\n        <p>Get back to work.</p>\n    {% endif %}\n\n.. admonition:: Python \"Truthiness\"\n\n   In Python and in the Django template system, these objects evaluate to\n   ``False`` in a Boolean context:\n\n   * An empty list (``[]``)\n   * An empty tuple (``()``)\n   * An empty dictionary (``{}``)\n   * An empty string (``''``)\n   * Zero (``0``)\n   * The special object ``None``\n   * The object ``False`` (obviously)\n   * Custom objects that define their own Boolean context behavior\n     (this is advanced Python usage)\n\n   Everything else evaluates to ``True``.\n\nThe ``{% if %}`` tag accepts ``and``, ``or``, or ``not`` for testing multiple\nvariables, or to negate a given variable. For example::\n\n    {% if athlete_list and coach_list %}\n        Both athletes and coaches are available.\n    {% endif %}\n\n    {% if not athlete_list %}\n        There are no athletes.\n    {% endif %}\n\n    {% if athlete_list or coach_list %}\n        There are some athletes or some coaches.\n    {% endif %}\n\n    {% if not athlete_list or coach_list %}\n        There are no athletes or there are some coaches.\n    {% endif %}\n\n    {% if athlete_list and not coach_list %}\n        There are some athletes and absolutely no coaches.\n    {% endif %}\n\n``{% if %}`` tags don't allow ``and`` and ``or`` clauses within the same tag,\nbecause the order of logic would be ambiguous. For example, this is invalid::\n\n    {% if athlete_list and coach_list or cheerleader_list %}\n\nThe use of parentheses for controlling order of operations is not supported. If\nyou find yourself needing parentheses, consider performing logic outside the\ntemplate and passing the result of that as a dedicated template variable. Or,\njust use nested ``{% if %}`` tags, like this::\n\n    {% if athlete_list %}\n        {% if coach_list or cheerleader_list %}\n            We have athletes, and either coaches or cheerleaders!\n        {% endif %}\n    {% endif %}\n\nMultiple uses of the same logical operator are fine, but you can't\ncombine different operators. For example, this is valid::\n\n    {% if athlete_list or coach_list or parent_list or teacher_list %}\n\nThere is no ``{% elif %}`` tag. Use nested ``{% if %}`` tags to accomplish\nthe same thing::\n\n    {% if athlete_list %}\n        <p>Here are the athletes: {{ athlete_list }}.</p>\n    {% else %}\n        <p>No athletes are available.</p>\n        {% if coach_list %}\n            <p>Here are the coaches: {{ coach_list }}.</p>\n        {% endif %}\n    {% endif %}\n\nMake sure to close each ``{% if %}`` with an ``{% endif %}``. Otherwise, Django\nwill throw a ``TemplateSyntaxError``.\n\nfor\n~~~\n\nThe ``{% for %}`` tag allows you to loop over each item in a sequence. As in\nPython's ``for`` statement, the syntax is ``for X in Y``, where ``Y`` is the\nsequence to loop over and ``X`` is the name of the variable to use for a\nparticular cycle of the loop. Each time through the loop, the template system\nwill render everything between ``{% for %}`` and ``{% endfor %}``.\n\nFor example, you could use the following to display a list of athletes given a\nvariable ``athlete_list``::\n\n    <ul>\n    {% for athlete in athlete_list %}\n        <li>{{ athlete.name }}</li>\n    {% endfor %}\n    </ul>\n\nAdd ``reversed`` to the tag to loop over the list in reverse::\n\n    {% for athlete in athlete_list reversed %}\n    ...\n    {% endfor %}\n\nIt's possible to nest ``{% for %}`` tags::\n\n    {% for athlete in athlete_list %}\n        <h1>{{ athlete.name }}</h1>\n        <ul>\n        {% for sport in athlete.sports_played %}\n            <li>{{ sport }}</li>\n        {% endfor %}\n        </ul>\n    {% endfor %}\n\nA common pattern is to check the size of the list before looping over it, and\noutputting some special text if the list is empty::\n\n    {% if athlete_list %}\n        {% for athlete in athlete_list %}\n            <p>{{ athlete.name }}</p>\n        {% endfor %}\n    {% else %}\n        <p>There are no athletes. Only computer programmers.</p>\n    {% endif %}\n\nBecause this pattern is so common, the ``for`` tag supports an optional\n``{% empty %}`` clause that lets you define what to output if the list is\nempty. This example is equivalent to the previous one::\n\n    {% for athlete in athlete_list %}\n        <p>{{ athlete.name }}</p>\n    {% empty %}\n        <p>There are no athletes. Only computer programmers.</p>\n    {% endfor %}\n\nThere is no support for \"breaking out\" of a loop before the loop is finished.\nIf you want to accomplish this, change the variable you're looping over so that\nit includes only the values you want to loop over. Similarly, there is no\nsupport for a \"continue\" statement that would instruct the loop processor to\nreturn immediately to the front of the loop. (See the section \"Philosophies and\nLimitations\" later in this chapter for the reasoning behind this design\ndecision.)\n\nWithin each ``{% for %}`` loop, you get access to a template variable called\n``forloop``. This variable has a few attributes that give you information about\nthe progress of the loop:\n\n* ``forloop.counter`` is always set to an integer representing the number\n  of times the loop has been entered. This is one-indexed, so the first\n  time through the loop, ``forloop.counter`` will be set to ``1``.\n  Here's an example::\n\n      {% for item in todo_list %}\n          <p>{{ forloop.counter }}: {{ item }}</p>\n      {% endfor %}\n\n* ``forloop.counter0`` is like ``forloop.counter``, except it's\n  zero-indexed. Its value will be set to ``0`` the first time through the\n  loop.\n\n* ``forloop.revcounter`` is always set to an integer representing the\n  number of remaining items in the loop. The first time through the loop,\n  ``forloop.revcounter`` will be set to the total number of items in the\n  sequence you're traversing. The last time through the loop,\n  ``forloop.revcounter`` will be set to ``1``.\n\n* ``forloop.revcounter0`` is like ``forloop.revcounter``, except it's\n  zero-indexed. The first time through the loop, ``forloop.revcounter0``\n  will be set to the number of elements in the sequence minus 1. The last\n  time through the loop, it will be set to ``0``.\n\n* ``forloop.first`` is a Boolean value set to ``True`` if this is the first\n  time through the loop. This is convenient for special-casing::\n\n      {% for object in objects %}\n          {% if forloop.first %}<li class=\"first\">{% else %}<li>{% endif %}\n          {{ object }}\n          </li>\n      {% endfor %}\n\n* ``forloop.last`` is a Boolean value set to ``True`` if this is the last\n  time through the loop. A common use for this is to put pipe\n  characters between a list of links::\n\n      {% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}\n\n  The above template code might output something like this::\n\n      Link1 | Link2 | Link3 | Link4\n\n  Another common use for this is to put a comma between words in a list::\n\n      Favorite places:\n      {% for p in places %}{{ p }}{% if not forloop.last %}, {% endif %}{% endfor %}\n\n*  ``forloop.parentloop`` is a reference to the ``forloop`` object for the\n   *parent* loop, in case of nested loops. Here's an example::\n\n      {% for country in countries %}\n          <table>\n          {% for city in country.city_list %}\n              <tr>\n              <td>Country #{{ forloop.parentloop.counter }}</td>\n              <td>City #{{ forloop.counter }}</td>\n              <td>{{ city }}</td>\n              </tr>\n          {% endfor %}\n          </table>\n      {% endfor %}\n\nThe magic ``forloop`` variable is only available within loops. After the\ntemplate parser has reached ``{% endfor %}``, ``forloop`` disappears.\n\n.. admonition:: Context and the forloop Variable\n\n   Inside the ``{% for %}`` block, the existing variables are moved\n   out of the way to avoid overwriting the magic ``forloop``\n   variable. Django exposes this moved context in\n   ``forloop.parentloop``. You generally don't need to worry about\n   this, but if you supply a template variable named ``forloop``\n   (though we advise against it), it will be named\n   ``forloop.parentloop`` while inside the ``{% for %}`` block.\n\nifequal/ifnotequal\n~~~~~~~~~~~~~~~~~~\n\nThe Django template system deliberately is not a full-fledged programming\nlanguage and thus does not allow you to execute arbitrary Python statements.\n(More on this idea in the section \"Philosophies and Limitations.\") However,\nit's quite a common template requirement to compare two values and display\nsomething if they're equal -- and Django provides an ``{% ifequal %}`` tag for\nthat purpose.\n\nThe ``{% ifequal %}`` tag compares two values and displays everything between\n``{% ifequal %}`` and ``{% endifequal %}`` if the values are equal.\n\nThis example compares the template variables ``user`` and ``currentuser``::\n\n    {% ifequal user currentuser %}\n        <h1>Welcome!</h1>\n    {% endifequal %}\n\nThe arguments can be hard-coded strings, with either single or double quotes,\nso the following is valid::\n\n    {% ifequal section 'sitenews' %}\n        <h1>Site News</h1>\n    {% endifequal %}\n\n    {% ifequal section \"community\" %}\n        <h1>Community</h1>\n    {% endifequal %}\n\nJust like ``{% if %}``, the ``{% ifequal %}`` tag supports an optional\n``{% else %}``::\n\n    {% ifequal section 'sitenews' %}\n        <h1>Site News</h1>\n    {% else %}\n        <h1>No News Here</h1>\n    {% endifequal %}\n\nOnly template variables, strings, integers, and decimal numbers are allowed as\narguments to ``{% ifequal %}``. These are valid examples::\n\n    {% ifequal variable 1 %}\n    {% ifequal variable 1.23 %}\n    {% ifequal variable 'foo' %}\n    {% ifequal variable \"foo\" %}\n\nAny other types of variables, such as Python dictionaries, lists, or Booleans,\ncan't be hard-coded in ``{% ifequal %}``. These are invalid examples::\n\n    {% ifequal variable True %}\n    {% ifequal variable [1, 2, 3] %}\n    {% ifequal variable {'key': 'value'} %}\n\nIf you need to test whether something is true or false, use the ``{% if %}``\ntags instead of ``{% ifequal %}``.\n\nComments\n~~~~~~~~\n\nJust as in HTML or Python, the Django template language allows for comments. To\ndesignate a comment, use ``{# #}``::\n\n    {# This is a comment #}\n\nThe comment will not be output when the template is rendered.\n\nComments using this syntax cannot span multiple lines. This limitation improves\ntemplate parsing performance. In the following template, the rendered output\nwill look exactly the same as the template (i.e., the comment tag will\nnot be parsed as a comment)::\n\n    This is a {# this is not\n    a comment #}\n    test.\n\nIf you want to use multi-line comments, use the ``{% comment %}`` template tag,\nlike this::\n\n    {% comment %}\n    This is a\n    multi-line comment.\n    {% endcomment %}\n\nFilters\n-------\n\nAs explained earlier in this chapter, template filters are simple ways of\naltering the value of variables before they're displayed. Filters use a pipe\ncharacter, like this::\n\n    {{ name|lower }}\n\nThis displays the value of the ``{{ name }}`` variable after being filtered\nthrough the ``lower`` filter, which converts text to lowercase.\n\nFilters can be *chained* -- that is, they can be used in tandem such that the\noutput of one filter is applied to the next. Here's an example that takes the\nfirst element in a list and converts it to uppercase::\n\n    {{ my_list|first|upper }}\n\nSome filters take arguments. A filter argument comes after a colon and is\nalways in double quotes. For example::\n\n    {{ bio|truncatewords:\"30\" }}\n\nThis displays the first 30 words of the ``bio`` variable.\n\nThe following are a few of the most important filters. Appendix E covers the rest.\n\n* ``addslashes``: Adds a backslash before any backslash, single quote, or\n  double quote. This is useful if the produced text is included in\n  a JavaScript string.\n\n* ``date``: Formats a ``date`` or ``datetime`` object according to a\n  format string given in the parameter, for example::\n\n      {{ pub_date|date:\"F j, Y\" }}\n\n  Format strings are defined in Appendix E.\n\n* ``length``: Returns the length of the value. For a list, this returns the\n  number of elements. For a string, this returns the number of characters.\n  (Python experts, take note that this works on any Python object that\n  knows how to determine its length -- i.e., any object that has a\n  ``__len__()`` method.)\n\nPhilosophies and Limitations\n============================\n\nNow that you've gotten a feel for the Django template language, we should point\nout some of its intentional limitations, along with some philosophies behind why\nit works the way it works.\n\nMore than any other component of Web applications, template syntax is highly\nsubjective, and programmers' opinions vary wildly. The fact that Python alone\nhas dozens, if not hundreds, of open source template-language implementations\nsupports this point. Each was likely created because its developer deemed all\nexisting template languages inadequate. (In fact, it is said to be a rite of\npassage for a Python developer to write his or her own template language! If\nyou haven't done this yet, consider it. It's a fun exercise.)\n\nWith that in mind, you might be interested to know that Django doesn't require\nthat you use its template language. Because Django is intended to be a\nfull-stack Web framework that provides all the pieces necessary for Web\ndevelopers to be productive, many times it's *more convenient* to use Django's\ntemplate system than other Python template libraries, but it's not a strict\nrequirement in any sense. As you'll see in the upcoming section \"Using Templates\nin Views\", it's very easy to use another template language with Django.\n\nStill, it's clear we have a strong preference for the way Django's template\nlanguage works. The template system has roots in how Web development is done at\nWorld Online and the combined experience of Django's creators. Here are a few of\nthose philosophies:\n\n* *Business logic should be separated from presentation logic*. Django's\n  developers see a  template system as a tool that controls presentation and\n  presentation-related logic -- and that's it. The template system shouldn't\n  support functionality that goes beyond this basic goal.\n\n  For that reason, it's impossible to call Python code directly within\n  Django templates. All \"programming\" is fundamentally limited to the scope\n  of what template tags can do. It *is* possible to write custom template\n  tags that do arbitrary things, but the out-of-the-box Django template\n  tags intentionally do not allow for arbitrary Python code execution.\n\n* *Syntax should be decoupled from HTML/XML*. Although Django's template\n  system is used primarily to produce HTML, it's intended to be just as\n  usable for non-HTML formats, such as plain text. Some other template\n  languages are XML based, placing all template logic within XML tags or\n  attributes, but Django deliberately avoids this limitation. Requiring\n  valid XML to write templates introduces a world of human mistakes and\n  hard-to-understand error messages, and using an XML engine to parse\n  templates incurs an unacceptable level of overhead in template processing.\n\n* *Designers are assumed to be comfortable with HTML code*. The template\n  system isn't designed so that templates necessarily are displayed nicely\n  in WYSIWYG editors such as Dreamweaver. That is too severe a limitation\n  and wouldn't allow the syntax to be as friendly as it is. Django expects\n  template authors to be comfortable editing HTML directly.\n\n* *Designers are assumed not to be Python programmers*. The template system\n  authors recognize that Web page templates are most often written by\n  *designers*, not *programmers*, and therefore should not assume Python\n  knowledge.\n\n  However, the system also intends to accommodate small teams in which the\n  templates *are* created by Python programmers. It offers a way to extend\n  the system's syntax by writing raw Python code. (More on this in Chapter\n  9.)\n\n* *The goal is not to invent a programming language*. The goal is to offer\n  just enough programming-esque functionality, such as branching and\n  looping, that is essential for making presentation-related decisions.\n\nUsing Templates in Views\n========================\n\nYou've learned the basics of using the template system; now let's use this\nknowledge to create a view. Recall the ``current_datetime`` view in\n``mysite.views``, which we started in the previous chapter. Here's what it looks\nlike::\n\n    from django.http import HttpResponse\n    import datetime\n\n    def current_datetime(request):\n        now = datetime.datetime.now()\n        html = \"<html><body>It is now %s.</body></html>\" % now\n        return HttpResponse(html)\n\nLet's change this view to use Django's template system. At first, you might\nthink to do something like this::\n\n    from django.template import Template, Context\n    from django.http import HttpResponse\n    import datetime\n\n    def current_datetime(request):\n        now = datetime.datetime.now()\n        t = Template(\"<html><body>It is now {{ current_date }}.</body></html>\")\n        html = t.render(Context({'current_date': now}))\n        return HttpResponse(html)\n\nSure, that uses the template system, but it doesn't solve the problems we\npointed out in the introduction of this chapter. Namely, the template is still\nembedded in the Python code, so true separation of data and presentation isn't\nachieved. Let's fix that by putting the template in a *separate file*, which\nthis view will load.\n\nYou might first consider saving your template somewhere on your\nfilesystem and using Python's built-in file-opening functionality to read\nthe contents of the template. Here's what that might look like, assuming the\ntemplate was saved as the file ``/home/djangouser/templates/mytemplate.html``::\n\n    from django.template import Template, Context\n    from django.http import HttpResponse\n    import datetime\n\n    def current_datetime(request):\n        now = datetime.datetime.now()\n        # Simple way of using templates from the filesystem.\n        # This is BAD because it doesn't account for missing files!\n        fp = open('/home/djangouser/templates/mytemplate.html')\n        t = Template(fp.read())\n        fp.close()\n        html = t.render(Context({'current_date': now}))\n        return HttpResponse(html)\n\nThis approach, however, is inelegant for these reasons:\n\n* It doesn't handle the case of a missing file. If the file\n  ``mytemplate.html`` doesn't exist or isn't readable, the ``open()`` call\n  will raise an ``IOError`` exception.\n\n* It hard-codes your template location. If you were to use this\n  technique for every view function, you'd be duplicating the template\n  locations. Not to mention it involves a lot of typing!\n\n* It includes a lot of boring boilerplate code. You've got better things to\n  do than to write calls to ``open()``, ``fp.read()``, and ``fp.close()``\n  each time you load a template.\n\nTo solve these issues, we'll use *template loading* and *template directories*.\n\nTemplate Loading\n================\n\nDjango provides a convenient and powerful API for loading templates from the\nfilesystem, with the goal of removing redundancy both in your template-loading\ncalls and in your templates themselves.\n\nIn order to use this template-loading API, first you'll need to tell the\nframework where you store your templates. The place to do this is in your\nsettings file -- the ``settings.py`` file that we mentioned last chapter, when\nwe introduced the ``ROOT_URLCONF`` setting.\n\nIf you're following along, open your ``settings.py`` and find the\n``TEMPLATE_DIRS`` setting. By default, it's an empty tuple, likely containing\nsome auto-generated comments::\n\n    TEMPLATE_DIRS = (\n        # Put strings here, like \"/home/html/django_templates\" or \"C:/www/django/templates\".\n        # Always use forward slashes, even on Windows.\n        # Don't forget to use absolute paths, not relative paths.\n    )\n\nThis setting tells Django's template-loading mechanism where to look for\ntemplates. Pick a directory where you'd like to store your templates and add it\nto ``TEMPLATE_DIRS``, like so::\n\n    TEMPLATE_DIRS = (\n        '/home/django/mysite/templates',\n    )\n\nThere are a few things to note:\n\n* You can specify any directory you want, as long as the directory and\n  templates within that directory are readable by the user account under\n  which your Web server runs. If you can't think of an appropriate\n  place to put your templates, we recommend creating a ``templates``\n  directory within your project (i.e., within the ``mysite`` directory you\n  created in Chapter 2).\n\n* If your ``TEMPLATE_DIRS`` contains only one directory, don't forget the\n  comma at the end of the directory string!\n\n  Bad::\n\n      # Missing comma!\n      TEMPLATE_DIRS = (\n          '/home/django/mysite/templates'\n      )\n\n  Good::\n\n      # Comma correctly in place.\n      TEMPLATE_DIRS = (\n          '/home/django/mysite/templates',\n      )\n\n  The reason for this is that Python requires commas within single-element\n  tuples to disambiguate the tuple from a parenthetical expression. This is\n  a common newbie gotcha.\n\n* If you're on Windows, include your drive letter and use Unix-style\n  forward slashes rather than backslashes, as follows::\n\n      TEMPLATE_DIRS = (\n          'C:/www/django/templates',\n      )\n\n* It's simplest to use absolute paths (i.e., directory paths that start at\n  the root of the filesystem). If you want to be a bit more flexible and\n  decoupled, though, you can take advantage of the fact that Django\n  settings files are just Python code by constructing the contents of\n  ``TEMPLATE_DIRS`` dynamically. For example::\n\n      import os.path\n\n      TEMPLATE_DIRS = (\n          os.path.join(os.path.dirname(__file__), 'templates').replace('\\\\','/'),\n      )\n\n  This example uses the \"magic\" Python variable ``__file__``, which is\n  automatically set to the file name of the Python module in which the code\n  lives. It gets the name of the directory that contains ``settings.py``\n  (``os.path.dirname``), then joins that with ``templates`` in a\n  cross-platform way (``os.path.join``), then ensures that everything uses\n  forward slashes instead of backslashes (in case of Windows).\n\n  While we're on the topic of dynamic Python code in settings files, we\n  should point out that it's very important to avoid Python errors in your\n  settings file. If you introduce a syntax error, or a runtime error, your\n  Django-powered site will likely crash.\n\nWith ``TEMPLATE_DIRS`` set, the next step is to change the view code to\nuse Django's template-loading functionality rather than hard-coding the\ntemplate paths. Returning to our ``current_datetime`` view, let's change it\nlike so::\n\n    from django.template.loader import get_template\n    from django.template import Context\n    from django.http import HttpResponse\n    import datetime\n\n    def current_datetime(request):\n        now = datetime.datetime.now()\n        t = get_template('current_datetime.html')\n        html = t.render(Context({'current_date': now}))\n        return HttpResponse(html)\n\nIn this example, we're using the function\n``django.template.loader.get_template()`` rather than loading the template from\nthe filesystem manually. The ``get_template()`` function takes a template name\nas its argument, figures out where the template lives on the filesystem, opens\nthat file, and returns a compiled ``Template`` object.\n\nOur template in this example is ``current_datetime.html``, but there's nothing\nspecial about that ``.html`` extension. You can give your templates whatever\nextension makes sense for your application, or you can leave off extensions\nentirely.\n\nTo determine the location of the template on your filesystem,\n``get_template()`` combines your template directories from ``TEMPLATE_DIRS``\nwith the template name that you pass to ``get_template()``. For example, if\nyour ``TEMPLATE_DIRS`` is set to ``'/home/django/mysite/templates'``, the above\n``get_template()`` call would look for the template\n``/home/django/mysite/templates/current_datetime.html``.\n\nIf ``get_template()`` cannot find the template with the given name, it raises\na ``TemplateDoesNotExist`` exception. To see what that looks like, fire up the\nDjango development server again by running ``python manage.py runserver``\nwithin your Django project's directory. Then, point your browser at the page\nthat activates the ``current_datetime`` view (e.g.,\n``http://127.0.0.1:8000/time/``). Assuming your ``DEBUG`` setting is set to\n``True`` and you haven't yet created a ``current_datetime.html`` template, you\nshould see a Django error page highlighting the ``TemplateDoesNotExist`` error.\n\n.. figure:: graphics/chapter04/missing_template.png\n   :alt: Screenshot of a \"TemplateDoesNotExist\" error.\n\n   Figure 4-1: The error page shown when a template cannot be found.\n\nThis error page is similar to the one we explained in Chapter 3, with one\nadditional piece of debugging information: a \"Template-loader postmortem\"\nsection. This section tells you which templates Django tried to load, along with\nthe reason each attempt failed (e.g., \"File does not exist\"). This information\nis invaluable when you're trying to debug template-loading errors.\n\nMoving along, create the ``current_datetime.html`` file within your template\ndirectory using the following template code::\n\n    <html><body>It is now {{ current_date }}.</body></html>\n\nRefresh the page in your Web browser, and you should see the fully rendered\npage.\n\nrender()\n--------\n\nWe've shown you how to load a template, fill a ``Context`` and return an\n``HttpResponse`` object with the result of the rendered template. We've\noptimized it to use ``get_template()`` instead of hard-coding templates and\ntemplate paths. But it still requires a fair amount of typing to do those\nthings. Because this is such a common idiom, Django provides a shortcut that\nlets you load a template, render it and return an ``HttpResponse`` -- all in\none line of code.\n\nThis shortcut is a function called ``render()``, which lives in the\nmodule ``django.shortcuts``. Most of the time, you'll be using\n``render()`` rather than loading templates and creating ``Context``\nand ``HttpResponse`` objects manually -- unless your employer judges your work\nby total lines of code written, that is.\n\nHere's the ongoing ``current_datetime`` example rewritten to use\n``render()``::\n\n    from django.shortcuts import render\n    import datetime\n\n    def current_datetime(request):\n        now = datetime.datetime.now()\n        return render(request, 'current_datetime.html', {'current_date': now})\n\nWhat a difference! Let's step through the code changes:\n\n* We no longer have to import ``get_template``, ``Template``, ``Context``,\n  or ``HttpResponse``. Instead, we import\n  ``django.shortcuts.render``. The ``import datetime`` remains.\n\n* Within the ``current_datetime`` function, we still calculate ``now``, but\n  the template loading, context creation, template rendering, and\n  ``HttpResponse`` creation are all taken care of by the\n  ``render()`` call. Because ``render()`` returns\n  an ``HttpResponse`` object, we can simply ``return`` that value in the\n  view.\n\nThe first argument to ``render()`` is the request, the second is the name of\nthe template to use. The third argument, if given, should be a dictionary to\nuse in creating a ``Context`` for that template. If you don't provide a third\nargument, ``render()`` will use an empty dictionary.\n\nSubdirectories in get_template()\n--------------------------------\n\nIt can get unwieldy to store all of your templates in a single directory. You\nmight like to store templates in subdirectories of your template directory, and\nthat's fine. In fact, we recommend doing so; some more advanced Django\nfeatures (such as the generic views system, which we cover in\nChapter 11) expect this template layout as a default convention.\n\nStoring templates in subdirectories of your template directory is easy.\nIn your calls to ``get_template()``, just include\nthe subdirectory name and a slash before the template name, like so::\n\n    t = get_template('dateapp/current_datetime.html')\n\nBecause ``render()`` is a small wrapper around ``get_template()``,\nyou can do the same thing with the second argument to ``render()``,\nlike this::\n\n    return render(request, 'dateapp/current_datetime.html', {'current_date': now})\n\nThere's no limit to the depth of your subdirectory tree. Feel free to use\nas many subdirectories as you like.\n\n.. note::\n\n    Windows users, be sure to use forward slashes rather than backslashes.\n    ``get_template()`` assumes a Unix-style file name designation.\n\nThe ``include`` Template Tag\n----------------------------\n\nNow that we've covered the template-loading mechanism, we can introduce a\nbuilt-in template tag that takes advantage of it: ``{% include %}``. This tag\nallows you to include the contents of another template. The argument to the tag\nshould be the name of the template to include, and the template name can be\neither a variable or a hard-coded (quoted) string, in either single or double\nquotes. Anytime you have the same code in multiple templates,\nconsider using an ``{% include %}`` to remove the duplication.\n\nThese two examples include the contents of the template ``nav.html``. The\nexamples are equivalent and illustrate that either single or double quotes\nare allowed::\n\n    {% include 'nav.html' %}\n    {% include \"nav.html\" %}\n\nThis example includes the contents of the template ``includes/nav.html``::\n\n    {% include 'includes/nav.html' %}\n\nThis example includes the contents of the template whose name is contained in\nthe variable ``template_name``::\n\n    {% include template_name %}\n\nAs in ``get_template()``, the file name of the template is determined by adding\nthe template directory from ``TEMPLATE_DIRS`` to the requested template name.\n\nIncluded templates are evaluated with the context of the template\nthat's including them. For example, consider these two templates::\n\n    # mypage.html\n\n    <html>\n    <body>\n    {% include \"includes/nav.html\" %}\n    <h1>{{ title }}</h1>\n    </body>\n    </html>\n\n    # includes/nav.html\n\n    <div id=\"nav\">\n        You are in: {{ current_section }}\n    </div>\n\nIf you render ``mypage.html`` with a context containing ``current_section``,\nthen the variable will be available in the \"included\" template, as you would\nexpect.\n\nIf, in an ``{% include %}`` tag, a template with the given name isn't found,\nDjango will do one of two things:\n\n* If ``DEBUG`` is set to ``True``, you'll see the\n  ``TemplateDoesNotExist`` exception on a Django error page.\n\n* If ``DEBUG`` is set to ``False``, the tag will fail\n  silently, displaying nothing in the place of the tag.\n\nTemplate Inheritance\n====================\n\nOur template examples so far have been tiny HTML snippets, but in the real\nworld, you'll be using Django's template system to create entire HTML pages.\nThis leads to a common Web development problem: across a Web site, how does\none reduce the duplication and redundancy of common page areas, such as\nsitewide navigation?\n\nA classic way of solving this problem is to use *server-side includes*,\ndirectives you can embed within your HTML pages to \"include\" one Web page\ninside another. Indeed, Django supports that approach, with the\n``{% include %}`` template tag just described. But the preferred way of\nsolving this problem with Django is to use a more elegant strategy called\n*template inheritance*.\n\nIn essence, template inheritance lets you build a base \"skeleton\" template that\ncontains all the common parts of your site and defines \"blocks\" that child\ntemplates can override.\n\nLet's see an example of this by creating a more complete template for our\n``current_datetime`` view, by editing the ``current_datetime.html`` file::\n\n    <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n    <html lang=\"en\">\n    <head>\n        <title>The current time</title>\n    </head>\n    <body>\n        <h1>My helpful timestamp site</h1>\n        <p>It is now {{ current_date }}.</p>\n\n        <hr>\n        <p>Thanks for visiting my site.</p>\n    </body>\n    </html>\n\nThat looks just fine, but what happens when we want to create a template for\nanother view -- say, the ``hours_ahead`` view from Chapter 3? If we want again\nto make a nice, valid, full HTML template, we'd create something like::\n\n    <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n    <html lang=\"en\">\n    <head>\n        <title>Future time</title>\n    </head>\n    <body>\n        <h1>My helpful timestamp site</h1>\n        <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>\n\n        <hr>\n        <p>Thanks for visiting my site.</p>\n    </body>\n    </html>\n\nClearly, we've just duplicated a lot of HTML. Imagine if we had a more\ntypical site, including a navigation bar, a few style sheets, perhaps some\nJavaScript -- we'd end up putting all sorts of redundant HTML into each\ntemplate.\n\nThe server-side include solution to this problem is to factor out the\ncommon bits in both templates and save them in separate template snippets,\nwhich are then included in each template. Perhaps you'd store the top\nbit of the template in a file called ``header.html``::\n\n    <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n    <html lang=\"en\">\n    <head>\n\nAnd perhaps you'd store the bottom bit in a file called ``footer.html``::\n\n        <hr>\n        <p>Thanks for visiting my site.</p>\n    </body>\n    </html>\n\nWith an include-based strategy, headers and footers are easy. It's the\nmiddle ground that's messy. In this example, both pages feature a title --\n``<h1>My helpful timestamp site</h1>`` -- but that title can't fit into\n``header.html`` because the ``<title>`` on both pages is different. If we\nincluded the ``<h1>`` in the header, we'd have to include the ``<title>``,\nwhich wouldn't allow us to customize it per page. See where this is going?\n\nDjango's template inheritance system solves these problems. You can think of it\nas an \"inside-out\" version of server-side includes. Instead of defining the\nsnippets that are *common*, you define the snippets that are *different*.\n\nThe first step is to define a *base template* -- a skeleton of your page that\n*child templates* will later fill in. Here's a base template for our ongoing\nexample::\n\n    <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n    <html lang=\"en\">\n    <head>\n        <title>{% block title %}{% endblock %}</title>\n    </head>\n    <body>\n        <h1>My helpful timestamp site</h1>\n        {% block content %}{% endblock %}\n        {% block footer %}\n        <hr>\n        <p>Thanks for visiting my site.</p>\n        {% endblock %}\n    </body>\n    </html>\n\nThis template, which we'll call ``base.html``, defines a simple HTML skeleton\ndocument that we'll use for all the pages on the site. It's the job of child\ntemplates to override, or add to, or leave alone the contents of the blocks.\n(If you're following along, save this file to your template directory as\n``base.html``.)\n\nWe're using a template tag here that you haven't seen before: the\n``{% block %}`` tag. All the ``{% block %}`` tags do is tell the template\nengine that a child template may override those portions of the template.\n\nNow that we have this base template, we can modify our existing\n``current_datetime.html`` template to use it::\n\n    {% extends \"base.html\" %}\n\n    {% block title %}The current time{% endblock %}\n\n    {% block content %}\n    <p>It is now {{ current_date }}.</p>\n    {% endblock %}\n\nWhile we're at it, let's create a template for the ``hours_ahead`` view from\nChapter 3. (If you're following along with code, we'll leave it up to you to\nchange ``hours_ahead`` to use the template system instead of hard-coded HTML.)\nHere's what that could look like::\n\n    {% extends \"base.html\" %}\n\n    {% block title %}Future time{% endblock %}\n\n    {% block content %}\n    <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>\n    {% endblock %}\n\nIsn't this beautiful? Each template contains only the code that's *unique* to\nthat template. No redundancy needed. If you need to make a site-wide design\nchange, just make the change to ``base.html``, and all of the other templates\nwill immediately reflect the change.\n\nHere's how it works. When you load the template ``current_datetime.html``,\nthe template engine sees the ``{% extends %}`` tag, noting that\nthis template is a child template. The engine immediately loads the\nparent template -- in this case, ``base.html``.\n\nAt that point, the template engine notices the three ``{% block %}`` tags\nin ``base.html`` and replaces those blocks with the contents of the child\ntemplate. So, the title we've defined in ``{% block title %}`` will be\nused, as will the ``{% block content %}``.\n\nNote that since the child template doesn't define the ``footer`` block,\nthe template system uses the value from the parent template instead.\nContent within a ``{% block %}`` tag in a parent template is always\nused as a fallback.\n\nInheritance doesn't affect the template context. In other words, any template\nin the inheritance tree will have access to every one of your template\nvariables from the context.\n\nYou can use as many levels of inheritance as needed. One common way of using\ninheritance is the following three-level approach:\n\n1. Create a ``base.html`` template that holds the main look and feel of\n   your site. This is the stuff that rarely, if ever, changes.\n\n2. Create a ``base_SECTION.html`` template for each \"section\" of your site\n   (e.g., ``base_photos.html`` and ``base_forum.html``). These templates\n   extend ``base.html`` and include section-specific styles/design.\n\n3. Create individual templates for each type of page, such as a forum page\n   or a photo gallery. These templates extend the appropriate section\n   template.\n\nThis approach maximizes code reuse and makes it easy to add items to shared\nareas, such as section-wide navigation.\n\nHere are some guidelines for working with template inheritance:\n\n* If you use ``{% extends %}`` in a template, it must be the first\n  template tag in that template. Otherwise, template inheritance won't\n  work.\n\n* Generally, the more ``{% block %}`` tags in your base templates, the\n  better. Remember, child templates don't have to define all parent blocks,\n  so you can fill in reasonable defaults in a number of blocks, and then\n  define only the ones you need in the child templates. It's better to have\n  more hooks than fewer hooks.\n\n* If you find yourself duplicating code in a number of templates, it\n  probably means you should move that code to a ``{% block %}`` in a\n  parent template.\n\n* If you need to get the content of the block from the parent template,\n  use ``{{ block.super }}``, which is a \"magic\" variable providing the\n  rendered text of the parent template. This is useful if you want to add\n  to the contents of a parent block instead of completely overriding it.\n\n* You may not define multiple ``{% block %}`` tags with the same name in\n  the same template. This limitation exists because a block tag works in\n  \"both\" directions. That is, a block tag doesn't just provide a hole to\n  fill, it also defines the content that fills the hole in the *parent*.\n  If there were two similarly named ``{% block %}`` tags in a template,\n  that template's parent wouldn't know which one of the blocks' content to\n  use.\n\n* The template name you pass to ``{% extends %}`` is loaded using the same\n  method that ``get_template()`` uses. That is, the template name is\n  appended to your ``TEMPLATE_DIRS`` setting.\n\n* In most cases, the argument to ``{% extends %}`` will be a string, but it\n  can also be a variable, if you don't know the name of the parent template\n  until runtime. This lets you do some cool, dynamic stuff.\n\nWhat's next?\n============\n\nYou now have the basics of Django's template system under your belt. What's next?\n\nMany modern Web sites are *database-driven*: the content of the Web site is\nstored in a relational database. This allows a clean separation of data and logic\n(in the same way views and templates allow the separation of logic and display.)\n\nThe :doc:`next chapter <chapter05>` covers the tools Django gives you to\ninteract with a database.\n"
  },
  {
    "path": "Python/DjangoBook/chapter05.rst",
    "content": "=================\nChapter 5: Models\n=================\n\nIn Chapter 3, we covered the fundamentals of building dynamic Web sites\nwith Django: setting up views and URLconfs. As we explained, a view is\nresponsible for doing *some arbitrary logic*, and then returning a response. In\none of the examples, our arbitrary logic was to calculate the current date and\ntime.\n\nIn modern Web applications, the arbitrary logic often involves interacting\nwith a database. Behind the scenes, a *database-driven Web site* connects to\na database server, retrieves some data out of it, and displays that data on a\nWeb page. The site might also provide ways for site visitors to populate the\ndatabase on their own.\n\nMany complex Web sites provide some combination of the two. Amazon.com, for\ninstance, is a great example of a database-driven site. Each product page is\nessentially a query into Amazon's product database formatted as HTML, and when\nyou post a customer review, it gets inserted into the database of reviews.\n\nDjango is well suited for making database-driven Web sites, because it comes\nwith easy yet powerful tools for performing database queries using Python. This\nchapter explains that functionality: Django's database layer.\n\n(Note: While it's not strictly necessary to know basic relational database\ntheory and SQL in order to use Django's database layer, it's highly\nrecommended. An introduction to those concepts is beyond the scope of this\nbook, but keep reading even if you're a database newbie. You'll probably be\nable to follow along and grasp concepts based on the context.)\n\nThe \"Dumb\" Way to Do Database Queries in Views\n==============================================\n\nJust as Chapter 3 detailed a \"dumb\" way to produce output within a\nview (by hard-coding the text directly within the view), there's a \"dumb\" way to\nretrieve data from a database in a view. It's simple: just use any existing\nPython library to execute an SQL query and do something with the results.\n\nIn this example view, we use the ``MySQLdb`` library (available via\nhttp://www.djangoproject.com/r/python-mysql/) to connect to a MySQL database,\nretrieve some records, and feed them to a template for display as a Web page::\n\n    from django.shortcuts import render\n    import MySQLdb\n\n    def book_list(request):\n        db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost')\n        cursor = db.cursor()\n        cursor.execute('SELECT name FROM books ORDER BY name')\n        names = [row[0] for row in cursor.fetchall()]\n        db.close()\n        return render(request, 'book_list.html', {'names': names})\n\n.. SL Tested ok\n\nThis approach works, but some problems should jump out at you immediately:\n\n* We're hard-coding the database connection parameters. Ideally, these\n  parameters would be stored in the Django configuration.\n\n* We're having to write a fair bit of boilerplate code: creating a\n  connection, creating a cursor, executing a statement, and closing the\n  connection. Ideally, all we'd have to do is specify which results we\n  wanted.\n\n* It ties us to MySQL. If, down the road, we switch from MySQL to\n  PostgreSQL, we'll have to use a different database adapter (e.g.,\n  ``psycopg`` rather than ``MySQLdb``), alter the connection parameters,\n  and -- depending on the nature of the SQL statement -- possibly rewrite\n  the SQL. Ideally, the database server we're using would be abstracted, so\n  that a database server change could be made in a single place. (This\n  feature is particularly relevant if you're building an open-source Django\n  application that you want to be used by as many people as possible.)\n\nAs you might expect, Django's database layer aims to solve these problems.\nHere's a sneak preview of how the previous view can be rewritten using Django's\ndatabase API::\n\n    from django.shortcuts import render\n    from mysite.books.models import Book\n\n    def book_list(request):\n        books = Book.objects.order_by('name')\n        return render(request, 'book_list.html', {'books': books})\n\nWe'll explain this code a little later in the chapter. For now, just get a\nfeel for how it looks.\n\nThe MTV (or MVC) Development Pattern\n====================================\n\nBefore we delve into any more code, let's take a moment to consider the overall\ndesign of a database-driven Django Web application.\n\nAs we mentioned in previous chapters, Django is designed to encourage loose\ncoupling and strict separation between pieces of an application. If you follow\nthis philosophy, it's easy to make changes to one particular piece of the\napplication without affecting the other pieces. In view functions, for\ninstance, we discussed the importance of separating the business logic from the\npresentation logic by using a template system. With the database layer, we're\napplying that same philosophy to data access logic.\n\nThose three pieces together -- data access logic, business logic, and\npresentation logic -- comprise a concept that's sometimes called the\n*Model-View-Controller* (MVC) pattern of software architecture. In this\npattern, \"Model\" refers to the data access layer, \"View\" refers to the part of\nthe system that selects what to display and how to display it, and\n\"Controller\" refers to the part of the system that decides which view to use,\ndepending on user input, accessing the model as needed.\n\n.. admonition:: Why the Acronym?\n\n    The goal of explicitly defining patterns such as MVC is mostly to\n    streamline communication among developers. Instead of having to tell your\n    coworkers, \"Let's make an abstraction of the data access, then let's have a\n    separate layer that handles data display, and let's put a layer in the\n    middle that regulates this,\" you can take advantage of a shared vocabulary\n    and say, \"Let's use the MVC pattern here.\"\n\nDjango follows this MVC pattern closely enough that it can be called an MVC\nframework. Here's roughly how the M, V, and C break down in Django:\n\n* *M*, the data-access portion, is handled by Django's database layer,\n  which is described in this chapter.\n\n* *V*, the portion that selects which data to display and how to display\n  it, is handled by views and templates.\n\n* *C*, the portion that delegates to a view depending on user input, is\n  handled by the framework itself by following your URLconf and calling the\n  appropriate Python function for the given URL.\n\nBecause the \"C\" is handled by the framework itself and most of the excitement\nin Django happens in models, templates and views, Django has been referred to\nas an *MTV framework*. In the MTV development pattern,\n\n* *M* stands for \"Model,\" the data access layer. This layer contains\n  anything and everything about the data: how to access it, how to validate\n  it, which behaviors it has, and the relationships between the data.\n\n* *T* stands for \"Template,\" the presentation layer. This layer contains\n  presentation-related decisions: how something should be displayed on a\n  Web page or other type of document.\n\n* *V* stands for \"View,\" the business logic layer. This layer contains the\n  logic that access the model and defers to the appropriate template(s).\n  You can think of it as the bridge between models and templates.\n\nIf you're familiar with other MVC Web-development frameworks, such as Ruby on\nRails, you may consider Django views to be the \"controllers\" and Django\ntemplates to be the \"views.\" This is an unfortunate confusion brought about by\ndiffering interpretations of MVC. In Django's interpretation of MVC, the \"view\"\ndescribes the data that gets presented to the user; it's not necessarily just\n*how* the data looks, but *which* data is presented. In contrast, Ruby on Rails\nand similar frameworks suggest that the controller's job includes deciding\nwhich data gets presented to the user, whereas the view is strictly *how* the\ndata looks, not *which* data is presented.\n\nNeither interpretation is more \"correct\" than the other. The important thing is\nto understand the underlying concepts.\n\nConfiguring the Database\n========================\n\nWith all of that philosophy in mind, let's start exploring Django's database\nlayer. First, we need to take care of some initial configuration; we need to\ntell Django which database server to use and how to connect to it.\n\nWe'll assume you've set up a database server, activated it, and created a\ndatabase within it (e.g., using a ``CREATE DATABASE`` statement). If you're\nusing SQLite, no such setup is required, because SQLite uses standalone files\non the filesystem to store its data.\n\nAs with ``TEMPLATE_DIRS`` in the previous chapter, database configuration lives in\nthe Django settings file, called ``settings.py`` by default. Edit that file and\nlook for the database settings::\n\n    DATABASES = {\n        'default': {\n            'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.\n            'NAME': '',                      # Or path to database file if using sqlite3.\n            'USER': '',                      # Not used with sqlite3.\n            'PASSWORD': '',                  # Not used with sqlite3.\n            'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.\n            'PORT': '',                      # Set to empty string for default. Not used with sqlite3.\n        }\n    }\n\nHere's a rundown of each setting.\n\n* ``ENGINE`` tells Django which database engine to use. If you're\n  using a database with Django, ``ENGINE`` must be set to one of\n  the strings shown in Table 5-1.\n\n  .. table:: Table 5-1. Database Engine Settings\n\n      ============================================ ============ ================================================\n      Setting                                      Database     Required Adapter\n      ============================================ ============ ================================================\n      ``django.db.backends.postgresql_psycopg2``   PostgreSQL   ``psycopg`` version 2.x,\n                                                                http://www.djangoproject.com/r/python-pgsql/.\n\n      ``django.db.backends.mysql``                 MySQL        ``MySQLdb``,\n                                                                http://www.djangoproject.com/r/python-mysql/.\n\n      ``django.db.backends.sqlite3``               SQLite       No adapter needed.\n\n      ``django.db.backends.oracle``                Oracle       ``cx_Oracle``,\n                                                                http://www.djangoproject.com/r/python-oracle/.\n      ============================================ ============ ================================================\n\n  Note that for whichever database back-end you use, you'll need to download\n  and install the appropriate database adapter. Each one is available for\n  free on the Web; just follow the links in the \"Required Adapter\" column\n  in Table 5-1. If you're on Linux, your distribution's package-management\n  system might offer convenient packages. (Look for packages called\n  ``python-postgresql`` or ``python-psycopg``, for example.)\n\n  Example::\n\n      'ENGINE': 'django.db.backends.postgresql_psycopg2',\n\n* ``NAME`` tells Django the name of your database. For example::\n\n      'NAME': 'mydb',\n\n  If you're using SQLite, specify the full filesystem path to the database\n  file on your filesystem. For example::\n\n      'NAME': '/home/django/mydata.db',\n\n  As for where you put that SQLite database, we're using the ``/home/django``\n  directory in this example, but you should pick a directory that works\n  best for you.\n\n* ``USER`` tells Django which username to use when connecting to\n  your database. For example: If you're using SQLite, leave this blank.\n\n* ``PASSWORD`` tells Django which password to use when connecting\n  to your database. If you're using SQLite or have an empty password, leave\n  this blank.\n\n* ``HOST`` tells Django which host to use when connecting to your\n  database. If your database is on the same computer as your Django\n  installation (i.e., localhost), leave this blank. If you're using SQLite,\n  leave this blank.\n\n  MySQL is a special case here. If this value starts with a forward slash\n  (``'/'``) and you're using MySQL, MySQL will connect via a Unix socket to\n  the specified socket, for example::\n\n      'HOST': '/var/run/mysql',\n\n.. SL The usual convention is for the socket to be named 'mysql.sock' or similar,\n.. SL so would '/var/run/mysql.sock' be a better example?\n\n  If you're using MySQL and this value *doesn't* start with a forward\n  slash, then this value is assumed to be the host.\n\n* ``PORT`` tells Django which port to use when connecting to your\n  database. If you're using SQLite, leave this blank. Otherwise, if you\n  leave this blank, the underlying database adapter will use whichever\n  port is default for your given database server. In most cases, the\n  default port is fine, so you can leave this blank.\n\nOnce you've entered those settings and saved ``settings.py``, it's a good idea\nto test your configuration. To do this, run ``python manage.py shell`` as in\nthe last chapter, from within the ``mysite`` project directory. (As we pointed\nout last chapter ``manage.py shell`` is a way to run the Python interpreter\nwith the correct Django settings activated. This is necessary in our case,\nbecause Django needs to know which settings file to use in order to get your\ndatabase connection information.)\n\nIn the shell, type these commands to test your database configuration::\n\n    >>> from django.db import connection\n    >>> cursor = connection.cursor()\n\nIf nothing happens, then your database is configured properly. Otherwise, check\nthe error message for clues about what's wrong. Table 5-2 shows some common errors.\n\n.. table:: Table 5-2. Database Configuration Error Messages\n\n    =========================================================  ===============================================\n    Error Message                                              Solution\n    =========================================================  ===============================================\n    You haven't set the ENGINE setting yet.                    Set the ``ENGINE`` setting to\n                                                               something other than an empty string. Valid\n                                                               values are in Table 5-1.\n    Environment variable DJANGO_SETTINGS_MODULE is undefined.  Run the command ``python manage.py shell``\n                                                               rather than ``python``.\n    Error loading _____ module: No module named _____.         You haven't installed the appropriate\n                                                               database-specific adapter (e.g., ``psycopg``\n                                                               or ``MySQLdb``). Adapters are *not* bundled\n                                                               with Django, so it's your responsibility to\n                                                               download and install them on your own.\n    _____ isn't an available database backend.                 Set your ``ENGINE`` setting to\n                                                               one of the valid engine settings described\n                                                               previously. Perhaps you made a typo?\n    database _____ does not exist                              Change the ``NAME`` setting to\n                                                               point to a database that exists, or\n                                                               execute the appropriate\n                                                               ``CREATE DATABASE`` statement in order to\n                                                               create it.\n    role _____ does not exist                                  Change the ``USER`` setting to point\n                                                               to a user that exists, or create the user\n                                                               in your database.\n    could not connect to server                                Make sure ``HOST`` and\n                                                               ``PORT`` are set correctly, and\n                                                               make sure the database server is running.\n    =========================================================  ===============================================\n\nYour First App\n==============\n\nNow that you've verified the connection is working, it's time to create a\n*Django app* -- a bundle of Django code, including models and views, that\nlives together in a single Python package and represents a full Django\napplication.\n\nIt's worth explaining the terminology here, because this tends to trip up\nbeginners. We'd already created a *project*, in Chapter 2, so what's the\ndifference between a *project* and an *app*? The difference is that of\nconfiguration vs. code:\n\n* A project is an instance of a certain set of Django apps, plus the\n  configuration for those apps.\n\n  Technically, the only requirement of a project is that it supplies a\n  settings file, which defines the database connection information, the\n  list of installed apps, the ``TEMPLATE_DIRS``, and so forth.\n\n* An app is a portable set of Django functionality, usually including\n  models and views, that lives together in a single Python package.\n\n  For example, Django comes with a number of apps, such as a commenting\n  system and an automatic admin interface. A key thing to note about these\n  apps is that they're portable and reusable across multiple projects.\n\nThere are very few hard-and-fast rules about how you fit your Django code into\nthis scheme. If you're building a simple Web site, you may use only a single\napp. If you're building a complex Web site with several unrelated pieces such\nas an e-commerce system and a message board, you'll probably want to split\nthose into separate apps so that you'll be able to reuse them individually in\nthe future.\n\nIndeed, you don't necessarily need to create apps at all, as evidenced by the\nexample view functions we've created so far in this book. In those cases, we\nsimply created a file called ``views.py``, filled it with view functions, and\npointed our URLconf at those functions. No \"apps\" were needed.\n\nHowever, there's one requirement regarding the app convention: if you're using\nDjango's database layer (models), you must create a Django app. Models must\nlive within apps. Thus, in order to start writing our models, we'll need to\ncreate a new app.\n\nWithin the ``mysite`` project directory, type this command to create a\n``books`` app::\n\n    python manage.py startapp books\n\nThis command does not produce any output, but it does create a ``books``\ndirectory within the ``mysite`` directory. Let's look at the contents\nof that directory::\n\n    books/\n        __init__.py\n        models.py\n        tests.py\n        views.py\n\nThese files will contain the models and views for this app.\n\nHave a look at ``models.py`` and ``views.py`` in your favorite text editor.\nBoth files are empty, except for comments and an import in ``models.py``. This\nis the blank slate for your Django app.\n\nDefining Models in Python\n=========================\n\nAs we discussed earlier in this chapter, the \"M\" in \"MTV\" stands for \"Model.\" A\nDjango model is a description of the data in your database, represented as\nPython code. It's your data layout -- the equivalent of your SQL ``CREATE\nTABLE`` statements -- except it's in Python instead of SQL, and it includes\nmore than just database column definitions. Django uses a model to execute SQL\ncode behind the scenes and return convenient Python data structures representing\nthe rows in your database tables. Django also uses models to represent\nhigher-level concepts that SQL can't necessarily handle.\n\nIf you're familiar with databases, your immediate thought might be, \"Isn't it\nredundant to define data models in Python instead of in SQL?\" Django works the\nway it does for several reasons:\n\n* Introspection requires overhead and is imperfect. In order to provide\n  convenient data-access APIs, Django needs to know the\n  database layout *somehow*, and there are two ways of accomplishing this.\n  The first way would be to explicitly describe the data in Python, and the\n  second way would be to introspect the database at runtime to determine\n  the data models.\n\n  This second way seems cleaner, because the metadata about your tables\n  lives in only one place, but it introduces a few problems. First,\n  introspecting a database at runtime obviously requires overhead. If the\n  framework had to introspect the database each time it processed a\n  request, or even only when the Web server was initialized, this would\n  incur an unacceptable level of overhead. (While some believe that level\n  of overhead is acceptable, Django's developers aim to trim as much\n  framework overhead as possible.) Second, some databases, notably older\n  versions of MySQL, do not store sufficient metadata for accurate and\n  complete introspection.\n\n* Writing Python is fun, and keeping everything in Python limits the number\n  of times your brain has to do a \"context switch.\" It helps productivity\n  if you keep yourself in a single programming environment/mentality for as\n  long as possible. Having to write SQL, then Python, and then SQL again is\n  disruptive.\n\n* Having data models stored as code rather than in your database makes it\n  easier to keep your models under version control. This way, you can\n  easily keep track of changes to your data layouts.\n\n* SQL allows for only a certain level of metadata about a data layout. Most\n  database systems, for example, do not provide a specialized data type for\n  representing email addresses or URLs. Django models do. The advantage of\n  higher-level data types is higher productivity and more reusable code.\n\n* SQL is inconsistent across database platforms. If you're distributing a\n  Web application, for example, it's much more pragmatic to distribute a\n  Python module that describes your data layout than separate sets of\n  ``CREATE TABLE`` statements for MySQL, PostgreSQL, and SQLite.\n\nA drawback of this approach, however, is that it's possible for the Python code\nto get out of sync with what's actually in the database. If you make changes to\na Django model, you'll need to make the same changes inside your database to\nkeep your database consistent with the model. We'll discuss some strategies for\nhandling this problem later in this chapter.\n\nFinally, we should note that Django includes a utility that can generate models\nby introspecting an existing database. This is useful for quickly getting up\nand running with legacy data. We'll cover this in Chapter 18.\n\nYour First Model\n================\n\nAs an ongoing example in this chapter and the next chapter, we'll focus on a\nbasic book/author/publisher data layout. We use this as our example because the\nconceptual relationships between books, authors, and publishers are well known,\nand this is a common data layout used in introductory SQL textbooks. You're\nalso reading a book that was written by authors and produced by a publisher!\n\nWe'll suppose the following concepts, fields, and relationships:\n\n* An author has a first name, a last name and an email address.\n\n* A publisher has a name, a street address, a city, a state/province, a\n  country, and a Web site.\n\n* A book has a title and a publication date. It also has one or more\n  authors (a many-to-many relationship with authors) and a single publisher\n  (a one-to-many relationship -- aka foreign key -- to publishers).\n\nThe first step in using this database layout with Django is to express it as\nPython code. In the ``models.py`` file that was created by the ``startapp``\ncommand, enter the following::\n\n    from django.db import models\n\n    class Publisher(models.Model):\n        name = models.CharField(max_length=30)\n        address = models.CharField(max_length=50)\n        city = models.CharField(max_length=60)\n        state_province = models.CharField(max_length=30)\n        country = models.CharField(max_length=50)\n        website = models.URLField()\n\n    class Author(models.Model):\n        first_name = models.CharField(max_length=30)\n        last_name = models.CharField(max_length=40)\n        email = models.EmailField()\n\n    class Book(models.Model):\n        title = models.CharField(max_length=100)\n        authors = models.ManyToManyField(Author)\n        publisher = models.ForeignKey(Publisher)\n        publication_date = models.DateField()\n\nLet's quickly examine this code to cover the basics. The first thing to notice\nis that each model is represented by a Python class that is a subclass of\n``django.db.models.Model``. The parent class, ``Model``, contains all the\nmachinery necessary to make these objects capable of interacting with a\ndatabase -- and that leaves our models responsible solely for defining their\nfields, in a nice and compact syntax. Believe it or not, this is all the code\nwe need to write to have basic data access with Django.\n\nEach model generally corresponds to a single database table, and each attribute\non a model generally corresponds to a column in that database table. The\nattribute name corresponds to the column's name, and the type of field (e.g.,\n``CharField``) corresponds to the database column type (e.g., ``varchar``). For\nexample, the ``Publisher`` model is equivalent to the following table (assuming\nPostgreSQL ``CREATE TABLE`` syntax)::\n\n    CREATE TABLE \"books_publisher\" (\n        \"id\" serial NOT NULL PRIMARY KEY,\n        \"name\" varchar(30) NOT NULL,\n        \"address\" varchar(50) NOT NULL,\n        \"city\" varchar(60) NOT NULL,\n        \"state_province\" varchar(30) NOT NULL,\n        \"country\" varchar(50) NOT NULL,\n        \"website\" varchar(200) NOT NULL\n    );\n\nIndeed, Django can generate that ``CREATE TABLE`` statement automatically, as\nwe'll show you in a moment.\n\nThe exception to the one-class-per-database-table rule is the case of\nmany-to-many relationships. In our example models, ``Book`` has a\n``ManyToManyField`` called ``authors``. This designates that a book has one or\nmany authors, but the ``Book`` database table doesn't get an ``authors``\ncolumn. Rather, Django creates an additional table -- a many-to-many \"join\ntable\" -- that handles the mapping of books to authors.\n\nFor a full list of field types and model syntax options, see Appendix B.\n\nFinally, note we haven't explicitly defined a primary key in any of these\nmodels. Unless you instruct it otherwise, Django automatically gives every\nmodel an auto-incrementing integer primary key field called ``id``. Each Django\nmodel is required to have a single-column primary key.\n\nInstalling the Model\n====================\n\nWe've written the code; now let's create the tables in our database. In order\nto do that, the first step is to *activate* these models in our Django project.\nWe do that by adding the ``books`` app to the list of \"installed apps\" in the\nsettings file.\n\nEdit the ``settings.py`` file again, and look for the ``INSTALLED_APPS``\nsetting. ``INSTALLED_APPS`` tells Django which apps are activated for a given\nproject. By default, it looks something like this::\n\n    INSTALLED_APPS = (\n        'django.contrib.auth',\n        'django.contrib.contenttypes',\n        'django.contrib.sessions',\n        'django.contrib.sites',\n    )\n\nTemporarily comment out all four of those strings by putting a hash character\n(``#``) in front of them. (They're included by default as a common-case\nconvenience, but we'll activate and discuss them in subsequent chapters.)\nWhile you're at it, comment out the default ``MIDDLEWARE_CLASSES`` setting, too;\nthe default values in ``MIDDLEWARE_CLASSES`` depend on some of the apps we\njust commented out. Then, add  ``'mysite.books'`` to the ``INSTALLED_APPS``\nlist, so the setting ends up looking like this::\n\n    MIDDLEWARE_CLASSES = (\n        # 'django.middleware.common.CommonMiddleware',\n        # 'django.contrib.sessions.middleware.SessionMiddleware',\n        # 'django.contrib.auth.middleware.AuthenticationMiddleware',\n    )\n\n    INSTALLED_APPS = (\n        # 'django.contrib.auth',\n        # 'django.contrib.contenttypes',\n        # 'django.contrib.sessions',\n        # 'django.contrib.sites',\n        'mysite.books',\n    )\n\n(As we mentioned last chapter when setting ``TEMPLATE_DIRS``, you'll need to be\nsure to include the trailing comma in ``INSTALLED_APPS``, because it's a\nsingle-element tuple. By the way, this book's authors prefer to put a comma\nafter *every* element of a tuple, regardless of whether the tuple has only a\nsingle element. This avoids the issue of forgetting commas, and there's no\npenalty for using that extra comma.)\n\n``'mysite.books'`` refers to the ``books`` app we're working on. Each app in\n``INSTALLED_APPS`` is represented by its full Python path -- that is, the path\nof packages, separated by dots, leading to the app package.\n\nNow that the Django app has been activated in the settings file, we can create\nthe database tables in our database. First, let's validate the models by\nrunning this command::\n\n    python manage.py validate\n\n.. SL Tested ok\n\nThe ``validate`` command checks whether your models' syntax and logic are\ncorrect. If all is well, you'll see the message ``0 errors found``. If you\ndon't, make sure you typed in the model code correctly. The error output should\ngive you helpful information about what was wrong with the code.\n\nAny time you think you have problems with your models, run\n``python manage.py validate``. It tends to catch all the common model problems.\n\nIf your models are valid, run the following command for Django to generate\n``CREATE TABLE`` statements for your models in the ``books`` app (with colorful\nsyntax highlighting available, if you're using Unix)::\n\n    python manage.py sqlall books\n\nIn this command, ``books`` is the name of the app. It's what you specified when\nyou ran the command ``manage.py startapp``. When you run the command, you\nshould see something like this::\n\n    BEGIN;\n    CREATE TABLE \"books_publisher\" (\n        \"id\" serial NOT NULL PRIMARY KEY,\n        \"name\" varchar(30) NOT NULL,\n        \"address\" varchar(50) NOT NULL,\n        \"city\" varchar(60) NOT NULL,\n        \"state_province\" varchar(30) NOT NULL,\n        \"country\" varchar(50) NOT NULL,\n        \"website\" varchar(200) NOT NULL\n    )\n    ;\n    CREATE TABLE \"books_author\" (\n        \"id\" serial NOT NULL PRIMARY KEY,\n        \"first_name\" varchar(30) NOT NULL,\n        \"last_name\" varchar(40) NOT NULL,\n        \"email\" varchar(75) NOT NULL\n    )\n    ;\n    CREATE TABLE \"books_book\" (\n        \"id\" serial NOT NULL PRIMARY KEY,\n        \"title\" varchar(100) NOT NULL,\n        \"publisher_id\" integer NOT NULL REFERENCES \"books_publisher\" (\"id\") DEFERRABLE INITIALLY DEFERRED,\n        \"publication_date\" date NOT NULL\n    )\n    ;\n    CREATE TABLE \"books_book_authors\" (\n        \"id\" serial NOT NULL PRIMARY KEY,\n        \"book_id\" integer NOT NULL REFERENCES \"books_book\" (\"id\") DEFERRABLE INITIALLY DEFERRED,\n        \"author_id\" integer NOT NULL REFERENCES \"books_author\" (\"id\") DEFERRABLE INITIALLY DEFERRED,\n        UNIQUE (\"book_id\", \"author_id\")\n    )\n    ;\n    CREATE INDEX \"books_book_publisher_id\" ON \"books_book\" (\"publisher_id\");\n    COMMIT;\n\n.. SL Tested ok (sqlall output for postgres matches that shown here)\n\nNote the following:\n\n* Table names are automatically generated by combining the name of the app\n  (``books``) and the lowercase name of the model (``publisher``,\n  ``book``, and ``author``). You can override this behavior, as detailed\n  in Appendix B.\n\n* As we mentioned earlier, Django adds a primary key for each table\n  automatically -- the ``id`` fields. You can override this, too.\n\n* By convention, Django appends ``\"_id\"`` to the foreign key field name. As\n  you might have guessed, you can override this behavior, too.\n\n* The foreign key relationship is made explicit by a ``REFERENCES``\n  statement.\n\n* These ``CREATE TABLE`` statements are tailored to the database you're\n  using, so database-specific field types such as ``auto_increment``\n  (MySQL), ``serial`` (PostgreSQL), or ``integer primary key`` (SQLite) are\n  handled for you automatically. The same goes for quoting of column names\n  (e.g., using double quotes or single quotes). This example output is in\n  PostgreSQL syntax.\n\nThe ``sqlall`` command doesn't actually create the tables or otherwise touch\nyour database -- it just prints output to the screen so you can see what SQL\nDjango would execute if you asked it. If you wanted to, you could copy and\npaste this SQL into your database client, or use Unix pipes to pass it\ndirectly (e.g., ``python manage.py sqlall books | psql mydb``). However, Django\nprovides an easier way of committing the SQL to the database: the ``syncdb``\ncommand::\n\n    python manage.py syncdb\n\nRun that command, and you'll see something like this::\n\n    Creating table books_publisher\n    Creating table books_author\n    Creating table books_book\n    Installing index for books.Book model\n\n.. SL Tested ok\n\nThe ``syncdb`` command is a simple \"sync\" of your models to your database. It\nlooks at all of the models in each app in your ``INSTALLED_APPS`` setting,\nchecks the database to see whether the appropriate tables exist yet, and\ncreates the tables if they don't yet exist. Note that ``syncdb`` does *not*\nsync changes in models or deletions of models; if you make a change to a model\nor delete a model, and you want to update the database, ``syncdb`` will not\nhandle that. (More on this in the \"Making Changes to a Database Schema\" section\ntoward the end of this chapter.)\n\nIf you run ``python manage.py syncdb`` again, nothing happens, because you\nhaven't added any models to the ``books`` app or added any apps to\n``INSTALLED_APPS``. Ergo, it's always safe to run ``python manage.py syncdb``\n-- it won't clobber things.\n\nIf you're interested, take a moment to dive into your database server's\ncommand-line client and see the database tables Django created. You can\nmanually run the command-line client (e.g., ``psql`` for PostgreSQL) or\nyou can run the command ``python manage.py dbshell``, which will figure out\nwhich command-line client to run, depending on your ``DATABASE_SERVER``\nsetting. The latter is almost always more convenient.\n\nBasic Data Access\n=================\n\nOnce you've created a model, Django automatically provides a high-level Python\nAPI for working with those models. Try it out by running\n``python manage.py shell`` and typing the following::\n\n    >>> from books.models import Publisher\n    >>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue',\n    ...     city='Berkeley', state_province='CA', country='U.S.A.',\n    ...     website='http://www.apress.com/')\n    >>> p1.save()\n    >>> p2 = Publisher(name=\"O'Reilly\", address='10 Fawcett St.',\n    ...     city='Cambridge', state_province='MA', country='U.S.A.',\n    ...     website='http://www.oreilly.com/')\n    >>> p2.save()\n    >>> publisher_list = Publisher.objects.all()\n    >>> publisher_list\n    [<Publisher: Publisher object>, <Publisher: Publisher object>]\n\n.. SL Tested ok\n\nThese few lines of code accomplish quite a bit. Here are the highlights:\n\n* First, we import our ``Publisher`` model class. This lets us interact\n  with the database table that contains publishers.\n\n* We create a ``Publisher`` object by instantiating it with values for\n  each field -- ``name``, ``address``, etc.\n\n* To save the object to the database, call its ``save()`` method. Behind\n  the scenes, Django executes an SQL ``INSERT`` statement here.\n\n* To retrieve publishers from the database, use the attribute\n  ``Publisher.objects``, which you can think of as a set of all publishers.\n  Fetch a list of *all* ``Publisher`` objects in the database with the\n  statement ``Publisher.objects.all()``. Behind the scenes, Django executes\n  an SQL ``SELECT`` statement here.\n\nOne thing is worth mentioning, in case it wasn't clear from this example. When\nyou're creating objects using the Django model API, Django doesn't save the\nobjects to the database until you call the ``save()`` method::\n\n    p1 = Publisher(...)\n    # At this point, p1 is not saved to the database yet!\n    p1.save()\n    # Now it is.\n\nIf you want to create an object and save it to the database in a single step,\nuse the ``objects.create()`` method. This example is equivalent to the example\nabove::\n\n    >>> p1 = Publisher.objects.create(name='Apress',\n    ...     address='2855 Telegraph Avenue',\n    ...     city='Berkeley', state_province='CA', country='U.S.A.',\n    ...     website='http://www.apress.com/')\n    >>> p2 = Publisher.objects.create(name=\"O'Reilly\",\n    ...     address='10 Fawcett St.', city='Cambridge',\n    ...     state_province='MA', country='U.S.A.',\n    ...     website='http://www.oreilly.com/')\n    >>> publisher_list = Publisher.objects.all()\n    >>> publisher_list\n\n.. SL Tested ok\n\nNaturally, you can do quite a lot with the Django database API -- but first,\nlet's take care of a small annoyance.\n\nAdding Model String Representations\n===================================\n\nWhen we printed out the list of publishers, all we got was this\nunhelpful display that makes it difficult to tell the ``Publisher`` objects\napart::\n\n    [<Publisher: Publisher object>, <Publisher: Publisher object>]\n\nWe can fix this easily by adding a method called ``__unicode__()`` to our\n``Publisher`` class. A ``__unicode__()`` method tells Python how to display the\n\"unicode\" representation of an object. You can see this in action by adding a\n``__unicode__()`` method to the three models:\n\n.. parsed-literal::\n\n    from django.db import models\n\n    class Publisher(models.Model):\n        name = models.CharField(max_length=30)\n        address = models.CharField(max_length=50)\n        city = models.CharField(max_length=60)\n        state_province = models.CharField(max_length=30)\n        country = models.CharField(max_length=50)\n        website = models.URLField()\n\n        **def __unicode__(self):**\n            **return self.name**\n\n    class Author(models.Model):\n        first_name = models.CharField(max_length=30)\n        last_name = models.CharField(max_length=40)\n        email = models.EmailField()\n\n        **def __unicode__(self):**\n            **return u'%s %s' % (self.first_name, self.last_name)**\n\n    class Book(models.Model):\n        title = models.CharField(max_length=100)\n        authors = models.ManyToManyField(Author)\n        publisher = models.ForeignKey(Publisher)\n        publication_date = models.DateField()\n\n        **def __unicode__(self):**\n            **return self.title**\n\nAs you can see, a ``__unicode__()`` method can do whatever it needs to do in order\nto return a representation of an object. Here, the ``__unicode__()`` methods for\n``Publisher`` and ``Book`` simply return the object's name and title,\nrespectively, but the ``__unicode__()`` for ``Author`` is slightly more complex --\nit pieces together the ``first_name`` and ``last_name`` fields, separated by a\nspace.\n\nThe only requirement for ``__unicode__()`` is that it return a Unicode object.\nIf ``__unicode__()`` doesn't return a Unicode object -- if it returns, say, an\ninteger -- then Python will raise a ``TypeError`` with a message like\n``\"coercing to Unicode: need string or buffer, int found\"``.\n\n.. admonition:: Unicode objects\n\n    What are Unicode objects?\n\n    You can think of a Unicode object as a Python string that can handle more\n    than a million different types of characters, from accented versions of\n    Latin characters to non-Latin characters to curly quotes and obscure\n    symbols.\n\n    Normal Python strings are *encoded*, which means they use an encoding such\n    as ASCII, ISO-8859-1 or UTF-8. If you're storing fancy characters (anything\n    beyond the standard 128 ASCII characters such as 0-9 and A-Z) in a normal\n    Python string, you have to keep track of which encoding your string is\n    using, or the fancy characters might appear messed up when they're\n    displayed or printed. Problems occur when you have data that's stored in\n    one encoding and you try to combine it with data in a different encoding,\n    or you try to display it in an application that assumes a certain encoding.\n    We've all seen Web pages and e-mails that are littered with \"??? ??????\"\n    or other characters in odd places; that generally suggests there's an\n    encoding problem.\n\n    Unicode objects, however, have no encoding; they use a consistent,\n    universal set of characters called, well, \"Unicode.\" When you deal with\n    Unicode objects in Python, you can mix and match them safely without having\n    to worry about encoding issues.\n\n    Django uses Unicode objects throughout the framework. Model objects are\n    retrieved as Unicode objects, views interact with Unicode data, and\n    templates are rendered as Unicode. Generally, you won't have to worry about\n    making sure your encodings are right; things should just work.\n\n    Note that this has been a *very* high-level, dumbed down overview of\n    Unicode objects, and you owe it to yourself to learn more about the topic.\n    A good place to start is http://www.joelonsoftware.com/articles/Unicode.html .\n\nFor the ``__unicode__()`` changes to take effect, exit out of the Python shell\nand enter it again with ``python manage.py shell``. (This is the simplest way\nto make code changes take effect.) Now the list of ``Publisher`` objects is\nmuch easier to understand::\n\n    >>> from books.models import Publisher\n    >>> publisher_list = Publisher.objects.all()\n    >>> publisher_list\n    [<Publisher: Apress>, <Publisher: O'Reilly>]\n\n.. SL Tested ok\n\nMake sure any model you define has a ``__unicode__()`` method -- not only for\nyour own convenience when using the interactive interpreter, but also because\nDjango uses the output of ``__unicode__()`` in several places when it needs to\ndisplay objects.\n\nFinally, note that ``__unicode__()`` is a good example of adding *behavior* to\nmodels. A Django model describes more than the database table layout for an\nobject; it also describes any functionality that object knows how to do.\n``__unicode__()`` is one example of such functionality -- a model knows how to\ndisplay itself.\n\nInserting and Updating Data\n===========================\n\nYou've already seen this done: to insert a row into your database, first create\nan instance of your model using keyword arguments, like so::\n\n    >>> p = Publisher(name='Apress',\n    ...         address='2855 Telegraph Ave.',\n    ...         city='Berkeley',\n    ...         state_province='CA',\n    ...         country='U.S.A.',\n    ...         website='http://www.apress.com/')\n\nAs we noted above, this act of instantiating a model class does *not* touch\nthe database. The record isn't saved into the database until you call\n``save()``, like this::\n\n    >>> p.save()\n\n.. SL Tested ok\n\nIn SQL, this can roughly be translated into the following::\n\n    INSERT INTO books_publisher\n        (name, address, city, state_province, country, website)\n    VALUES\n        ('Apress', '2855 Telegraph Ave.', 'Berkeley', 'CA',\n         'U.S.A.', 'http://www.apress.com/');\n\nBecause the ``Publisher`` model uses an autoincrementing primary key ``id``,\nthe initial call to ``save()`` does one more thing: it calculates the primary\nkey value for the record and sets it to the ``id`` attribute on the instance::\n\n    >>> p.id\n    52    # this will differ based on your own data\n\n.. SL Should be '52L' to match actual output.\n\nSubsequent calls to ``save()`` will save the record in place, without creating\na new record (i.e., performing an SQL ``UPDATE`` statement instead of an\n``INSERT``)::\n\n    >>> p.name = 'Apress Publishing'\n    >>> p.save()\n\n.. SL Tested ok\n\nThe preceding ``save()`` statement will result in roughly the following SQL::\n\n    UPDATE books_publisher SET\n        name = 'Apress Publishing',\n        address = '2855 Telegraph Ave.',\n        city = 'Berkeley',\n        state_province = 'CA',\n        country = 'U.S.A.',\n        website = 'http://www.apress.com'\n    WHERE id = 52;\n\nYes, note that *all* of the fields will be updated, not just the ones that have\nbeen changed. Depending on your application, this may cause a race condition.\nSee \"Updating Multiple Objects in One Statement\" below to find out how to\nexecute this (slightly different) query::\n\n    UPDATE books_publisher SET\n        name = 'Apress Publishing'\n    WHERE id=52;\n\nSelecting Objects\n=================\n\nKnowing how to create and update database records is essential, but chances are\nthat the Web applications you'll build will be doing more querying of existing\nobjects than creating new ones. We've already seen a way to retrieve *every*\nrecord for a given model::\n\n    >>> Publisher.objects.all()\n    [<Publisher: Apress>, <Publisher: O'Reilly>]\n\n.. SL Tested ok\n\nThis roughly translates to this SQL::\n\n    SELECT id, name, address, city, state_province, country, website\n    FROM books_publisher;\n\n.. note::\n\n    Notice that Django doesn't use ``SELECT *`` when looking up data and instead\n    lists all fields explicitly. This is by design: in certain circumstances\n    ``SELECT *`` can be slower, and (more important) listing fields more closely\n    follows one tenet of the Zen of Python: \"Explicit is better than implicit.\"\n\n    For more on the Zen of Python, try typing ``import this`` at a Python\n    prompt.\n\nLet's take a close look at each part of this ``Publisher.objects.all()`` line:\n\n* First, we have the model we defined, ``Publisher``. No surprise here: when\n  you want to look up data, you use the model for that data.\n\n* Next, we have the ``objects`` attribute. This is called a *manager*.\n  Managers are discussed in detail in Chapter 10. For now, all you need to\n  know is that managers take care of all \"table-level\" operations on data\n  including, most important, data lookup.\n\n  All models automatically get a ``objects`` manager; you'll use it\n  any time you want to look up model instances.\n\n* Finally, we have ``all()``. This is a method on the ``objects`` manager\n  that returns all the rows in the database. Though this object *looks*\n  like a list, it's actually a *QuerySet* -- an object that represents a\n  specific set of rows from the database. Appendix C deals with QuerySets\n  in detail. For the rest of this chapter, we'll just treat them like the\n  lists they emulate.\n\nAny database lookup is going to follow this general pattern -- we'll call methods on\nthe manager attached to the model we want to query against.\n\nFiltering Data\n--------------\n\nNaturally, it's rare to want to select *everything* from a database at once; in\nmost cases, you'll want to deal with a subset of your data. In the Django API,\nyou can filter your data using the ``filter()`` method::\n\n    >>> Publisher.objects.filter(name='Apress')\n    [<Publisher: Apress>]\n\n.. SL Tested ok\n\n``filter()`` takes keyword arguments that get translated into the appropriate\nSQL ``WHERE`` clauses. The preceding example would get translated into\nsomething like this::\n\n    SELECT id, name, address, city, state_province, country, website\n    FROM books_publisher\n    WHERE name = 'Apress';\n\nYou can pass multiple arguments into ``filter()`` to narrow down things further::\n\n    >>> Publisher.objects.filter(country=\"U.S.A.\", state_province=\"CA\")\n    [<Publisher: Apress>]\n\n.. SL Tested ok\n\nThose multiple arguments get translated into SQL ``AND`` clauses. Thus, the\nexample in the code snippet translates into the following::\n\n    SELECT id, name, address, city, state_province, country, website\n    FROM books_publisher\n    WHERE country = 'U.S.A.'\n    AND state_province = 'CA';\n\nNotice that by default the lookups use the SQL ``=`` operator to do exact match\nlookups. Other lookup types are available::\n\n    >>> Publisher.objects.filter(name__contains=\"press\")\n    [<Publisher: Apress>]\n\n.. SL Tested ok\n\nThat's a *double* underscore there between ``name`` and ``contains``. Like\nPython itself, Django uses the double underscore to signal that something\n\"magic\" is happening -- here, the ``__contains`` part gets translated by Django\ninto a SQL ``LIKE`` statement::\n\n    SELECT id, name, address, city, state_province, country, website\n    FROM books_publisher\n    WHERE name LIKE '%press%';\n\nMany other types of lookups are available, including ``icontains``\n(case-insensitive ``LIKE``), ``startswith`` and ``endswith``, and ``range`` (SQL\n``BETWEEN`` queries). Appendix C describes all of these lookup types in detail.\n\nRetrieving Single Objects\n-------------------------\n\nThe ``filter()`` examples above all returned a ``QuerySet``, which you can\ntreat like a list. Sometimes it's more convenient to fetch only a single object,\nas opposed to a list. That's what the ``get()`` method is for::\n\n    >>> Publisher.objects.get(name=\"Apress\")\n    <Publisher: Apress>\n\n.. SL Tested ok\n\nInstead of a list (rather, ``QuerySet``), only a single object is returned.\nBecause of that, a query resulting in multiple objects will cause an\nexception::\n\n    >>> Publisher.objects.get(country=\"U.S.A.\")\n    Traceback (most recent call last):\n        ...\n    MultipleObjectsReturned: get() returned more than one Publisher --\n        it returned 2! Lookup parameters were {'country': 'U.S.A.'}\n\n.. SL Tested ok\n\nA query that returns no objects also causes an exception::\n\n    >>> Publisher.objects.get(name=\"Penguin\")\n    Traceback (most recent call last):\n        ...\n    DoesNotExist: Publisher matching query does not exist.\n\n.. SL Tested ok\n\nThe ``DoesNotExist`` exception is an attribute of the model's class --\n``Publisher.DoesNotExist``. In your applications, you'll want to trap these\nexceptions, like this::\n\n    try:\n        p = Publisher.objects.get(name='Apress')\n    except Publisher.DoesNotExist:\n        print \"Apress isn't in the database yet.\"\n    else:\n        print \"Apress is in the database.\"\n\n.. SL Tested ok\n\nOrdering Data\n-------------\n\nAs you play around with the previous examples, you might discover that the objects\nare being returned in a seemingly random order. You aren't imagining things; so\nfar we haven't told the database how to order its results, so we're simply\ngetting back data in some arbitrary order chosen by the database.\n\nIn your Django applications, you'll probably want to order your results\naccording to a certain value -- say, alphabetically. To do this, use the\n``order_by()`` method::\n\n    >>> Publisher.objects.order_by(\"name\")\n    [<Publisher: Apress>, <Publisher: O'Reilly>]\n\n.. SL Tested ok\n\nThis doesn't look much different from the earlier ``all()`` example, but the\nSQL now includes a specific ordering::\n\n    SELECT id, name, address, city, state_province, country, website\n    FROM books_publisher\n    ORDER BY name;\n\nYou can order by any field you like::\n\n    >>> Publisher.objects.order_by(\"address\")\n    [<Publisher: O'Reilly>, <Publisher: Apress>]\n\n    >>> Publisher.objects.order_by(\"state_province\")\n    [<Publisher: Apress>, <Publisher: O'Reilly>]\n\n.. SL Tested ok\n\nTo order by multiple fields (where the second field is used to disambiguate\nordering in cases where the first is the same), use multiple arguments::\n\n    >>> Publisher.objects.order_by(\"state_province\", \"address\")\n     [<Publisher: Apress>, <Publisher: O'Reilly>]\n\n.. SL Tested ok\n\nYou can also specify reverse ordering by prefixing the field name with a ``-``\n(that's a minus character)::\n\n    >>> Publisher.objects.order_by(\"-name\")\n    [<Publisher: O'Reilly>, <Publisher: Apress>]\n\n.. SL Tested ok\n\nWhile this flexibility is useful, using ``order_by()`` all the time can be quite\nrepetitive. Most of the time you'll have a particular field you usually want\nto order by. In these cases, Django lets you specify a default ordering in the\nmodel:\n\n.. parsed-literal::\n\n    class Publisher(models.Model):\n        name = models.CharField(max_length=30)\n        address = models.CharField(max_length=50)\n        city = models.CharField(max_length=60)\n        state_province = models.CharField(max_length=30)\n        country = models.CharField(max_length=50)\n        website = models.URLField()\n\n        def __unicode__(self):\n            return self.name\n\n        **class Meta:**\n            **ordering = ['name']**\n\nHere, we've introduced a new concept: the ``class Meta``, which is a class\nthat's embedded within the ``Publisher`` class definition (i.e., it's indented\nto be within ``class Publisher``). You can use this ``Meta`` class on any model\nto specify various model-specific options. A full reference of ``Meta`` options\nis available in Appendix B, but for now, we're concerned with the ``ordering``\noption. If you specify this, it tells Django that unless an ordering is given\nexplicitly with ``order_by()``, all ``Publisher`` objects should be ordered by\nthe ``name`` field whenever they're retrieved with the Django database API.\n\nChaining Lookups\n----------------\n\nYou've seen how you can filter data, and you've seen how you can order it. Often, of course,\nyou'll need to do both. In these cases, you simply \"chain\" the lookups together::\n\n    >>> Publisher.objects.filter(country=\"U.S.A.\").order_by(\"-name\")\n    [<Publisher: O'Reilly>, <Publisher: Apress>]\n\n.. SL Tested ok\n\nAs you might expect, this translates to a SQL query with both a ``WHERE`` and an\n``ORDER BY``::\n\n    SELECT id, name, address, city, state_province, country, website\n    FROM books_publisher\n    WHERE country = 'U.S.A'\n    ORDER BY name DESC;\n\nSlicing Data\n------------\n\nAnother common need is to look up only a fixed number of rows. Imagine you have thousands\nof publishers in your database, but you want to display only the first one. You can do this\nusing Python's standard list slicing syntax::\n\n    >>> Publisher.objects.order_by('name')[0]\n    <Publisher: Apress>\n\n.. SL Tested ok\n\nThis translates roughly to::\n\n    SELECT id, name, address, city, state_province, country, website\n    FROM books_publisher\n    ORDER BY name\n    LIMIT 1;\n\nSimilarly, you can retrieve a specific subset of data using Python's\nrange-slicing syntax::\n\n    >>> Publisher.objects.order_by('name')[0:2]\n\n.. SL Tested ok (but should show expected output?)\n\nThis returns two objects, translating roughly to::\n\n    SELECT id, name, address, city, state_province, country, website\n    FROM books_publisher\n    ORDER BY name\n    OFFSET 0 LIMIT 2;\n\nNote that negative slicing is *not* supported::\n\n    >>> Publisher.objects.order_by('name')[-1]\n    Traceback (most recent call last):\n      ...\n    AssertionError: Negative indexing is not supported.\n\nThis is easy to get around, though. Just change the ``order_by()`` statement,\nlike this::\n\n    >>> Publisher.objects.order_by('-name')[0]\n\nUpdating Multiple Objects in One Statement\n------------------------------------------\n\nWe pointed out in the \"Inserting and Updating Data\" section that the model\n``save()`` method updates *all* columns in a row. Depending on your\napplication, you may want to update only a subset of columns.\n\nFor example, let's say we want to update the Apress ``Publisher`` to change\nthe name from ``'Apress'`` to ``'Apress Publishing'``. Using ``save()``, it\nwould look something like this::\n\n    >>> p = Publisher.objects.get(name='Apress')\n    >>> p.name = 'Apress Publishing'\n    >>> p.save()\n\n.. SL Tested ok\n\nThis roughly translates to the following SQL::\n\n    SELECT id, name, address, city, state_province, country, website\n    FROM books_publisher\n    WHERE name = 'Apress';\n\n    UPDATE books_publisher SET\n        name = 'Apress Publishing',\n        address = '2855 Telegraph Ave.',\n        city = 'Berkeley',\n        state_province = 'CA',\n        country = 'U.S.A.',\n        website = 'http://www.apress.com'\n    WHERE id = 52;\n\n(Note that this example assumes Apress has a publisher ID of ``52``.)\n\nYou can see in this example that Django's ``save()`` method sets *all* of the\ncolumn values, not just the ``name`` column. If you're in an environment where\nother columns of the database might change due to some other process, it's\nsmarter to change *only* the column you need to change. To do this, use the\n``update()`` method on ``QuerySet`` objects. Here's an example::\n\n    >>> Publisher.objects.filter(id=52).update(name='Apress Publishing')\n\n.. SL Tested ok\n\nThe SQL translation here is much more efficient and has no chance of race\nconditions::\n\n    UPDATE books_publisher\n    SET name = 'Apress Publishing'\n    WHERE id = 52;\n\nThe ``update()`` method works on any ``QuerySet``, which means you can edit\nmultiple records in bulk. Here's how you might change the ``country`` from\n``'U.S.A.'`` to ``USA`` in each ``Publisher`` record::\n\n    >>> Publisher.objects.all().update(country='USA')\n    2\n\n.. SL Tested ok\n\nThe ``update()`` method has a return value -- an integer representing how many\nrecords changed. In the above example, we got ``2``.\n\nDeleting Objects\n================\n\nTo delete an object from your database, simply call the object's ``delete()``\nmethod::\n\n    >>> p = Publisher.objects.get(name=\"O'Reilly\")\n    >>> p.delete()\n    >>> Publisher.objects.all()\n    [<Publisher: Apress Publishing>]\n\n.. SL Tested ok\n\nYou can also delete objects in bulk by calling ``delete()`` on the result of\nany ``QuerySet``. This is similar to the ``update()`` method we showed in the\nlast section::\n\n    >>> Publisher.objects.filter(country='USA').delete()\n    >>> Publisher.objects.all().delete()\n    >>> Publisher.objects.all()\n    []\n\n.. SL Tested ok\n\nBe careful deleting your data! As a precaution against deleting all of the data\nin a particular table, Django requires you to explicitly use ``all()`` if you\nwant to delete *everything* in your table. For example, this won't work::\n\n    >>> Publisher.objects.delete()\n    Traceback (most recent call last):\n      File \"<console>\", line 1, in <module>\n    AttributeError: 'Manager' object has no attribute 'delete'\n\n.. SL Tested ok\n\nBut it'll work if you add the ``all()`` method::\n\n    >>> Publisher.objects.all().delete()\n\n.. SL Tested ok\n\nIf you're just deleting a subset of your data, you don't need to include\n``all()``. To repeat a previous example::\n\n    >>> Publisher.objects.filter(country='USA').delete()\n\n.. SL Tested ok\n\nWhat's Next?\n============\n\nHaving read this chapter, you have enough knowledge of Django models to be able\nto write basic database applications. Chapter 10 will provide some information\non more advanced usage of Django's database layer.\n\nOnce you've defined your models, the next step is to populate your database\nwith data. You might have legacy data, in which case Chapter 18 will give you\nadvice about integrating with legacy databases. You might rely on site users\nto supply your data, in which case Chapter 7 will teach you how to process\nuser-submitted form data.\n\nBut in some cases, you or your team might need to enter data manually, in which\ncase it would be helpful to have a Web-based interface for entering and\nmanaging data. The :doc:`next chapter <chapter06>` covers Django's admin interface, which exists\nprecisely for that reason.\n"
  },
  {
    "path": "Python/DjangoBook/chapter06.rst",
    "content": "================================\nChapter 6: The Django Admin Site\n================================\n\nFor a certain class of Web sites, an *admin interface* is an essential part of\nthe infrastructure. This is a Web-based interface, limited to trusted site\nadministrators, that enables the adding, editing and deletion of site content.\nSome common examples: the interface you use to post to your blog, the backend\nsite managers use to moderate user-generated comments, the tool your clients\nuse to update the press releases on the Web site you built for them.\n\nThere's a problem with admin interfaces, though: it's boring to build them.\nWeb development is fun when you're developing public-facing functionality, but\nbuilding admin interfaces is always the same. You have to authenticate users,\ndisplay and handle forms, validate input, and so on. It's boring, and it's\nrepetitive.\n\nSo what's Django's approach to these boring, repetitive tasks? It does it all\nfor you -- in just a couple of lines of code, no less. With Django, building an\nadmin interface is a solved problem.\n\nThis chapter is about Django's automatic admin interface. The feature works by\nreading metadata in your model to provide a powerful and production-ready\ninterface that site administrators can start using immediately. Here, we discuss\nhow to activate, use, and customize this feature.\n\nNote that we recommend reading this chapter even if you don't intend to use the\nDjango admin site, because we introduce a few concepts that apply to all of\nDjango, regardless of admin-site usage.\n\nThe django.contrib packages\n===========================\n\nDjango's automatic admin is part of a larger suite of Django functionality\ncalled ``django.contrib`` -- the part of the Django codebase that contains\nvarious useful add-ons to the core framework. You can think of\n``django.contrib`` as Django's equivalent of the Python standard library --\noptional, de facto implementations of common patterns. They're bundled with\nDjango so that you don't have to reinvent the wheel in your own applications.\n\nThe admin site is the first part of ``django.contrib`` that we're covering in\nthis book; technically, it's called ``django.contrib.admin``. Other available\nfeatures in ``django.contrib`` include a user authentication system\n(``django.contrib.auth``), support for anonymous sessions\n(``django.contrib.sessions``) and even a system for user comments\n(``django.contrib.comments``). You'll get to know the various ``django.contrib``\nfeatures as you become a Django expert, and we'll spend some more time\ndiscussing them in Chapter 16. For now, just know that Django ships with many\nnice add-ons, and ``django.contrib`` is generally where they live.\n\nActivating the Admin Interface\n==============================\n\nThe Django admin site is entirely optional, because only certain types of sites\nneed this functionality. That means you'll need to take a few steps to activate\nit in your project.\n\nFirst, make a few changes to your settings file:\n\n1. Add ``'django.contrib.admin'`` to the ``INSTALLED_APPS`` setting. (The\n   order of ``INSTALLED_APPS`` doesn't matter, but we like to keep things\n   alphabetical so it's easy for a human to read.)\n\n2. Make sure ``INSTALLED_APPS`` contains ``'django.contrib.auth'``,\n   ``'django.contrib.contenttypes'`` and ``'django.contrib.sessions'``. The\n   Django admin site requires these three packages. (If you're following\n   along with our ongoing ``mysite`` project, note that we commented out\n   these three ``INSTALLED_APPS`` entries in Chapter 5. Uncomment them now.)\n\n3. Make sure ``MIDDLEWARE_CLASSES`` contains\n   ``'django.middleware.common.CommonMiddleware'``,\n   ``'django.contrib.sessions.middleware.SessionMiddleware'`` and\n   ``'django.contrib.auth.middleware.AuthenticationMiddleware'``. (Again,\n   if you're following along, note that we commented them out in Chapter 5,\n   so uncomment them.)\n\nSecond, run ``python manage.py syncdb``. This step will install the extra\ndatabase tables that the admin interface uses. The first time you run\n``syncdb`` with ``'django.contrib.auth'`` in ``INSTALLED_APPS``, you'll be\nasked about creating a superuser. If you don't do this, you'll need to run\n``python manage.py createsuperuser`` separately to create an admin user\naccount; otherwise, you won't be able to log in to the admin site. (Potential\ngotcha: the ``python manage.py createsuperuser`` command is only available if\n``'django.contrib.auth'`` is in your ``INSTALLED_APPS``.)\n\nThird, add the admin site to your URLconf (in ``urls.py``, remember). By\ndefault, the ``urls.py`` generated by ``django-admin.py startproject`` contains\ncommented-out code for the Django admin, and all you have to do is uncomment\nit. For the record, here are the bits you need to make sure are in there::\n\n    # Include these import statements...\n    from django.contrib import admin\n    admin.autodiscover()\n\n    # And include this URLpattern...\n    urlpatterns = patterns('',\n        # ...\n        (r'^admin/', include(admin.site.urls)),\n        # ...\n    )\n\nWith that bit of configuration out of the way, now you can see the Django\nadmin site in action. Just run the development server\n(``python manage.py runserver``, as in previous chapters) and visit\n``http://127.0.0.1:8000/admin/`` in your Web browser.\n\nUsing the Admin Site\n====================\n\nThe admin site is designed to be used by nontechnical users, and as such it\nshould be pretty self-explanatory. Nevertheless, we'll give you a quick\nwalkthrough of the basic features.\n\nThe first thing you'll see is a login screen, as shown in Figure 6-1.\n\n.. figure:: graphics/chapter06/login.png\n   :alt: Screenshot of Django's login page.\n\n   Figure 6-1. Django's login screen\n\nLog in with the username and password you set up when you added your superuser.\nIf you're unable to log in, make sure you've actually created a superuser --\ntry running ``python manage.py createsuperuser``.\n\nOnce you're logged in, the first thing you'll see will be the admin home page.\nThis page lists all the available types of data that can be edited on the admin\nsite. At this point, because we haven't activated any of our own models yet,\nthe list is sparse: it includes only Groups and Users, which are the two\ndefault admin-editable models.\n\n.. DWP The screenshot contains books etc too.\n\n.. figure:: graphics/chapter06/admin_index.png\n   :alt: Screenshot of the Django admin home page.\n\n   Figure 6-2. The Django admin home page\n\nEach type of data in the Django admin site has a *change list* and an\n*edit form*. Change lists show you all the available objects in the database,\nand edit forms let you add, change or delete particular records in your\ndatabase.\n\n.. admonition:: Other languages\n\n    If your primary language is not English and your Web browser is configured\n    to prefer a language other than English, you can make a quick change to\n    see whether the Django admin site has been translated into your language.\n    Just add ``'django.middleware.locale.LocaleMiddleware'`` to your\n    ``MIDDLEWARE_CLASSES`` setting, making sure it appears *after*\n    ``'django.contrib.sessions.middleware.SessionMiddleware'``.\n\n    When you've done that, reload the admin index page. If a translation for\n    your language is available, then the various parts of the interface -- from\n    the \"Change password\" and \"Log out\" links at the top of the page, to the\n    \"Groups\" and \"Users\" links in the middle -- will appear in your language\n    instead of English. Django ships with translations for dozens of languages.\n\n    For much more on Django's internationalization features, see Chapter 19.\n\nClick the \"Change\" link in the \"Users\" row to load the change list page for\nusers.\n\n.. figure:: graphics/chapter06/user_changelist.png\n   :alt: Screenshot of the user change list page.\n\n   Figure 6-3. The user change list page\n\n.. DWP This screenshot is actually the list for books.\n\nThis page displays all users in the database; you can think of it as a\nprettied-up Web version of a ``SELECT * FROM auth_user;`` SQL query. If you're\nfollowing along with our ongoing example, you'll only see one user here,\nassuming you've added only one, but once you have more users, you'll probably\nfind the filtering, sorting and searching options useful. Filtering options are\nat right, sorting is available by clicking a column header, and the search box\nat the top lets you search by username.\n\nClick the username of the user you created, and you'll see the edit form for\nthat user.\n\n.. figure:: graphics/chapter06/user_editform.png\n   :alt: Screenshot of the user edit form\n\n   Figure 6-4. The user edit form\n\n.. DWP The edit form screenshot is for a book.\n\nThis page lets you change the attributes of the user, like the\nfirst/last names and various permissions. (Note that to change a user's\npassword, you should click \"change password form\" under the password field\nrather than editing the hashed code.) Another thing to note here is that fields\nof different types get different widgets -- for example, date/time fields have\ncalendar controls, boolean fields have checkboxes, character fields have simple\ntext input fields.\n\nYou can delete a record by clicking the delete button at the bottom left of its\nedit form. That'll take you to a confirmation page, which, in some cases, will\ndisplay any dependent objects that will be deleted, too. (For example, if you\ndelete a publisher, any book with that publisher will be deleted, too!)\n\nYou can add a record by clicking \"Add\" in the appropriate column of the admin\nhome page. This will give you an empty version of the edit page, ready for you\nto fill out.\n\nYou'll also notice that the admin interface also handles input validation for\nyou. Try leaving a required field blank or putting an invalid date into a date\nfield, and you'll see those errors when you try to save, as shown in Figure 6-5.\n\n.. figure:: graphics/chapter06/user_editform_errors.png\n   :alt: Screenshot of an edit form displaying errors.\n\n   Figure 6-5. An edit form displaying errors\n\n.. DWP The screenshots are still following a book example.\n\nWhen you edit an existing object, you'll notice a History link in the\nupper-right corner of the window. Every change made through the admin interface\nis logged, and you can examine this log by clicking the History link (see\nFigure 6-6).\n\n.. figure:: graphics/chapter06/user_history.png\n   :alt: Screenshot of an object history page.\n\n   Figure 6-6. An object history page\n\n.. DWP Still using a book in the pictures.\n\nAdding Your Models to the Admin Site\n====================================\n\nThere's one crucial part we haven't done yet. Let's add our own models to the\nadmin site, so we can add, change and delete objects in our custom database\ntables using this nice interface. We'll continue the ``books`` example from\nChapter 5, where we defined three models: ``Publisher``, ``Author`` and\n``Book``.\n\nWithin the ``books`` directory (``mysite/books``), create a file called\n``admin.py``, and type in the following lines of code::\n\n    from django.contrib import admin\n    from mysite.books.models import Publisher, Author, Book\n\n    admin.site.register(Publisher)\n    admin.site.register(Author)\n    admin.site.register(Book)\n\nThis code tells the Django admin site to offer an interface for each of these\nmodels.\n\nOnce you've done this, go to your admin home page in your Web browser\n(``http://127.0.0.1:8000/admin/``), and you should see a \"Books\" section with\nlinks for Authors, Books and Publishers. (You might have to stop and start the\n``runserver`` for the changes to take effect.)\n\n.. SL Tested ok\n\nYou now have a fully functional admin interface for each of those three models.\nThat was easy!\n\nTake some time to add and change records, to populate your database with some\ndata. If you followed Chapter 5's examples of creating ``Publisher`` objects\n(and you didn't delete them), you'll already see those records on the publisher\nchange list page.\n\nOne feature worth mentioning here is the admin site's handling of foreign keys\nand many-to-many relationships, both of which appear in the ``Book`` model. As\na reminder, here's what the ``Book`` model looks like::\n\n    class Book(models.Model):\n        title = models.CharField(max_length=100)\n        authors = models.ManyToManyField(Author)\n        publisher = models.ForeignKey(Publisher)\n        publication_date = models.DateField()\n\n        def __unicode__(self):\n            return self.title\n\nOn the Django admin site's \"Add book\" page\n(``http://127.0.0.1:8000/admin/books/book/add/``), the publisher (a\n``ForeignKey``) is represented by a select box, and the authors field\n(a ``ManyToManyField``) is represented by a multiple-select box. Both fields\nsit next to a green plus sign icon that lets you add related records of that\ntype. For example, if you click the green plus sign next to the \"Publisher\"\nfield, you'll get a pop-up window that lets you add a publisher. After you\nsuccessfully create the publisher in the pop-up, the \"Add book\" form will be\nupdated with the newly created publisher. Slick.\n\nHow the Admin Site Works\n========================\n\nBehind the scenes, how does the admin site work? It's pretty straightforward.\n\nWhen Django loads your URLconf from ``urls.py`` at server startup, it executes\nthe ``admin.autodiscover()`` statement that we added as part of activating the\nadmin. This function iterates over your ``INSTALLED_APPS`` setting and looks\nfor a file called ``admin.py`` in each installed app. If an ``admin.py``\nexists in a given app, it executes the code in that file.\n\nIn the ``admin.py`` in our ``books`` app, each call to\n``admin.site.register()`` simply registers the given model with the admin. The\nadmin site will only display an edit/change interface for models that have been\nexplicitly registered.\n\nThe app ``django.contrib.auth`` includes its own ``admin.py``, which is why\nUsers and Groups showed up automatically in the admin. Other ``django.contrib``\napps, such as ``django.contrib.redirects``, also add themselves to the admin,\nas do many third-party Django applications you might download from the Web.\n\nBeyond that, the Django admin site is just a Django application, with its own\nmodels, templates, views and URLpatterns. You add it to your application by\nhooking it into your URLconf, just as you hook in your own views. You can\ninspect its templates, views and URLpatterns by poking around in\n``django/contrib/admin`` in your copy of the Django codebase -- but don't be\ntempted to change anything directly in there, as there are plenty of hooks for\nyou to customize the way the admin site works. (If you do decide to poke around\nthe Django admin application, keep in mind it does some rather complicated\nthings in reading metadata about models, so it would probably take a good\namount of time to read and understand the code.)\n\nMaking Fields Optional\n======================\n\nAfter you play around with the admin site for a while, you'll probably notice a\nlimitation -- the edit forms require every field to be filled out, whereas in\nmany cases you'd want certain fields to be optional. Let's say, for example,\nthat we want our ``Author`` model's ``email`` field to be optional -- that is,\na blank string should be allowed. In the real world, you might not have an\ne-mail address on file for every author.\n\nTo specify that the ``email`` field is optional, edit the ``Author`` model\n(which, as you'll recall from Chapter 5, lives in ``mysite/books/models.py``).\nSimply add ``blank=True`` to the ``email`` field, like so:\n\n.. parsed-literal::\n\n    class Author(models.Model):\n        first_name = models.CharField(max_length=30)\n        last_name = models.CharField(max_length=40)\n        email = models.EmailField(**blank=True**)\n\n.. SL Tested ok\n\nThis tells Django that a blank value is indeed allowed for authors' e-mail\naddresses. By default, all fields have ``blank=False``, which means blank\nvalues are not allowed.\n\nThere's something interesting happening here. Until now, with the exception of\nthe ``__unicode__()`` method, our models have served as definitions of our\ndatabase tables -- Pythonic expressions of SQL ``CREATE TABLE`` statements,\nessentially. In adding ``blank=True``, we have begun expanding our model beyond\na simple definition of what the database table looks like. Now, our model class\nis starting to become a richer collection of knowledge about what ``Author``\nobjects are and what they can do. Not only is the ``email`` field represented\nby a ``VARCHAR`` column in the database; it's also an optional field in\ncontexts such as the Django admin site.\n\nOnce you've added that ``blank=True``, reload the \"Add author\" edit form\n(``http://127.0.0.1:8000/admin/books/author/add/``), and you'll notice the\nfield's label -- \"Email\" -- is no longer bolded. This signifies it's not a\nrequired field. You can now add authors without needing to provide\ne-mail addresses; you won't get the loud red \"This field is required\" message\nanymore, if the field is submitted empty.\n\nMaking Date and Numeric Fields Optional\n---------------------------------------\n\nA common gotcha related to ``blank=True`` has to do with date and numeric\nfields, but it requires a fair amount of background explanation.\n\nSQL has its own way of specifying blank values -- a special value called\n``NULL``. ``NULL`` could mean \"unknown,\" or \"invalid,\" or some other\napplication-specific meaning.\n\nIn SQL, a value of ``NULL`` is different than an empty string, just as the\nspecial Python object ``None`` is different than an empty Python string\n(``\"\"``). This means it's possible for a particular character field (e.g., a\n``VARCHAR`` column) to contain both ``NULL`` values and empty string values.\n\nThis can cause unwanted ambiguity and confusion: \"Why does this record have a\n``NULL`` but this other one has an empty string? Is there a difference, or was\nthe data just entered inconsistently?\" And: \"How do I get all the records that\nhave a blank value -- should I look for both ``NULL`` records and empty\nstrings, or do I only select the ones with empty strings?\"\n\nTo help avoid such ambiguity, Django's automatically generated ``CREATE TABLE``\nstatements (which were covered in Chapter 5) add an explicit ``NOT NULL`` to\neach column definition. For example, here's the generated statement for our\n``Author`` model, from Chapter 5::\n\n    CREATE TABLE \"books_author\" (\n        \"id\" serial NOT NULL PRIMARY KEY,\n        \"first_name\" varchar(30) NOT NULL,\n        \"last_name\" varchar(40) NOT NULL,\n        \"email\" varchar(75) NOT NULL\n    )\n    ;\n\nIn most cases, this default behavior is optimal for your application and will\nsave you from data-inconsistency headaches. And it works nicely with the rest\nof Django, such as the Django admin site, which inserts an empty string (*not*\na ``NULL`` value) when you leave a character field blank.\n\nBut there's an exception with database column types that do not accept empty\nstrings as valid values -- such as dates, times and numbers. If you try to\ninsert an empty string into a date or integer column, you'll likely get a\ndatabase error, depending on which database you're using. (PostgreSQL, which is\nstrict, will raise an exception here; MySQL might accept it or might not,\ndepending on the version you're using, the time of day and the phase of the\nmoon.) In this case, ``NULL`` is the only way to specify an empty\nvalue. In Django models, you can specify that ``NULL`` is allowed by adding\n``null=True`` to a field.\n\nSo that's a long way of saying this: if you want to allow blank values in a\ndate field (e.g., ``DateField``, ``TimeField``, ``DateTimeField``) or numeric\nfield (e.g., ``IntegerField``, ``DecimalField``, ``FloatField``), you'll need\nto use both ``null=True`` *and* ``blank=True``.\n\nFor sake of example, let's change our ``Book`` model to allow a blank\n``publication_date``. Here's the revised code:\n\n.. parsed-literal::\n\n    class Book(models.Model):\n        title = models.CharField(max_length=100)\n        authors = models.ManyToManyField(Author)\n        publisher = models.ForeignKey(Publisher)\n        publication_date = models.DateField(**blank=True, null=True**)\n\n.. SL Tested ok\n\nAdding ``null=True`` is more complicated than adding ``blank=True``, because\n``null=True`` changes the semantics of the database -- that is, it changes the\n``CREATE TABLE`` statement to remove the ``NOT NULL`` from the\n``publication_date`` field. To complete this change, we'll need to update the\ndatabase.\n\nFor a number of reasons, Django does not attempt to automate changes to\ndatabase schemas, so it's your own responsibility to execute the appropriate\n``ALTER TABLE`` statement whenever you make such a change to a model. Recall\nthat you can use ``manage.py dbshell`` to enter your database server's shell.\nHere's how to remove the ``NOT NULL`` in this particular case::\n\n    ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;\n\n(Note that this SQL syntax is specific to PostgreSQL.)\n\nWe'll cover schema changes in more depth in Chapter 10.\n\nBringing this back to the admin site, now the \"Add book\" edit form should allow\nfor empty publication date values.\n\nCustomizing Field Labels\n========================\n\nOn the admin site's edit forms, each field's label is generated from its model\nfield name. The algorithm is simple: Django just replaces underscores with\nspaces and capitalizes the first character, so, for example, the ``Book``\nmodel's ``publication_date`` field has the label \"Publication date.\"\n\nHowever, field names don't always lend themselves to nice admin field labels,\nso in some cases you might want to customize a label. You can do this by\nspecifying ``verbose_name`` in the appropriate model field.\n\nFor example, here's how we can change the label of the ``Author.email`` field\nto \"e-mail,\" with a hyphen:\n\n.. parsed-literal::\n\n    class Author(models.Model):\n        first_name = models.CharField(max_length=30)\n        last_name = models.CharField(max_length=40)\n        email = models.EmailField(blank=True, **verbose_name='e-mail'**)\n\nMake that change and reload the server, and you should see the field's new\nlabel on the author edit form.\n\nNote that you shouldn't capitalize the first letter of a ``verbose_name``\nunless it should *always* be capitalized (e.g., ``\"USA state\"``). Django will\nautomatically capitalize it when it needs to, and it will use the exact\n``verbose_name`` value in other places that don't require capitalization.\n\nFinally, note that you can pass the ``verbose_name`` as a positional argument,\nfor a slightly more compact syntax. This example is equivalent to the previous\none:\n\n.. parsed-literal::\n\n    class Author(models.Model):\n        first_name = models.CharField(max_length=30)\n        last_name = models.CharField(max_length=40)\n        email = models.EmailField(**'e-mail',** blank=True)\n\n.. SL Tested ok\n\nThis won't work with ``ManyToManyField`` or ``ForeignKey`` fields, though,\nbecause they require the first argument to be a model class. In those cases,\nspecifying ``verbose_name`` explicitly is the way to go.\n\nCustom ModelAdmin classes\n=========================\n\nThe changes we've made so far -- ``blank=True``, ``null=True`` and\n``verbose_name`` -- are really model-level changes, not admin-level changes.\nThat is, these changes are fundamentally a part of the model and just so happen\nto be used by the admin site; there's nothing admin-specific about them.\n\nBeyond these, the Django admin site offers a wealth of options that let you\ncustomize how the admin site works for a particular model. Such options live in\n*ModelAdmin classes*, which are classes that contain configuration for a\nspecific model in a specific admin site instance.\n\nCustomizing change lists\n------------------------\n\nLet's dive into admin customization by specifying the fields that are\ndisplayed on the change list for our ``Author`` model. By default, the change\nlist displays the result of ``__unicode__()`` for each object. In Chapter 5, we\ndefined the ``__unicode__()`` method for ``Author`` objects to display the\nfirst name and last name together:\n\n.. parsed-literal::\n\n    class Author(models.Model):\n        first_name = models.CharField(max_length=30)\n        last_name = models.CharField(max_length=40)\n        email = models.EmailField(blank=True, verbose_name='e-mail')\n\n        **def __unicode__(self):**\n            **return u'%s %s' % (self.first_name, self.last_name)**\n\nAs a result, the change list for ``Author`` objects displays each other's\nfirst name and last name together, as you can see in Figure 6-7.\n\n.. DWP The image is of the change list for a book, not an author.\n\n.. figure:: graphics/chapter06/author_changelist1.png\n   :alt: Screenshot of the author change list page.\n\n   Figure 6-7. The author change list page\n\nWe can improve on this default behavior by adding a few other fields to the\nchange list display. It'd be handy, for example, to see each author's e-mail\naddress in this list, and it'd be nice to be able to sort by first and last\nname.\n\nTo make this happen, we'll define a ``ModelAdmin`` class for the ``Author``\nmodel. This class is the key to customizing the admin, and one of the most\nbasic things it lets you do is specify the list of fields to display on change\nlist pages. Edit ``admin.py`` to make these changes:\n\n.. parsed-literal::\n\n    from django.contrib import admin\n    from mysite.books.models import Publisher, Author, Book\n\n    **class AuthorAdmin(admin.ModelAdmin):**\n        **list_display = ('first_name', 'last_name', 'email')**\n\n    admin.site.register(Publisher)\n    **admin.site.register(Author, AuthorAdmin)**\n    admin.site.register(Book)\n\n.. SL Tested ok\n\nHere's what we've done:\n\n* We created the class ``AuthorAdmin``. This class, which subclasses\n  ``django.contrib.admin.ModelAdmin``, holds custom configuration\n  for a specific admin model. We've only specified one customization --\n  ``list_display``, which is set to a tuple of field names to display on\n  the change list page. These field names must exist in the model, of\n  course.\n\n* We altered the ``admin.site.register()`` call to add ``AuthorAdmin`` after\n  ``Author``. You can read this as: \"Register the ``Author`` model with the\n  ``AuthorAdmin`` options.\"\n\n  The ``admin.site.register()`` function takes a ``ModelAdmin`` subclass as\n  an optional second argument. If you don't specify a second argument (as\n  is the case for ``Publisher`` and ``Book``), Django will use the default\n  admin options for that model.\n\nWith that tweak made, reload the author change list page, and you'll see it's\nnow displaying three columns -- the first name, last name and e-mail address.\nIn addition, each of those columns is sortable by clicking on the column\nheader. (See Figure 6-8.)\n\n.. figure:: graphics/chapter06/author_changelist2.png\n   :alt: Screenshot of the author change list page after list_display.\n\n   Figure 6-8. The author change list page after list_display\n\n.. DWP This figure has the same filename as the last one.\n\nNext, let's add a simple search bar. Add ``search_fields`` to the\n``AuthorAdmin``, like so:\n\n.. parsed-literal::\n\n    class AuthorAdmin(admin.ModelAdmin):\n        list_display = ('first_name', 'last_name', 'email')\n        **search_fields = ('first_name', 'last_name')**\n\n.. SL Tested ok\n\nReload the page in your browser, and you should see a search bar at the top.\n(See Figure 6-9.) We've just told the admin change list page to include a\nsearch bar that searches against the ``first_name`` and ``last_name`` fields.\nAs a user might expect, this is case-insensitive and searches both fields, so\nsearching for the string ``\"bar\"`` would find both an author with the first\nname Barney and an author with the last name Hobarson.\n\n.. DWP Again, same screenshot.\n\n.. figure:: graphics/chapter06/author_changelist3.png\n   :alt: Screenshot of the author change list page after search_fields.\n\n   Figure 6-9. The author change list page after search_fields\n\nNext, let's add some date filters to our ``Book`` model's change list page:\n\n.. parsed-literal::\n\n    from django.contrib import admin\n    from mysite.books.models import Publisher, Author, Book\n\n    class AuthorAdmin(admin.ModelAdmin):\n        list_display = ('first_name', 'last_name', 'email')\n        search_fields = ('first_name', 'last_name')\n\n    **class BookAdmin(admin.ModelAdmin):**\n        **list_display = ('title', 'publisher', 'publication_date')**\n        **list_filter = ('publication_date',)**\n\n    admin.site.register(Publisher)\n    admin.site.register(Author, AuthorAdmin)\n    **admin.site.register(Book, BookAdmin)**\n\n.. SL Tested ok\n\nHere, because we're dealing with a different set of options, we created a\nseparate ``ModelAdmin`` class -- ``BookAdmin``. First, we defined a\n``list_display`` just to make the change list look a bit nicer. Then, we\nused ``list_filter``, which is set to a tuple of fields to use to create\nfilters along the right side of the change list page. For date fields, Django\nprovides shortcuts to filter the list to \"Today,\" \"Past 7 days,\" \"This month\"\nand \"This year\" -- shortcuts that Django's developers have found hit the\ncommon cases for filtering by date. Figure 6-10 shows what that looks like.\n\n.. DWP Screenshot needs changing.\n\n.. figure:: graphics/chapter06/book_changelist1.png\n   :alt: Screenshot of the book change list page after list_filter.\n\n   Figure 6-10. The book change list page after list_filter\n\n``list_filter`` also works on fields of other types, not just ``DateField``.\n(Try it with ``BooleanField`` and ``ForeignKey`` fields, for example.) The\nfilters show up as long as there are at least 2 values to choose from.\n\nAnother way to offer date filters is to use the ``date_hierarchy`` admin\noption, like this:\n\n.. parsed-literal::\n\n    class BookAdmin(admin.ModelAdmin):\n        list_display = ('title', 'publisher', 'publication_date')\n        list_filter = ('publication_date',)\n        **date_hierarchy = 'publication_date'**\n\n.. SL Tested ok\n\nWith this in place, the change list page gets a date drill-down navigation bar\nat the top of the list, as shown in Figure 6-11. It starts with a list of\navailable years, then drills down into months and individual days.\n\n.. DWP Screenshot again.\n\n.. figure:: graphics/chapter06/book_changelist2.png\n   :alt: Screenshot of the book change list page after date_hierarchy.\n\n   Figure 6-11. The book change list page after date_hierarchy\n\nNote that ``date_hierarchy`` takes a *string*, not a tuple, because only one\ndate field can be used to make the hierarchy.\n\nFinally, let's change the default ordering so that books on the change list\npage are always ordered descending by their publication date. By default,\nthe change list orders objects according to their model's ``ordering`` within\n``class Meta`` (which we covered in Chapter 5) -- but you haven't specified\nthis ``ordering`` value, then the ordering is undefined.\n\n.. parsed-literal::\n\n    class BookAdmin(admin.ModelAdmin):\n        list_display = ('title', 'publisher', 'publication_date')\n        list_filter = ('publication_date',)\n        date_hierarchy = 'publication_date'\n        **ordering = ('-publication_date',)**\n\n.. SL Tested ok\n\nThis admin ``ordering`` option works exactly as the ``ordering`` in models'\n``class Meta``, except that it only uses the first field name in the list. Just\npass a list or tuple of field names, and add a minus sign to a field to use\ndescending sort order.\n\nReload the book change list to see this in action. Note that the\n\"Publication date\" header now includes a small arrow that indicates which way\nthe records are sorted. (See Figure 6-12.)\n\n.. DWP Different screenshot needed.\n\n.. figure:: graphics/chapter06/book_changelist3.png\n   :alt: Screenshot of the book change list page after ordering.\n\n   Figure 6-12. The book change list page after ordering\n\nWe've covered the main change list options here. Using these options, you can\nmake a very powerful, production-ready data-editing interface with only a few\nlines of code.\n\nCustomizing edit forms\n----------------------\n\nJust as the change list can be customized, edit forms can be customized in many\nways.\n\nFirst, let's customize the way fields are ordered. By default, the order of\nfields in an edit form corresponds to the order they're defined in the model.\nWe can change that using the ``fields`` option in our ``ModelAdmin`` subclass:\n\n.. parsed-literal::\n\n    class BookAdmin(admin.ModelAdmin):\n        list_display = ('title', 'publisher', 'publication_date')\n        list_filter = ('publication_date',)\n        date_hierarchy = 'publication_date'\n        ordering = ('-publication_date',)\n        **fields = ('title', 'authors', 'publisher', 'publication_date')**\n\n.. SL Tested ok\n\nAfter this change, the edit form for books will use the given ordering for\nfields. It's slightly more natural to have the authors after the book title.\nOf course, the field order should depend on your data-entry workflow. Every\nform is different.\n\nAnother useful thing the ``fields`` option lets you do is to *exclude* certain\nfields from being edited entirely. Just leave out the field(s) you want to\nexclude. You might use this if your admin users are only trusted to edit a\ncertain segment of your data, or if part of your fields are changed by some\noutside, automated process. For example, in our book database, we could\nhide the ``publication_date`` field from being editable:\n\n.. parsed-literal::\n\n    class BookAdmin(admin.ModelAdmin):\n        list_display = ('title', 'publisher', 'publication_date')\n        list_filter = ('publication_date',)\n        date_hierarchy = 'publication_date'\n        ordering = ('-publication_date',)\n        **fields = ('title', 'authors', 'publisher')**\n\n.. SL Tested ok\n\nAs a result, the edit form for books doesn't offer a way to specify the\npublication date. This could be useful, say, if you're an editor who prefers\nthat his authors not push back publication dates. (This is purely a\nhypothetical example, of course.)\n\nWhen a user uses this incomplete form to add a new book, Django will simply set\nthe ``publication_date`` to ``None`` -- so make sure that field has\n``null=True``.\n\nAnother commonly used edit-form customization has to do with many-to-many\nfields. As we've seen on the edit form for books, the admin site represents each\n``ManyToManyField`` as a multiple-select boxes, which is the most logical\nHTML input widget to use -- but multiple-select boxes can be difficult to use.\nIf you want to select multiple items, you have to hold down the control key,\nor command on a Mac, to do so. The admin site helpfully inserts a bit of text\nthat explains this, but, still, it gets unwieldy when your field contains\nhundreds of options.\n\nThe admin site's solution is ``filter_horizontal``. Let's add that to\n``BookAdmin`` and see what it does.\n\n.. parsed-literal::\n\n    class BookAdmin(admin.ModelAdmin):\n        list_display = ('title', 'publisher', 'publication_date')\n        list_filter = ('publication_date',)\n        date_hierarchy = 'publication_date'\n        ordering = ('-publication_date',)\n        **filter_horizontal = ('authors',)**\n\n.. SL Tested ok\n\n(If you're following along, note that we've also removed the ``fields`` option\nto restore all the fields in the edit form.)\n\nReload the edit form for books, and you'll see that the \"Authors\" section now\nuses a fancy JavaScript filter interface that lets you search through the\noptions dynamically and move specific authors from \"Available authors\" to\nthe \"Chosen authors\" box, and vice versa.\n\n.. DWP screenshot!\n\n.. figure:: graphics/chapter06/book_editform1.png\n   :alt: Screenshot of the book edit form after adding filter_horizontal.\n\n   Figure 6-13. The book edit form after adding filter_horizontal\n\nWe'd highly recommend using ``filter_horizontal`` for any ``ManyToManyField``\nthat has more than 10 items. It's far easier to use than a simple\nmultiple-select widget. Also, note you can use ``filter_horizontal``\nfor multiple fields -- just specify each name in the tuple.\n\n``ModelAdmin`` classes also support a ``filter_vertical`` option. This works\nexactly as ``filter_horizontal``, but the resulting JavaScript interface stacks\nthe two boxes vertically instead of horizontally. It's a matter of personal\ntaste.\n\n``filter_horizontal`` and ``filter_vertical`` only work on ``ManyToManyField``\nfields, not ``ForeignKey`` fields. By default, the admin site uses simple\n``<select>`` boxes for ``ForeignKey`` fields, but, as for ``ManyToManyField``,\nsometimes you don't want to incur the overhead of having to select all the\nrelated objects to display in the drop-down. For example, if our book database\ngrows to include thousands of publishers, the \"Add book\" form could take a\nwhile to load, because it would have to load every publisher for display in the\n``<select>`` box.\n\nThe way to fix this is to use an option called ``raw_id_fields``. Set this to\na tuple of ``ForeignKey`` field names, and those fields will be displayed in\nthe admin with a simple text input box (``<input type=\"text\">``) instead of a\n``<select>``. See Figure 6-14.\n\n.. parsed-literal::\n\n    class BookAdmin(admin.ModelAdmin):\n        list_display = ('title', 'publisher', 'publication_date')\n        list_filter = ('publication_date',)\n        date_hierarchy = 'publication_date'\n        ordering = ('-publication_date',)\n        filter_horizontal = ('authors',)\n        **raw_id_fields = ('publisher',)**\n\n.. SL Tested ok\n\n.. DWP Screenshot!\n\n.. figure:: graphics/chapter06/book_editform2.png\n   :alt: Screenshot of edit form after raw_id_fields.\n\n   Figure 6-14. The book edit form after adding raw_id_fields\n\nWhat do you enter in this input box? The database ID of the publisher. Given\nthat humans don't normally memorize database IDs, there's also a\nmagnifying-glass icon that you can click to pull up a pop-up window, from which\nyou can select the publisher to add.\n\nUsers, Groups, and Permissions\n==============================\n\nBecause you're logged in as a superuser, you have access to create, edit, and\ndelete any object. Naturally, different environments require different\npermission systems -- not everybody can or should be a superuser. Django's\nadmin site uses a permissions system that you can use to give specific users\naccess only to the portions of the interface that they need.\n\nThese user accounts are meant to be generic enough to be used outside of the\nadmin interface, but we'll just treat them as admin user accounts for now. In\nChapter 14, we'll cover how to integrate user accounts with the rest of your\nsite (i.e., not just the admin site).\n\nYou can edit users and permissions through the admin interface just like any\nother object. We saw this earlier in this chapter, when we played around with\nthe User and Group sections of the admin. User objects have the standard\nusername, password, e-mail and real name fields you might expect, along with a\nset of fields that define what the user is allowed to do in the admin\ninterface. First, there's a set of three boolean flags:\n\n* The \"active\" flag controls whether the user is active at all.\n  If this flag is off and the user tries to log in, he won't be allowed in,\n  even with a valid password.\n\n* The \"staff\" flag controls whether the user is allowed to log in to the\n  admin interface (i.e., whether that user is considered a \"staff member\" in\n  your organization). Since this same user system can be used to control\n  access to public (i.e., non-admin) sites (see Chapter 14), this flag\n  differentiates between public users and administrators.\n\n* The \"superuser\" flag gives the user full access to add, create and\n  delete any item in the admin interface. If a user has this flag set, then\n  all regular permissions (or lack thereof) are ignored for that user.\n\n\"Normal\" admin users -- that is, active, non-superuser staff members -- are\ngranted admin access through assigned permissions. Each object editable through\nthe admin interface (e.g., books, authors, publishers) has three permissions: a\n*create* permission, an *edit* permission and a *delete* permission. Assigning\npermissions to a user grants the user access to do what is described by those\npermissions.\n\nWhen you create a user, that user has no permissions, and it's up to you to\ngive the user specific permissions. For example, you can give a user permission\nto add and change publishers, but not permission to delete them. Note that\nthese permissions are defined per-model, not per-object -- so they let you say\n\"John can make changes to any book,\" but they don't let you say \"John can make\nchanges to any book published by Apress.\" The latter functionality, per-object\npermissions, is a bit more complicated and is outside the scope of this book\nbut is covered in the Django documentation.\n\n.. note::\n\n    Access to edit users and permissions is also controlled by this permission\n    system. If you give someone permission to edit users, she will be able to\n    edit her own permissions, which might not be what you want! Giving a user\n    permission to edit users is essentially turning a user into a superuser.\n\nYou can also assign users to groups. A *group* is simply a set of permissions to\napply to all members of that group. Groups are useful for granting identical\npermissions to a subset of users.\n\nWhen and Why to Use the Admin Interface -- And When Not to\n==========================================================\n\nAfter having worked through this chapter, you should have a good idea of how to\nuse Django's admin site. But we want to make a point of covering *when* and\n*why* you might want to use it -- and when *not* to use it.\n\nDjango's admin site especially shines when nontechnical users need to be able\nto enter data; that's the purpose behind the feature, after all. At the\nnewspaper where Django was first developed, development of a typical online\nfeature -- say, a special report on water quality in the municipal supply --\nwould go something like this:\n\n* The reporter responsible for the project meets with one of the developers\n  and describes the available data.\n\n* The developer designs Django models to fit this data and then opens up\n  the admin site to the reporter.\n\n* The reporter inspects the admin site to point out any missing or\n  extraneous fields -- better now than later. The developer changes the\n  models iteratively.\n\n* When the models are agreed upon, the reporter begins entering data using\n  the admin site. At the same time, the programmer can focus on developing\n  the publicly accessible views/templates (the fun part!).\n\nIn other words, the raison d'être of Django's admin interface is facilitating\nthe simultaneous work of content producers and programmers.\n\nHowever, beyond these obvious data entry tasks, the admin site is useful in a\nfew other cases:\n\n* *Inspecting data models*: Once you've defined a few models, it can be\n  quite useful to call them up in the admin interface and enter some dummy\n  data. In some cases, this might reveal data-modeling mistakes or other\n  problems with your models.\n\n* *Managing acquired data*: For applications that rely on data coming from\n  external sources (e.g., users or Web crawlers), the admin site gives you\n  an easy way to inspect or edit this data. You can think of it as a less\n  powerful, but more convenient, version of your database's command-line\n  utility.\n\n* *Quick and dirty data-management apps*: You can use the admin site to\n  build yourself a very lightweight data management app -- say, to keep\n  track of expenses. If you're just building something for your own needs,\n  not for public consumption, the admin site can take you a long way. In\n  this sense, you can think of it as a beefed up, relational version of a\n  spreadsheet.\n\nOne final point we want to make clear is: the admin site is not an\nend-all-be-all. Over the years, we've seen it hacked and chopped up to serve a\nvariety of functions it wasn't intended to serve. It's not intended to be a\n*public* interface to data, nor is it intended to allow for sophisticated\nsorting and searching of your data. As we said early in this chapter, it's for\ntrusted site administrators. Keeping this sweet spot in mind is the key to\neffective admin-site usage.\n\nWhat's Next?\n============\n\nSo far we've created a few models and configured a top-notch interface for\nediting data. In the :doc:`next chapter <chapter07>`, we'll move on to the real \"meat and potatoes\"\nof Web development: form creation and processing.\n"
  },
  {
    "path": "Python/DjangoBook/chapter07.rst",
    "content": "================\nChapter 7: Forms\n================\n\nHTML forms are the backbone of interactive Web sites, from the simplicity of\nGoogle's single search box to ubiquitous blog comment-submission forms to\ncomplex custom data-entry interfaces. This chapter covers how you can use\nDjango to access user-submitted form data, validate it and do something with\nit. Along the way, we'll cover ``HttpRequest`` and ``Form`` objects.\n\nGetting Data From the Request Object\n====================================\n\nWe introduced ``HttpRequest`` objects in Chapter 3 when we first covered view\nfunctions, but we didn't have much to say about them at the time. Recall that\neach view function takes an ``HttpRequest`` object as its first parameter, as\nin our ``hello()`` view::\n\n    from django.http import HttpResponse\n\n    def hello(request):\n        return HttpResponse(\"Hello world\")\n\n``HttpRequest`` objects, such as the variable ``request`` here, have a number\nof interesting attributes and methods that you should familiarize yourself\nwith, so that you know what's possible. You can use these attributes to get\ninformation about the current request (i.e., the user/Web browser that's\nloading the current page on your Django-powered site), at the time the view\nfunction is executed.\n\nInformation About the URL\n-------------------------\n\n``HttpRequest`` objects contain several pieces of information about the\ncurrently requested URL:\n\n===========================   ====================================  ========================\nAttribute/method              Description                           Example\n===========================   ====================================  ========================\n``request.path``              The full path, not including the      ``\"/hello/\"``\n                              domain but including the leading\n                              slash.\n\n``request.get_host()``        The host (i.e., the \"domain,\" in      ``\"127.0.0.1:8000\"``\n                              common parlance).                     or ``\"www.example.com\"``\n\n``request.get_full_path()``   The ``path``, plus a query string     ``\"/hello/?print=true\"``\n                              (if available).\n\n``request.is_secure()``       ``True`` if the request was made via  ``True`` or ``False``\n                              HTTPS. Otherwise, ``False``.\n===========================   ====================================  ========================\n\nAlways use these attributes/methods instead of hard-coding URLs in your views.\nThis makes for more flexible code that can be reused in other places. A\nsimplistic example::\n\n    # BAD!\n    def current_url_view_bad(request):\n        return HttpResponse(\"Welcome to the page at /current/\")\n\n    # GOOD\n    def current_url_view_good(request):\n        return HttpResponse(\"Welcome to the page at %s\" % request.path)\n\nOther Information About the Request\n-----------------------------------\n\n``request.META`` is a Python dictionary containing all available HTTP headers\nfor the given request -- including the user's IP address and user agent\n(generally the name and version of the Web browser). Note that the full list\nof available headers depends on which headers the user sent and which headers\nyour Web server sets. Some commonly available keys in this dictionary are:\n\n* ``HTTP_REFERER`` -- The referring URL, if any. (Note the misspelling of\n  ``REFERER``.)\n* ``HTTP_USER_AGENT`` -- The user's browser's user-agent string, if any.\n  This looks something like: ``\"Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17\"``.\n* ``REMOTE_ADDR`` -- The IP address of the client, e.g., ``\"12.345.67.89\"``.\n  (If the request has passed through any proxies, then this might be a\n  comma-separated list of IP addresses, e.g., ``\"12.345.67.89,23.456.78.90\"``.)\n\nNote that because ``request.META`` is just a basic Python dictionary, you'll\nget a ``KeyError`` exception if you try to access a key that doesn't exist.\n(Because HTTP headers are *external* data -- that is, they're submitted by your\nusers' browsers -- they shouldn't be trusted, and you should always design your\napplication to fail gracefully if a particular header is empty or doesn't\nexist.) You should either use a ``try``/``except`` clause or the ``get()``\nmethod to handle the case of undefined keys::\n\n    # BAD!\n    def ua_display_bad(request):\n        ua = request.META['HTTP_USER_AGENT']  # Might raise KeyError!\n        return HttpResponse(\"Your browser is %s\" % ua)\n\n    # GOOD (VERSION 1)\n    def ua_display_good1(request):\n        try:\n            ua = request.META['HTTP_USER_AGENT']\n        except KeyError:\n            ua = 'unknown'\n        return HttpResponse(\"Your browser is %s\" % ua)\n\n    # GOOD (VERSION 2)\n    def ua_display_good2(request):\n        ua = request.META.get('HTTP_USER_AGENT', 'unknown')\n        return HttpResponse(\"Your browser is %s\" % ua)\n\nWe encourage you to write a small view that displays all of the\n``request.META`` data so you can get to know what's in there. Here's what that\nview might look like::\n\n    def display_meta(request):\n        values = request.META.items()\n        values.sort()\n        html = []\n        for k, v in values:\n            html.append('<tr><td>%s</td><td>%s</td></tr>' % (k, v))\n        return HttpResponse('<table>%s</table>' % '\\n'.join(html))\n\nAs an exercise, see whether you can convert this view to use Django's template\nsystem instead of hard-coding the HTML. Also try adding ``request.path`` and\nthe other ``HttpRequest`` methods from the previous section.\n\n.. SL Tested ok (all four view funcs above)\n\nInformation About Submitted Data\n--------------------------------\n\nBeyond basic metadata about the request, ``HttpRequest`` objects have two\nattributes that contain information submitted by the user: ``request.GET`` and\n``request.POST``. Both of these are dictionary-like objects that give you\naccess to ``GET`` and ``POST`` data.\n\n.. admonition:: Dictionary-like objects\n\n    When we say ``request.GET`` and ``request.POST`` are \"dictionary-like\"\n    objects, we mean that they behave like standard Python dictionaries but\n    aren't technically dictionaries under the hood. For example,\n    ``request.GET`` and ``request.POST`` both have ``get()``, ``keys()``\n    and ``values()`` methods, and you can iterate over the keys by doing\n    ``for key in request.GET``.\n\n    So why the distinction? Because both ``request.GET`` and ``request.POST``\n    have additional methods that normal dictionaries don't have. We'll get into\n    these in a short while.\n\n    You might have encountered the similar term \"file-like objects\" -- Python\n    objects that have a few basic methods, like ``read()``, that let them\n    act as stand-ins for \"real\" file objects.\n\n``POST`` data generally is submitted from an HTML ``<form>``, while ``GET``\ndata can come from a ``<form>`` or the query string in the page's URL.\n\nA Simple Form-Handling Example\n==============================\n\nContinuing this book's ongoing example of books, authors and publishers, let's\ncreate a simple view that lets users search our book database by title.\n\nGenerally, there are two parts to developing a form: the HTML user interface\nand the backend view code that processes the submitted data. The first part is\neasy; let's just set up a view that displays a search form::\n\n    from django.shortcuts import render\n\n    def search_form(request):\n        return render(request, 'search_form.html')\n\nAs we learned in Chapter 3, this view can live anywhere on your Python path.\nFor sake of argument, put it in ``books/views.py``.\n\nThe accompanying template, ``search_form.html``, could look like this::\n\n    <html>\n    <head>\n        <title>Search</title>\n    </head>\n    <body>\n        <form action=\"/search/\" method=\"get\">\n            <input type=\"text\" name=\"q\">\n            <input type=\"submit\" value=\"Search\">\n        </form>\n    </body>\n    </html>\n\nThe URLpattern in ``urls.py`` could look like this::\n\n    from mysite.books import views\n\n    urlpatterns = patterns('',\n        # ...\n        (r'^search-form/$', views.search_form),\n        # ...\n    )\n\n(Note that we're importing the ``views`` module directly, instead of something\nlike ``from mysite.views import search_form``, because the former is less\nverbose. We'll cover this importing approach in more detail in Chapter 8.)\n\nNow, if you run the ``runserver`` and visit\n``http://127.0.0.1:8000/search-form/``, you'll see the search interface. Simple\nenough.\n\n.. SL Tested ok\n\nTry submitting the form, though, and you'll get a Django 404 error. The form\npoints to the URL ``/search/``, which hasn't yet been implemented. Let's fix\nthat with a second view function::\n\n    # urls.py\n\n    urlpatterns = patterns('',\n        # ...\n        (r'^search-form/$', views.search_form),\n        (r'^search/$', views.search),\n        # ...\n    )\n\n    # views.py\n\n    def search(request):\n        if 'q' in request.GET:\n            message = 'You searched for: %r' % request.GET['q']\n        else:\n            message = 'You submitted an empty form.'\n        return HttpResponse(message)\n\n.. SL Tested ok\n\nFor the moment, this merely displays the user's search term, so we can make\nsure the data is being submitted to Django properly, and so you can get a feel\nfor how the search term flows through the system. In short:\n\n1. The HTML ``<form>`` defines a variable ``q``. When it's submitted, the\n   value of ``q`` is sent via ``GET`` (``method=\"get\"``) to the URL\n   ``/search/``.\n\n2. The Django view that handles the URL ``/search/`` (``search()``) has\n   access to the ``q`` value in ``request.GET``.\n\nAn important thing to point out here is that we explicitly check that ``'q'``\nexists in ``request.GET``. As we pointed out in the ``request.META`` section\nabove, you shouldn't trust anything submitted by users or even assume that\nthey've submitted anything in the first place. If we didn't add this check, any\nsubmission of an empty form would raise ``KeyError`` in the view::\n\n    # BAD!\n    def bad_search(request):\n        # The following line will raise KeyError if 'q' hasn't\n        # been submitted!\n        message = 'You searched for: %r' % request.GET['q']\n        return HttpResponse(message)\n\n.. SL Tested ok\n\n.. admonition:: Query string parameters\n\n    Because ``GET`` data is passed in the query string (e.g.,\n    ``/search/?q=django``), you can use ``request.GET`` to access query string\n    variables. In Chapter 3's introduction of Django's URLconf system, we\n    compared Django's pretty URLs to more traditional PHP/Java URLs such as\n    ``/time/plus?hours=3`` and said we'd show you how to do the latter in\n    Chapter 7. Now you know how to access query string parameters in your\n    views (like ``hours=3`` in this example) -- use ``request.GET``.\n\n``POST`` data works the same way as ``GET`` data -- just use ``request.POST``\ninstead of ``request.GET``. What's the difference between ``GET`` and ``POST``?\nUse ``GET`` when the act of submitting the form is just a request to \"get\"\ndata. Use ``POST`` whenever the act of submitting the form will have some side\neffect -- *changing* data, or sending an e-mail, or something else that's\nbeyond simple *display* of data. In our book-search example, we're using\n``GET`` because the query doesn't change any data on our server. (See\nhttp://www.w3.org/2001/tag/doc/whenToUseGet.html if you want to learn more\nabout ``GET`` and ``POST``.)\n\nNow that we've verified ``request.GET`` is being passed in properly, let's hook\nthe user's search query into our book database (again, in ``views.py``)::\n\n    from django.http import HttpResponse\n    from django.shortcuts import render\n    from mysite.books.models import Book\n\n    def search(request):\n        if 'q' in request.GET and request.GET['q']:\n            q = request.GET['q']\n            books = Book.objects.filter(title__icontains=q)\n            return render(request, 'search_results.html',\n                {'books': books, 'query': q})\n        else:\n            return HttpResponse('Please submit a search term.')\n\nA couple of notes on what we did here:\n\n* Aside from checking that ``'q'`` exists in ``request.GET``, we also make\n  sure that ``request.GET['q']`` is a non-empty value before passing it to\n  the database query.\n\n* We're using ``Book.objects.filter(title__icontains=q)`` to query our\n  book table for all books whose title includes the given submission. The\n  ``icontains`` is a lookup type (as explained in Chapter 5 and Appendix\n  B), and the statement can be roughly translated as \"Get the books whose\n  title contains ``q``, without being case-sensitive.\"\n\n  This is a very simple way to do a book search. We wouldn't recommend\n  using a simple ``icontains`` query on a large production database, as\n  it can be slow. (In the real world, you'd want to use a custom search\n  system of some sort. Search the Web for *open-source full-text search*\n  to get an idea of the possibilities.)\n\n* We pass ``books``, a list of ``Book`` objects, to the template. The\n  template code for ``search_results.html`` might include something like\n  this::\n\n      <p>You searched for: <strong>{{ query }}</strong></p>\n\n      {% if books %}\n          <p>Found {{ books|length }} book{{ books|pluralize }}.</p>\n          <ul>\n              {% for book in books %}\n              <li>{{ book.title }}</li>\n              {% endfor %}\n          </ul>\n      {% else %}\n          <p>No books matched your search criteria.</p>\n      {% endif %}\n\n  Note usage of the ``pluralize`` template filter, which outputs an \"s\"\n  if appropriate, based on the number of books found.\n\n.. SL Tested ok\n\nImproving Our Simple Form-Handling Example\n==========================================\n\nAs in previous chapters, we've shown you the simplest thing that could possibly\nwork. Now we'll point out some problems and show you how to improve it.\n\nFirst, our ``search()`` view's handling of an empty query is poor -- we're just\ndisplaying a ``\"Please submit a search term.\"`` message, requiring the user to\nhit the browser's back button. This is horrid and unprofessional, and if you\never actually implement something like this in the wild, your Django privileges\nwill be revoked.\n\nIt would be much better to redisplay the form, with an error above it, so that\nthe user can try again immediately. The easiest way to do that would be to\nrender the template again, like this:\n\n.. parsed-literal::\n\n    from django.http import HttpResponse\n    from django.shortcuts import render\n    from mysite.books.models import Book\n\n    def search_form(request):\n        return render(request, 'search_form.html')\n\n    def search(request):\n        if 'q' in request.GET and request.GET['q']:\n            q = request.GET['q']\n            books = Book.objects.filter(title__icontains=q)\n            return render(request, 'search_results.html',\n                {'books': books, 'query': q})\n        else:\n            **return render(request, 'search_form.html', {'error': True})**\n\n(Note that we've included ``search_form()`` here so you can see both views in\none place.)\n\nHere, we've improved ``search()`` to render the ``search_form.html`` template\nagain, if the query is empty. And because we need to display an error message\nin that template, we pass a template variable. Now we can edit\n``search_form.html`` to check for the ``error`` variable:\n\n.. parsed-literal::\n\n    <html>\n    <head>\n        <title>Search</title>\n    </head>\n    <body>\n        **{% if error %}**\n            **<p style=\"color: red;\">Please submit a search term.</p>**\n        **{% endif %}**\n        <form action=\"/search/\" method=\"get\">\n            <input type=\"text\" name=\"q\">\n            <input type=\"submit\" value=\"Search\">\n        </form>\n    </body>\n    </html>\n\n.. SL Tested ok\n\nWe can still use this template from our original view, ``search_form()``,\nbecause ``search_form()`` doesn't pass ``error`` to the template -- so the\nerror message won't show up in that case.\n\nWith this change in place, it's a better application, but it now begs the\nquestion: is a dedicated ``search_form()`` view really necessary? As it stands,\na request to the URL ``/search/`` (without any ``GET`` parameters) will display\nthe empty form (but with an error). We can remove the ``search_form()`` view,\nalong with its associated URLpattern, as long as we change ``search()`` to\nhide the error message when somebody visits ``/search/`` with no ``GET``\nparameters::\n\n    def search(request):\n        error = False\n        if 'q' in request.GET:\n            q = request.GET['q']\n            if not q:\n                error = True\n            else:\n                books = Book.objects.filter(title__icontains=q)\n                return render(request, 'search_results.html',\n                    {'books': books, 'query': q})\n        return render(request, 'search_form.html',\n            {'error': error})\n\n.. SL Tested ok\n\nIn this updated view, if a user visits ``/search/`` with no ``GET`` parameters,\nhe'll see the search form with no error message. If a user submits the form\nwith an empty value for ``'q'``, he'll see the search form *with* an error\nmessage. And, finally, if a user submits the form with a non-empty value for\n``'q'``, he'll see the search results.\n\nWe can make one final improvement to this application, to remove a bit of\nredundancy. Now that we've rolled the two views and URLs into one and\n``/search/`` handles both search-form display and result display, the HTML\n``<form>`` in ``search_form.html`` doesn't have to hard-code a URL. Instead\nof this::\n\n    <form action=\"/search/\" method=\"get\">\n\nIt can be changed to this::\n\n    <form action=\"\" method=\"get\">\n\nThe ``action=\"\"`` means \"Submit the form to the same URL as the current page.\"\nWith this change in place, you won't have to remember to change the ``action``\nif you ever hook the ``search()`` view to another URL.\n\nSimple validation\n=================\n\nOur search example is still reasonably simple, particularly in terms of its\ndata validation; we're merely checking to make sure the search query isn't\nempty. Many HTML forms include a level of validation that's more complex than\nmaking sure the value is non-empty. We've all seen the error messages on Web\nsites:\n\n* \"Please enter a valid e-mail address. 'foo' is not an e-mail address.\"\n* \"Please enter a valid five-digit U.S. ZIP code. '123' is not a ZIP code.\"\n* \"Please enter a valid date in the format YYYY-MM-DD.\"\n* \"Please enter a password that is at least 8 characters long and contains\n  at least one number.\"\n\n.. admonition:: A note on JavaScript validation\n\n    This is beyond the scope of this book, but you can use JavaScript to\n    validate data on the client side, directly in the browser. But be warned:\n    even if you do this, you *must* validate data on the server side, too. Some\n    people have JavaScript turned off, and some malicious users might submit\n    raw, unvalidated data directly to your form handler to see whether they can\n    cause mischief.\n\n    There's nothing you can do about this, other than *always* validate\n    user-submitted data server-side (i.e., in your Django views). You should\n    think of JavaScript validation as a bonus usability feature, not as your\n    only means of validating.\n\nLet's tweak our ``search()`` view so that it validates that the search term is\nless than or equal to 20 characters long. (For sake of example, let's say\nanything longer than that might make the query too slow.) How might we do that?\nThe simplest possible thing would be to embed the logic directly in the view,\nlike this:\n\n.. parsed-literal::\n\n    def search(request):\n        error = False\n        if 'q' in request.GET:\n            q = request.GET['q']\n            if not q:\n                error = True\n            **elif len(q) > 20:**\n                **error = True**\n            else:\n                books = Book.objects.filter(title__icontains=q)\n                return render(request, 'search_results.html',\n                    {'books': books, 'query': q})\n        return render(request, 'search_form.html',\n            {'error': error})\n\nNow, if you try submitting a search query greater than 20 characters long,\nit won't let you search; you'll get an error message. But that error message\nin ``search_form.html`` currently says ``\"Please submit a search term.\"`` --\nso we'll have to change it to be accurate for both cases:\n\n.. parsed-literal::\n\n    <html>\n    <head>\n        <title>Search</title>\n    </head>\n    <body>\n        {% if error %}\n            <p style=\"color: red;\">Please submit a search term 20 characters or shorter.</p>\n        {% endif %}\n        <form action=\"/search/\" method=\"get\">\n            <input type=\"text\" name=\"q\">\n            <input type=\"submit\" value=\"Search\">\n        </form>\n    </body>\n    </html>\n\n.. SL Tested ok\n\nThere's something ugly about this. Our one-size-fits-all error message is\npotentially confusing. Why should the error message for an empty form\nsubmission mention anything about a 20-character limit? Error messages should\nbe specific, unambiguous and not confusing.\n\nThe problem is in the fact that we're using a simple boolean value for\n``error``, whereas we should be using a *list* of error message strings. Here's\nhow we might fix that:\n\n.. parsed-literal::\n\n    def search(request):\n        **errors = []**\n        if 'q' in request.GET:\n            q = request.GET['q']\n            if not q:\n                **errors.append('Enter a search term.')**\n            elif len(q) > 20:\n                **errors.append('Please enter at most 20 characters.')**\n            else:\n                books = Book.objects.filter(title__icontains=q)\n                return render(request, 'search_results.html',\n                    {'books': books, 'query': q})\n        return render(request, 'search_form.html',\n            {**'errors': errors**})\n\nThen, we need make a small tweak to the ``search_form.html`` template to\nreflect that it's now passed an ``errors`` list instead of an ``error`` boolean\nvalue:\n\n.. parsed-literal::\n\n    <html>\n    <head>\n        <title>Search</title>\n    </head>\n    <body>\n        **{% if errors %}**\n            **<ul>**\n                **{% for error in errors %}**\n                **<li>{{ error }}</li>**\n                **{% endfor %}**\n            **</ul>**\n        **{% endif %}**\n        <form action=\"/search/\" method=\"get\">\n            <input type=\"text\" name=\"q\">\n            <input type=\"submit\" value=\"Search\">\n        </form>\n    </body>\n    </html>\n\n.. SL Tested ok\n\nMaking a Contact Form\n=====================\n\nAlthough we iterated over the book search form example several times and\nimproved it nicely, it's still fundamentally simple: just a single field,\n``'q'``. Because it's so simple, we didn't even use Django's form library to\ndeal with it. But more complex forms call for more complex treatment -- and now\nwe'll develop something more complex: a site contact form.\n\nThis will be a form that lets site users submit a bit of feedback, along with\nan optional e-mail return address. After the form is submitted and the\ndata is validated, we'll automatically send the message via e-mail to the site\nstaff.\n\nWe'll start with our template, ``contact_form.html``.\n\n.. parsed-literal::\n\n    <html>\n    <head>\n        <title>Contact us</title>\n    </head>\n    <body>\n        <h1>Contact us</h1>\n\n        {% if errors %}\n            <ul>\n                {% for error in errors %}\n                <li>{{ error }}</li>\n                {% endfor %}\n            </ul>\n        {% endif %}\n\n        <form action=\"/contact/\" method=\"post\">\n            <p>Subject: <input type=\"text\" name=\"subject\"></p>\n            <p>Your e-mail (optional): <input type=\"text\" name=\"email\"></p>\n            <p>Message: <textarea name=\"message\" rows=\"10\" cols=\"50\"></textarea></p>\n            <input type=\"submit\" value=\"Submit\">\n        </form>\n    </body>\n    </html>\n\nWe've defined three fields: the subject, e-mail address and message. The second\nis optional, but the other two fields are required. Note we're using\n``method=\"post\"`` here instead of ``method=\"get\"`` because this form submission\nhas a side effect -- it sends an e-mail. Also, we copied the error-displaying\ncode from our previous template ``search_form.html``.\n\nIf we continue down the road established by our ``search()`` view from the\nprevious section, a naive version of our ``contact()`` view might look like\nthis::\n\n    from django.core.mail import send_mail\n    from django.http import HttpResponseRedirect\n    from django.shortcuts import render\n\n    def contact(request):\n        errors = []\n        if request.method == 'POST':\n            if not request.POST.get('subject', ''):\n                errors.append('Enter a subject.')\n            if not request.POST.get('message', ''):\n                errors.append('Enter a message.')\n            if request.POST.get('email') and '@' not in request.POST['email']:\n                errors.append('Enter a valid e-mail address.')\n            if not errors:\n                send_mail(\n                    request.POST['subject'],\n                    request.POST['message'],\n                    request.POST.get('email', 'noreply@example.com'),\n                    ['siteowner@example.com'],\n                )\n                return HttpResponseRedirect('/contact/thanks/')\n        return render(request, 'contact_form.html',\n            {'errors': errors})\n\n.. SL Tested ok (modulo email config and lack of thanks view)\n\n(If you're following along, you may be wondering whether to put this view in\nthe ``books/views.py`` file. It doesn't have anything to do with the books\napplication, so should it live elsewhere? It's totally up to you; Django\ndoesn't care, as long as you're able to point to the view from your URLconf.\nOur personal preference would be to create a separate directory, ``contact``,\nat the same level in the directory tree as ``books``. This would contain an\nempty ``__init__.py`` and ``views.py``.)\n\nA couple of new things are happening here:\n\n* We're checking that ``request.method`` is ``'POST'``. This will only be\n  true in the case of a form submission; it won't be true if somebody is\n  merely viewing the contact form. (In the latter case,\n  ``request.method will be set to 'GET'``, because in normal Web browsing,\n  browsers use ``GET``, not ``POST``.) This makes it a nice way to isolate\n  the \"form display\" case from the \"form processing\" case.\n\n* Instead of ``request.GET``, we're using ``request.POST`` to access the\n  submitted form data. This is necessary because the HTML ``<form>`` in\n  ``contact_form.html`` uses ``method=\"post\"``. If this view is accessed\n  via ``POST``, then ``request.GET`` will be empty.\n\n* This time, we have *two* required fields, ``subject`` and ``message``, so\n  we have to validate both. Note that we're using ``request.POST.get()``\n  and providing a blank string as the default value; this is a nice, short\n  way of handling both the cases of missing keys and missing data.\n\n* Although the ``email`` field is not required, we still validate it if it\n  is indeed submitted. Our validation algorithm here is fragile -- we're\n  just checking that the string contains an ``@`` character. In the real\n  world, you'd want more robust validation (and Django provides it, which\n  we'll show you very shortly).\n\n* We're using the function ``django.core.mail.send_mail`` to send an\n  e-mail. This function has four required arguments: the e-mail subject,\n  the e-mail body, the \"from\" address, and a list of recipient addresses.\n  ``send_mail`` is a convenient wrapper around Django's ``EmailMessage``\n  class, which provides advanced features such as attachments, multipart\n  e-mails, and full control over e-mail headers.\n\n  Note that in order to send e-mail using ``send_mail()``, your server must\n  be configured to send mail, and Django must be told about your outbound\n  e-mail server. See http://docs.djangoproject.com/en/dev/topics/email/ for\n  the specifics.\n\n* After the e-mail is sent, we redirect to a \"success\" page by returning an\n  ``HttpResponseRedirect`` object. We'll leave the implementation of that\n  \"success\" page up to you (it's a simple view/URLconf/template), but we\n  should explain why we initiate a redirect instead of, for example, simply\n  calling ``render()`` with a template right there.\n\n  The reason: if a user hits \"Refresh\" on a page that was loaded via\n  ``POST``, that request will be repeated. This can often lead to undesired\n  behavior, such as a duplicate record being added to the database -- or,\n  in our example, the e-mail being sent twice. If the user is redirected to\n  another page after the ``POST``, then there's no chance of repeating the\n  request.\n\n  You should *always* issue a redirect for successful ``POST`` requests.\n  It's a Web development best practice.\n\nThis view works, but those validation functions are kind of crufty. Imagine\nprocessing a form with a dozen fields; would you really want to have to write\nall of those ``if`` statements?\n\nAnother problem is *form redisplay*. In the case of validation errors, it's\nbest practice to redisplay the form *with* the previously submitted data\nalready filled in, so the user can see what he did wrong (and also so the user\ndoesn't have to reenter data in fields that were submitted correctly). We\n*could* manually pass the ``POST`` data back to the template, but we'd have to\nedit each HTML field to insert the proper value in the proper place:\n\n.. parsed-literal::\n\n    # views.py\n\n    def contact(request):\n        errors = []\n        if request.method == 'POST':\n            if not request.POST.get('subject', ''):\n                errors.append('Enter a subject.')\n            if not request.POST.get('message', ''):\n                errors.append('Enter a message.')\n            if request.POST.get('email') and '@' not in request.POST['email']:\n                errors.append('Enter a valid e-mail address.')\n            if not errors:\n                send_mail(\n                    request.POST['subject'],\n                    request.POST['message'],\n                    request.POST.get('email', 'noreply@example.com'),\n                    ['siteowner@example.com'],\n                )\n                return HttpResponseRedirect('/contact/thanks/')\n        return render(request, 'contact_form.html', {\n            'errors': errors,\n            **'subject': request.POST.get('subject', ''),**\n            **'message': request.POST.get('message', ''),**\n            **'email': request.POST.get('email', ''),**\n        })\n\n    # contact_form.html\n\n    <html>\n    <head>\n        <title>Contact us</title>\n    </head>\n    <body>\n        <h1>Contact us</h1>\n\n        {% if errors %}\n            <ul>\n                {% for error in errors %}\n                <li>{{ error }}</li>\n                {% endfor %}\n            </ul>\n        {% endif %}\n\n        <form action=\"/contact/\" method=\"post\">\n            <p>Subject: <input type=\"text\" name=\"subject\" **value=\"{{ subject }}\"**></p>\n            <p>Your e-mail (optional): <input type=\"text\" name=\"email\" **value=\"{{ email }}\"**></p>\n            <p>Message: <textarea name=\"message\" rows=\"10\" cols=\"50\">**{{ message }}**</textarea></p>\n            <input type=\"submit\" value=\"Submit\">\n        </form>\n    </body>\n    </html>\n\n.. SL Tested ok\n\nThis is a lot of cruft, and it introduces a lot of opportunities for human\nerror. We hope you're starting to see the opportunity for some higher-level\nlibrary that handles form- and validation-related tasks.\n\nYour First Form Class\n=====================\n\nDjango comes with a form library, called ``django.forms``, that handles many of\nthe issues we've been exploring this chapter -- from HTML form display to\nvalidation. Let's dive in and rework our contact form application using the\nDjango forms framework.\n\n.. admonition:: Django's \"newforms\" library\n\n    Throughout the Django community, you might see chatter about something\n    called ``django.newforms``. When people speak of ``django.newforms``,\n    they're talking about what is now ``django.forms`` -- the library covered by\n    this chapter.\n\n    The reason for this name change is historic. When Django was first released\n    to the public, it had a complicated, confusing forms system,\n    ``django.forms``. It was completely rewritten, and the new version was\n    called ``django.newforms`` so that people could still use the old system.\n    When Django 1.0 was released, the old ``django.forms`` went away, and\n    ``django.newforms`` became ``django.forms``.\n\nThe primary way to use the forms framework is to define a ``Form`` class for\neach HTML ``<form>`` you're dealing with. In our case, we only have one\n``<form>``, so we'll have one ``Form`` class. This class can live anywhere you\nwant -- including directly in your ``views.py`` file -- but community\nconvention is to keep ``Form`` classes in a separate file called ``forms.py``.\nCreate this file in the same directory as your ``views.py``, and enter the\nfollowing::\n\n    from django import forms\n\n    class ContactForm(forms.Form):\n        subject = forms.CharField()\n        email = forms.EmailField(required=False)\n        message = forms.CharField()\n\nThis is pretty intuitive, and it's similar to Django's model syntax. Each field\nin the form is represented by a type of ``Field`` class -- ``CharField`` and\n``EmailField`` are the only types of fields used here -- as attributes of a\n``Form`` class. Each field is required by default, so to make ``email``\noptional, we specify ``required=False``.\n\nLet's hop into the Python interactive interpreter and see what this class can\ndo. The first thing it can do is display itself as HTML::\n\n    >>> from contact.forms import ContactForm\n    >>> f = ContactForm()\n    >>> print f\n    <tr><th><label for=\"id_subject\">Subject:</label></th><td><input type=\"text\" name=\"subject\" id=\"id_subject\" /></td></tr>\n    <tr><th><label for=\"id_email\">Email:</label></th><td><input type=\"text\" name=\"email\" id=\"id_email\" /></td></tr>\n    <tr><th><label for=\"id_message\">Message:</label></th><td><input type=\"text\" name=\"message\" id=\"id_message\" /></td></tr>\n\n.. SL Tested ok\n\nDjango adds a label to each field, along with ``<label>`` tags for\naccessibility. The idea is to make the default behavior as optimal as possible.\n\nThis default output is in the format of an HTML ``<table>``, but there are a\nfew other built-in outputs::\n\n    >>> print f.as_ul()\n    <li><label for=\"id_subject\">Subject:</label> <input type=\"text\" name=\"subject\" id=\"id_subject\" /></li>\n    <li><label for=\"id_email\">Email:</label> <input type=\"text\" name=\"email\" id=\"id_email\" /></li>\n    <li><label for=\"id_message\">Message:</label> <input type=\"text\" name=\"message\" id=\"id_message\" /></li>\n    >>> print f.as_p()\n    <p><label for=\"id_subject\">Subject:</label> <input type=\"text\" name=\"subject\" id=\"id_subject\" /></p>\n    <p><label for=\"id_email\">Email:</label> <input type=\"text\" name=\"email\" id=\"id_email\" /></p>\n    <p><label for=\"id_message\">Message:</label> <input type=\"text\" name=\"message\" id=\"id_message\" /></p>\n\n.. SL Tested ok\n\nNote that the opening and closing ``<table>``, ``<ul>`` and ``<form>`` tags\naren't included in the output, so that you can add any additional rows and\ncustomization if necessary.\n\nThese methods are just shortcuts for the common case of \"display the entire\nform.\" You can also display the HTML for a particular field::\n\n    >>> print f['subject']\n    <input type=\"text\" name=\"subject\" id=\"id_subject\" />\n    >>> print f['message']\n    <input type=\"text\" name=\"message\" id=\"id_message\" />\n\n.. SL Tested ok\n\nThe second thing ``Form`` objects can do is validate data. To validate data,\ncreate a new ``Form`` object and pass it a dictionary of data that maps field\nnames to data::\n\n    >>> f = ContactForm({'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'})\n\nOnce you've associated data with a ``Form`` instance, you've created a \"bound\"\nform::\n\n    >>> f.is_bound\n    True\n\n.. SL Tested ok\n\nCall the ``is_valid()`` method on any bound ``Form`` to find out whether its\ndata is valid. We've passed a valid value for each field, so the ``Form`` in\nits entirety is valid::\n\n    >>> f.is_valid()\n    True\n\n.. SL Tested ok\n\nIf we don't pass the ``email`` field, it's still valid, because we've specified\n``required=False`` for that field::\n\n    >>> f = ContactForm({'subject': 'Hello', 'message': 'Nice site!'})\n    >>> f.is_valid()\n    True\n\n.. SL Tested ok\n\nBut, if we leave off either ``subject`` or ``message``, the ``Form`` is no\nlonger valid::\n\n    >>> f = ContactForm({'subject': 'Hello'})\n    >>> f.is_valid()\n    False\n    >>> f = ContactForm({'subject': 'Hello', 'message': ''})\n    >>> f.is_valid()\n    False\n\n.. SL Tested ok\n\nYou can drill down to get field-specific error messages::\n\n    >>> f = ContactForm({'subject': 'Hello', 'message': ''})\n    >>> f['message'].errors\n    [u'This field is required.']\n    >>> f['subject'].errors\n    []\n    >>> f['email'].errors\n    []\n\n.. SL Tested ok\n\nEach bound ``Form`` instance has an ``errors`` attribute that gives you a\ndictionary mapping field names to error-message lists::\n\n    >>> f = ContactForm({'subject': 'Hello', 'message': ''})\n    >>> f.errors\n    {'message': [u'This field is required.']}\n\n.. SL Tested ok\n\nFinally, for ``Form`` instances whose data has been found to be valid, a\n``cleaned_data`` attribute is available. This is a dictionary of the\nsubmitted data, \"cleaned up.\" Django's forms framework not only validates\ndata, it cleans it up by converting values to the appropriate Python types.\n\n    >>> f = ContactForm({'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'})\n    >>> f.is_valid()\n    True\n    >>> f.cleaned_data\n    {'message': u'Nice site!', 'email': u'adrian@example.com', 'subject': u'Hello'}\n\n.. SL Tested ok\n\nOur contact form only deals with strings, which are \"cleaned\" into Unicode\nobjects -- but if we were to use an ``IntegerField`` or ``DateField``, the\nforms framework would ensure that ``cleaned_data`` used proper Python\nintegers or ``datetime.date`` objects for the given fields.\n\nTying Form Objects Into Views\n=============================\n\nWith some basic knowledge about ``Form`` classes, you might see how we can use\nthis infrastructure to replace some of the cruft in our ``contact()`` view.\nHere's how we can rewrite ``contact()`` to use the forms framework::\n\n    # views.py\n\n    from django.shortcuts import render\n    from mysite.contact.forms import ContactForm\n\n    def contact(request):\n        if request.method == 'POST':\n            form = ContactForm(request.POST)\n            if form.is_valid():\n                cd = form.cleaned_data\n                send_mail(\n                    cd['subject'],\n                    cd['message'],\n                    cd.get('email', 'noreply@example.com'),\n                    ['siteowner@example.com'],\n                )\n                return HttpResponseRedirect('/contact/thanks/')\n        else:\n            form = ContactForm()\n        return render(request, 'contact_form.html', {'form': form})\n\n    # contact_form.html\n\n    <html>\n    <head>\n        <title>Contact us</title>\n    </head>\n    <body>\n        <h1>Contact us</h1>\n\n        {% if form.errors %}\n            <p style=\"color: red;\">\n                Please correct the error{{ form.errors|pluralize }} below.\n            </p>\n        {% endif %}\n\n        <form action=\"\" method=\"post\">\n            <table>\n                {{ form.as_table }}\n            </table>\n            <input type=\"submit\" value=\"Submit\">\n        </form>\n    </body>\n    </html>\n\n.. SL Tested ok\n\nLook at how much cruft we've been able to remove! Django's forms framework\nhandles the HTML display, the validation, data cleanup and form\nredisplay-with-errors.\n\nTry running this locally. Load the form, submit it with none of the fields\nfilled out, submit it with an invalid e-mail address, then finally submit it\nwith valid data. (Of course, depending on your mail-server configuration, you\nmight get an error when ``send_mail()`` is called, but that's another issue.)\n\nChanging How Fields Are Rendered\n================================\n\nProbably the first thing you'll notice when you render this form locally is\nthat the ``message`` field is displayed as an ``<input type=\"text\">``, and it\nought to be a ``<textarea>``. We can fix that by setting the field's *widget*:\n\n.. parsed-literal::\n\n    from django import forms\n\n    class ContactForm(forms.Form):\n        subject = forms.CharField()\n        email = forms.EmailField(required=False)\n        message = forms.CharField(**widget=forms.Textarea**)\n\n.. SL Tested ok\n\nThe forms framework separates out the presentation logic for each field into a\nset of widgets. Each field type has a default widget, but you can easily\noverride the default, or provide a custom widget of your own.\n\nThink of the ``Field`` classes as representing *validation logic*, while\nwidgets represent *presentation logic*.\n\nSetting a Maximum Length\n========================\n\nOne of the most common validation needs is to check that a field is of a\ncertain size. For good measure, we should improve our ``ContactForm`` to limit\nthe ``subject`` to 100 characters. To do that, just supply a ``max_length`` to\nthe ``CharField``, like this:\n\n.. parsed-literal::\n\n    from django import forms\n\n    class ContactForm(forms.Form):\n        subject = forms.CharField(**max_length=100**)\n        email = forms.EmailField(required=False)\n        message = forms.CharField(widget=forms.Textarea)\n\nAn optional ``min_length`` argument is also available.\n\nSetting Initial Values\n======================\n\nAs an improvement to this form, let's add an *initial value* for the\n``subject`` field: ``\"I love your site!\"`` (A little power of suggestion can't\nhurt.) To do this, we can use the ``initial`` argument when we create a\n``Form`` instance:\n\n.. parsed-literal::\n\n    def contact(request):\n        if request.method == 'POST':\n            form = ContactForm(request.POST)\n            if form.is_valid():\n                cd = form.cleaned_data\n                send_mail(\n                    cd['subject'],\n                    cd['message'],\n                    cd.get('email', 'noreply@example.com'),\n                    ['siteowner@example.com'],\n                )\n                return HttpResponseRedirect('/contact/thanks/')\n        else:\n            form = ContactForm(\n                **initial={'subject': 'I love your site!'}**\n            )\n        return render(request, 'contact_form.html', {'form': form})\n\n.. SL Tested ok\n\nNow, the ``subject`` field will be displayed prepopulated with that kind\nstatement.\n\nNote that there is a difference between passing *initial* data and passing\ndata that *binds* the form. The biggest difference is that if you're just\npassing *initial* data, then the form will be *unbound*, which means it won't\nhave any error messages.\n\nCustom Validation Rules\n=======================\n\nImagine we've launched our feedback form, and the e-mails have started tumbling\nin. There's just one problem: some of the submitted messages are just one or\ntwo words, which isn't long enough for us to make sense of. We decide to adopt\na new validation policy: four words or more, please.\n\nThere are a number of ways to hook custom validation into a Django form. If our\nrule is something we will reuse again and again, we can create a custom field\ntype. Most custom validations are one-off affairs, though, and can be tied\ndirectly to the ``Form`` class.\n\nWe want additional validation on the ``message`` field, so we add a\n``clean_message()`` method to our ``Form`` class:\n\n.. parsed-literal::\n\n    from django import forms\n\n    class ContactForm(forms.Form):\n        subject = forms.CharField(max_length=100)\n        email = forms.EmailField(required=False)\n        message = forms.CharField(widget=forms.Textarea)\n\n        def clean_message(self):\n            message = self.cleaned_data['message']\n            num_words = len(message.split())\n            if num_words < 4:\n                raise forms.ValidationError(\"Not enough words!\")\n            return message\n\n.. SL Tested ok\n\nDjango's form system automatically looks for any method whose name starts with\n``clean_`` and ends with the name of a field. If any such method exists, it's\ncalled during validation.\n\nSpecifically, the ``clean_message()`` method will be called *after* the default\nvalidation logic for a given field (in this case, the validation logic for a\nrequired ``CharField``). Because the field data has already been partially\nprocessed, we pull it out of ``self.cleaned_data``. Also, we don't have to\nworry about checking that the value exists and is non-empty; that's done by the\ndefault validator.\n\nWe naively use a combination of ``len()`` and ``split()`` to count the number\nof words. If the user has entered too few words, we raise a\n``forms.ValidationError``. The string attached to this exception will be\ndisplayed to the user as an item in the error list.\n\nIt's important that we explicitly return the cleaned value for the field at the\nend of the method. This allows us to modify the value (or convert it to a\ndifferent Python type) within our custom validation method. If we forget the\nreturn statement, then ``None`` will be returned, and the original value will\nbe lost.\n\nSpecifying labels\n=================\n\nBy default, the labels on Django's auto-generated form HTML are created by\nreplacing underscores with spaces and capitalizing the first letter -- so the\nlabel for the ``email`` field is ``\"Email\"``. (Sound familiar? It's the same\nsimple algorithm that Django's models use to calculate default ``verbose_name``\nvalues for fields. We covered this in Chapter 5.)\n\nBut, as with Django's models, we can customize the label for a given field.\nJust use ``label``, like so:\n\n.. parsed-literal::\n\n    class ContactForm(forms.Form):\n        subject = forms.CharField(max_length=100)\n        email = forms.EmailField(required=False, **label='Your e-mail address'**)\n        message = forms.CharField(widget=forms.Textarea)\n\n.. SL Tested ok\n\nCustomizing Form Design\n=======================\n\nOur ``contact_form.html`` template uses ``{{ form.as_table }}`` to display the\nform, but we can display the form in other ways to get more granular control\nover display.\n\nThe quickest way to customize forms' presentation is with CSS. Error lists, in\nparticular, could do with some visual enhancement, and the auto-generated error\nlists use ``<ul class=\"errorlist\">`` precisely so that you can target them with\nCSS. The following CSS really makes our errors stand out::\n\n    <style type=\"text/css\">\n        ul.errorlist {\n            margin: 0;\n            padding: 0;\n        }\n        .errorlist li {\n            background-color: red;\n            color: white;\n            display: block;\n            font-size: 10px;\n            margin: 0 0 3px;\n            padding: 4px 5px;\n        }\n    </style>\n\n.. SL Tested ok\n\nWhile it's convenient to have our form's HTML generated for us, in many\ncases you'll want to override the default rendering. ``{{ form.as_table }}``\nand friends are useful shortcuts while you develop your application, but\neverything about the way a form is displayed can be overridden, mostly within\nthe template itself, and you'll probably find yourself doing this.\n\nEach field's widget (``<input type=\"text\">``, ``<select>``, ``<textarea>``,\netc.) can be rendered individually by accessing ``{{ form.fieldname }}`` in the\ntemplate, and any errors associated with a field are available as\n``{{ form.fieldname.errors }}``. With this in mind, we can construct a custom\ntemplate for our contact form with the following template code::\n\n    <html>\n    <head>\n        <title>Contact us</title>\n    </head>\n    <body>\n        <h1>Contact us</h1>\n\n        {% if form.errors %}\n            <p style=\"color: red;\">\n                Please correct the error{{ form.errors|pluralize }} below.\n            </p>\n        {% endif %}\n\n        <form action=\"\" method=\"post\">\n            <div class=\"field\">\n                {{ form.subject.errors }}\n                <label for=\"id_subject\">Subject:</label>\n                {{ form.subject }}\n            </div>\n            <div class=\"field\">\n                {{ form.email.errors }}\n                <label for=\"id_email\">Your e-mail address:</label>\n                {{ form.email }}\n            </div>\n            <div class=\"field\">\n                {{ form.message.errors }}\n                <label for=\"id_message\">Message:</label>\n                {{ form.message }}\n            </div>\n            <input type=\"submit\" value=\"Submit\">\n        </form>\n    </body>\n    </html>\n\n``{{ form.message.errors }}`` displays a ``<ul class=\"errorlist\">`` if errors\nare present and a blank string if the field is valid (or the form is unbound).\nWe can also treat ``form.message.errors`` as a Boolean or even iterate\nover it as a list. For example::\n\n    <div class=\"field{% if form.message.errors %} errors{% endif %}\">\n        {% if form.message.errors %}\n            <ul>\n            {% for error in form.message.errors %}\n                <li><strong>{{ error }}</strong></li>\n            {% endfor %}\n            </ul>\n        {% endif %}\n        <label for=\"id_message\">Message:</label>\n        {{ form.message }}\n    </div>\n\n.. SL Tested ok\n\nIn the case of validation errors, this will add an \"errors\" class to the\ncontaining ``<div>`` and display the list of errors in an unordered list.\n\nWhat's Next?\n============\n\nThis chapter concludes the introductory material in this book -- the so-called\n\"core curriculum.\" The next section of the book, Chapters 8 to 12, goes into\nmore detail about advanced Django usage, including how to deploy a Django\napplication (Chapter 12).\n\nAfter these first seven chapters, you should know enough to start writing your\nown Django projects. The rest of the material in this book will help fill in the\nmissing pieces as you need them.\n\nWe'll start in :doc:`chapter08` by doubling back and taking a closer look at views\nand URLconfs (introduced first in :doc:`chapter03`).\n"
  },
  {
    "path": "Python/DjangoBook/chapter08.rst",
    "content": "======================================\nChapter 8: Advanced Views and URLconfs\n======================================\n\n.. SL Note: as the code examples in this chapter are expository, and\n.. SL are not complete runnable examples, I'm proof-reading by eye\n.. SL and running an automated syntax check on them to test them.\n\nIn `Chapter 3`_, we explained the basics of Django view functions and URLconfs.\nThis chapter goes into more detail about advanced functionality in those two\npieces of the framework.\n\n.. _Chapter 3: ../chapter03/\n\nURLconf Tricks\n==============\n\nThere's nothing \"special\" about URLconfs -- like anything else in Django,\nthey're just Python code. You can take advantage of this in several ways, as\ndescribed in the sections that follow.\n\nStreamlining Function Imports\n-----------------------------\n\nConsider this URLconf, which builds on the example in Chapter 3::\n\n    from django.conf.urls.defaults import *\n    from mysite.views import hello, current_datetime, hours_ahead\n\n    urlpatterns = patterns('',\n        (r'^hello/$', hello),\n        (r'^time/$', current_datetime),\n        (r'^time/plus/(\\d{1,2})/$', hours_ahead),\n    )\n\nAs explained in Chapter 3, each entry in the URLconf includes its associated\nview function, passed directly as a function object. This means it's necessary\nto import the view functions at the top of the module.\n\nBut as a Django application grows in complexity, its URLconf grows, too, and\nkeeping those imports can be tedious to manage. (For each new view function,\nyou have to remember to import it, and the import statement tends to get\noverly long if you use this approach.) It's possible to avoid that tedium by\nimporting the ``views`` module itself. This example URLconf is equivalent to\nthe previous one:\n\n.. parsed-literal::\n\n    from django.conf.urls.defaults import *\n    **from mysite import views**\n\n    urlpatterns = patterns('',\n        (r'^hello/$', **views.hello**),\n        (r'^time/$', **views.current_datetime**),\n        (r'^time/plus/(\\d{1,2})/$', **views.hours_ahead**),\n    )\n\nDjango offers another way of specifying the view function for a particular\npattern in the URLconf: you can pass a string containing the module name and\nfunction name rather than the function object itself. Continuing the ongoing\nexample:\n\n.. parsed-literal::\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^hello/$', **'mysite.views.hello'**),\n        (r'^time/$', **'mysite.views.current_datetime'**),\n        (r'^time/plus/(\\d{1,2})/$', **'mysite.views.hours_ahead'**),\n    )\n\n(Note the quotes around the view names. We're using\n``'mysite.views.current_datetime'`` -- with quotes -- instead of\n``mysite.views.current_datetime``.)\n\nUsing this technique, it's no longer necessary to import the view functions;\nDjango automatically imports the appropriate view function the first time it's\nneeded, according to the string describing the name and path of the view\nfunction.\n\nA further shortcut you can take when using the string technique is to factor\nout a common \"view prefix.\" In our URLconf example, each of the view strings\nstarts with ``'mysite.views'``, which is redundant to type. We can factor out\nthat common prefix and pass it as the first argument to ``patterns()``, like\nthis:\n\n.. parsed-literal::\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns(**'mysite.views'**,\n        (r'^hello/$', **'hello'**),\n        (r'^time/$', **'current_datetime'**),\n        (r'^time/plus/(\\d{1,2})/$', **'hours_ahead'**),\n    )\n\nNote that you don't put a trailing dot (``\".\"``) in the prefix, nor do you put\na leading dot in the view strings. Django puts those in automatically.\n\nWith these two approaches in mind, which is better? It really depends on your\npersonal coding style and needs.\n\nAdvantages of the string approach are as follows:\n\n* It's more compact, because it doesn't require you to import the view\n  functions.\n\n* It results in more readable and manageable URLconfs if your view\n  functions are spread across several different Python modules.\n\nAdvantages of the function object approach are as follows:\n\n* It allows for easy \"wrapping\" of view functions. See the section \"Wrapping View\n  Functions\" later in this chapter.\n\n* It's more \"Pythonic\" -- that is, it's more in line with Python\n  traditions, such as passing functions as objects.\n\nBoth approaches are valid, and you can even mix them within the same URLconf.\nThe choice is yours.\n\nUsing Multiple View Prefixes\n----------------------------\n\nIn practice, if you use the string technique, you'll probably end up mixing\nviews to the point where the views in your URLconf won't have a common prefix.\nHowever, you can still take advantage of the view prefix shortcut to\nremove duplication. Just add multiple ``patterns()`` objects together, like\nthis:\n\nOld::\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^hello/$', 'mysite.views.hello'),\n        (r'^time/$', 'mysite.views.current_datetime'),\n        (r'^time/plus/(\\d{1,2})/$', 'mysite.views.hours_ahead'),\n        (r'^tag/(\\w+)/$', 'weblog.views.tag'),\n    )\n\nNew::\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('mysite.views',\n        (r'^hello/$', 'hello'),\n        (r'^time/$', 'current_datetime'),\n        (r'^time/plus/(\\d{1,2})/$', 'hours_ahead'),\n    )\n\n    urlpatterns += patterns('weblog.views',\n        (r'^tag/(\\w+)/$', 'tag'),\n    )\n\nAll the framework cares about is that there's a module-level variable called\n``urlpatterns``. This variable can be constructed dynamically, as we do in this\nexample. We should specifically point out that the objects returned by\n``patterns()`` can be added together, which is something you might not have\nexpected.\n\nSpecial-Casing URLs in Debug Mode\n---------------------------------\n\nSpeaking of constructing ``urlpatterns`` dynamically, you might want to take\nadvantage of this technique to alter your URLconf's behavior while in Django's\ndebug mode. To do this, just check the value of the ``DEBUG`` setting at\nruntime, like so::\n\n    from django.conf import settings\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^$', views.homepage),\n        (r'^(\\d{4})/([a-z]{3})/$', views.archive_month),\n    )\n\n    if settings.DEBUG:\n        urlpatterns += patterns('',\n            (r'^debuginfo/$', views.debug),\n        )\n\nIn this example, the URL ``/debuginfo/`` will only be available if your\n``DEBUG`` setting is set to ``True``.\n\nUsing Named Groups\n------------------\n\nIn all of our URLconf examples so far, we've used simple, *non-named*\nregular expression groups -- that is, we put parentheses around parts of the URL\nwe wanted to capture, and Django passes that captured text to the view\nfunction as a positional argument. In more advanced usage, it's possible to use\n*named* regular expression groups to capture URL bits and pass them as\n*keyword* arguments to a view.\n\n.. admonition:: Keyword Arguments vs. Positional Arguments\n\n    A Python function can be called using keyword arguments or positional\n    arguments -- and, in some cases, both at the same time. In a keyword\n    argument call, you specify the names of the arguments along with the values\n    you're passing. In a positional argument call, you simply pass the\n    arguments without explicitly specifying which argument matches which value;\n    the association is implicit in the arguments' order.\n\n    For example, consider this simple function::\n\n        def sell(item, price, quantity):\n            print \"Selling %s unit(s) of %s at %s\" % (quantity, item, price)\n\n    To call it with positional arguments, you specify the arguments in the\n    order in which they're listed in the function definition::\n\n        sell('Socks', '$2.50', 6)\n\n    To call it with keyword arguments, you specify the names of the arguments\n    along with the values. The following statements are equivalent::\n\n        sell(item='Socks', price='$2.50', quantity=6)\n        sell(item='Socks', quantity=6, price='$2.50')\n        sell(price='$2.50', item='Socks', quantity=6)\n        sell(price='$2.50', quantity=6, item='Socks')\n        sell(quantity=6, item='Socks', price='$2.50')\n        sell(quantity=6, price='$2.50', item='Socks')\n\n    Finally, you can mix keyword and positional arguments, as long as all\n    positional arguments are listed before keyword arguments. The following\n    statements are equivalent to the previous examples::\n\n        sell('Socks', '$2.50', quantity=6)\n        sell('Socks', price='$2.50', quantity=6)\n        sell('Socks', quantity=6, price='$2.50')\n\nIn Python regular expressions, the syntax for named regular expression groups\nis ``(?P<name>pattern)``, where ``name`` is the name of the group and\n``pattern`` is some pattern to match.\n\nHere's an example URLconf that uses non-named groups::\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^articles/(\\d{4})/$', views.year_archive),\n        (r'^articles/(\\d{4})/(\\d{2})/$', views.month_archive),\n    )\n\nHere's the same URLconf, rewritten to use named groups::\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^articles/(?P<year>\\d{4})/$', views.year_archive),\n        (r'^articles/(?P<year>\\d{4})/(?P<month>\\d{2})/$', views.month_archive),\n    )\n\nThis accomplishes exactly the same thing as the previous example, with one\nsubtle difference: the captured values are passed to view functions as keyword\narguments rather than positional arguments.\n\nFor example, with non-named groups, a request to ``/articles/2006/03/`` would\nresult in a function call equivalent to this::\n\n    month_archive(request, '2006', '03')\n\nWith named groups, though, the same request would result in this function call::\n\n    month_archive(request, year='2006', month='03')\n\nIn practice, using named groups makes your URLconfs slightly more explicit and\nless prone to argument-order bugs -- and you can reorder the arguments in your\nviews' function definitions. Following the preceding example, if we wanted to\nchange the URLs to include the month *before* the year, and we were using\nnon-named groups, we'd have to remember to change the order of arguments in the\n``month_archive`` view. If we were using named groups, changing the order of\nthe captured parameters in the URL would have no effect on the view.\n\nOf course, the benefits of named groups come at the cost of brevity; some\ndevelopers find the named-group syntax ugly and too verbose. Still, another\nadvantage of named groups is readability, especially by those who aren't\nintimately familiar with regular expressions or your particular Django\napplication. It's easier to see what's happening, at a glance, in a\nURLconf that uses named groups.\n\nUnderstanding the Matching/Grouping Algorithm\n---------------------------------------------\n\nA caveat with using named groups in a URLconf is that a single URLconf pattern\ncannot contain both named and non-named groups. If you do this, Django won't\nthrow any errors, but you'll probably find that your URLs aren't matching as\nyou expect. Specifically, here's the algorithm the URLconf parser follows, with\nrespect to named groups vs. non-named groups in a regular expression:\n\n* If there are any named arguments, it will use those, ignoring non-named\n  arguments.\n\n* Otherwise, it will pass all non-named arguments as positional arguments.\n\n* In both cases, it will pass any extra options as keyword arguments. See\n  the next section for more information.\n\nPassing Extra Options to View Functions\n---------------------------------------\n\nSometimes you'll find yourself writing view functions that are quite similar,\nwith only a few small differences. For example, say you have two views whose\ncontents are identical except for the template they use::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^foo/$', views.foo_view),\n        (r'^bar/$', views.bar_view),\n    )\n\n    # views.py\n\n    from django.shortcuts import render\n    from mysite.models import MyModel\n\n    def foo_view(request):\n        m_list = MyModel.objects.filter(is_new=True)\n        return render(request, 'template1.html', {'m_list': m_list})\n\n    def bar_view(request):\n        m_list = MyModel.objects.filter(is_new=True)\n        return render(request, 'template2.html', {'m_list': m_list})\n\nWe're repeating ourselves in this code, and that's inelegant. At first, you\nmay think to remove the redundancy by using the same view for both URLs,\nputting parentheses around the URL to capture it, and checking the URL within\nthe view to determine the template, like so::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^(foo)/$', views.foobar_view),\n        (r'^(bar)/$', views.foobar_view),\n    )\n\n    # views.py\n\n    from django.shortcuts import render\n    from mysite.models import MyModel\n\n    def foobar_view(request, url):\n        m_list = MyModel.objects.filter(is_new=True)\n        if url == 'foo':\n            template_name = 'template1.html'\n        elif url == 'bar':\n            template_name = 'template2.html'\n        return render(request, template_name, {'m_list': m_list})\n\nThe problem with that solution, though, is that it couples your URLs to your\ncode. If you decide to rename ``/foo/`` to ``/fooey/``, you'll have to remember\nto change the view code.\n\nThe elegant solution involves an optional URLconf parameter. Each pattern in a\nURLconf may include a third item: a dictionary of keyword arguments to pass\nto the view function.\n\nWith this in mind, we can rewrite our ongoing example like this::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}),\n        (r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}),\n    )\n\n    # views.py\n\n    from django.shortcuts import render\n    from mysite.models import MyModel\n\n    def foobar_view(request, template_name):\n        m_list = MyModel.objects.filter(is_new=True)\n        return render(request, template_name, {'m_list': m_list})\n\nAs you can see, the URLconf in this example specifies ``template_name`` in the\nURLconf. The view function treats it as just another parameter.\n\nThis extra URLconf options technique is a nice way of sending additional\ninformation to your view functions with minimal fuss. As such, it's used by a\ncouple of Django's bundled applications, most notably its generic views system,\nwhich we cover in Chapter 11.\n\nThe following sections contain a couple of ideas on how you can use the extra\nURLconf options technique in your own projects.\n\nFaking Captured URLconf Values\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSay you have a set of views that match a pattern, along with another URL that\ndoesn't fit the pattern but whose view logic is the same. In this case, you can\n\"fake\" the capturing of URL values by using extra URLconf options to handle\nthat extra URL with the same view.\n\nFor example, you might have an application that displays some data for a\nparticular day, with URLs such as these::\n\n    /mydata/jan/01/\n    /mydata/jan/02/\n    /mydata/jan/03/\n    # ...\n    /mydata/dec/30/\n    /mydata/dec/31/\n\nThis is simple enough to deal with -- you can capture those in a URLconf like\nthis (using named group syntax)::\n\n    urlpatterns = patterns('',\n        (r'^mydata/(?P<month>\\w{3})/(?P<day>\\d\\d)/$', views.my_view),\n    )\n\nAnd the view function signature would look like this::\n\n    def my_view(request, month, day):\n        # ....\n\nThis approach is straightforward -- it's nothing you haven't seen before. The trick comes\nin when you want to add another URL that uses ``my_view`` but whose URL doesn't\ninclude a ``month`` and/or ``day``.\n\nFor example, you might want to add another URL, ``/mydata/birthday/``, which\nwould be equivalent to ``/mydata/jan/06/``. You can take advantage of extra\nURLconf options like so::\n\n    urlpatterns = patterns('',\n        (r'^mydata/birthday/$', views.my_view, {'month': 'jan', 'day': '06'}),\n        (r'^mydata/(?P<month>\\w{3})/(?P<day>\\d\\d)/$', views.my_view),\n    )\n\nThe cool thing here is that you don't have to change your view function at all.\nThe view function only cares that it *gets* ``month`` and ``day`` parameters --\nit doesn't matter whether they come from the URL capturing itself or extra\nparameters.\n\nMaking a View Generic\n~~~~~~~~~~~~~~~~~~~~~\n\nIt's good programming practice to \"factor out\" commonalities in code. For\nexample, with these two Python functions::\n\n    def say_hello(person_name):\n        print 'Hello, %s' % person_name\n\n    def say_goodbye(person_name):\n        print 'Goodbye, %s' % person_name\n\nwe can factor out the greeting to make it a parameter::\n\n    def greet(person_name, greeting):\n        print '%s, %s' % (greeting, person_name)\n\nYou can apply this same philosophy to your Django views by using extra URLconf\nparameters.\n\nWith this in mind, you can start making higher-level abstractions of your\nviews. Instead of thinking to yourself, \"This view displays a list of ``Event``\nobjects,\" and \"That view displays a list of ``BlogEntry`` objects,\" realize\nthey're both specific cases of \"A view that displays a list of objects, where\nthe type of object is variable.\"\n\nTake this code, for example::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^events/$', views.event_list),\n        (r'^blog/entries/$', views.entry_list),\n    )\n\n    # views.py\n\n    from django.shortcuts import render\n    from mysite.models import Event, BlogEntry\n\n    def event_list(request):\n        obj_list = Event.objects.all()\n        return render(request, 'mysite/event_list.html', {'event_list': obj_list})\n\n    def entry_list(request):\n        obj_list = BlogEntry.objects.all()\n        return render(request, 'mysite/blogentry_list.html', {'entry_list': obj_list})\n\nThe two views do essentially the same thing: they display a list of objects. So\nlet's factor out the type of object they're displaying::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n    from mysite import models, views\n\n    urlpatterns = patterns('',\n        (r'^events/$', views.object_list, {'model': models.Event}),\n        (r'^blog/entries/$', views.object_list, {'model': models.BlogEntry}),\n    )\n\n    # views.py\n\n    from django.shortcuts import render\n\n    def object_list(request, model):\n        obj_list = model.objects.all()\n        template_name = 'mysite/%s_list.html' % model.__name__.lower()\n        return render(request, template_name, {'object_list': obj_list})\n\nWith those small changes, we suddenly have a reusable, model-agnostic view!\nFrom now on, anytime we need a view that lists a set of objects, we can simply\nreuse this ``object_list`` view rather than writing view code. Here are a\ncouple of notes about what we did:\n\n* We're passing the model classes directly, as the ``model`` parameter. The\n  dictionary of extra URLconf options can pass any type of Python object --\n  not just strings.\n\n* The ``model.objects.all()`` line is an example of *duck typing*: \"If it\n  walks like a duck and talks like a duck, we can treat it like a duck.\"\n  Note the code doesn't know what type of object ``model`` is; the only\n  requirement is that ``model`` have an ``objects`` attribute, which in\n  turn has an ``all()`` method.\n\n* We're using ``model.__name__.lower()`` in determining the template name.\n  Every Python class has a ``__name__`` attribute that returns the class\n  name. This feature is useful at times like this, when we don't know the\n  type of class until runtime. For example, the ``BlogEntry`` class's\n  ``__name__`` is the string ``'BlogEntry'``.\n\n* In a slight difference between this example and the previous example,\n  we're passing the generic variable name ``object_list`` to the template.\n  We could easily change this variable name to be ``blogentry_list`` or\n  ``event_list``, but we've left that as an exercise for the reader.\n\nBecause database-driven Web sites have several common patterns, Django comes\nwith a set of \"generic views\" that use this exact technique to save you time.\nWe cover Django's built-in generic views in Chapter 11.\n\nGiving a View Configuration Options\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you're distributing a Django application, chances are that your users will\nwant some degree of configuration. In this case, it's a good idea to add hooks\nto your views for any configuration options you think people may want to\nchange. You can use extra URLconf parameters for this purpose.\n\nA common bit of an application to make configurable is the template name::\n\n    def my_view(request, template_name):\n        var = do_something()\n        return render(request, template_name, {'var': var})\n\nUnderstanding Precedence of Captured Values vs. Extra Options\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWhen there's a conflict, extra URLconf parameters get precedence over captured\nparameters. In other words, if your URLconf captures a named-group variable and\nan extra URLconf parameter includes a variable with the same name, the extra\nURLconf parameter value will be used.\n\nFor example, consider this URLconf::\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^mydata/(?P<id>\\d+)/$', views.my_view, {'id': 3}),\n    )\n\nHere, both the regular expression and the extra dictionary include an ``id``.\nThe hard-coded ``id`` gets precedence. That means any request (e.g.,\n``/mydata/2/`` or ``/mydata/432432/``) will be treated as if ``id`` is set\nto ``3``, regardless of the value captured in the URL.\n\nAstute readers will note that in this case, it's a waste of time and typing to\ncapture the ``id`` in the regular expression, because its value will always be\noverridden by the dictionary's value. That's correct; we bring this up only to\nhelp you avoid making the mistake.\n\nUsing Default View Arguments\n----------------------------\n\nAnother convenient trick is to specify default parameters for a view's\narguments. This tells the view which value to use for a parameter by default if\nnone is specified.\n\nAn example::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^blog/$', views.page),\n        (r'^blog/page(?P<num>\\d+)/$', views.page),\n    )\n\n    # views.py\n\n    def page(request, num='1'):\n        # Output the appropriate page of blog entries, according to num.\n        # ...\n\nHere, both URL patterns point to the same view -- ``views.page`` -- but the\nfirst pattern doesn't capture anything from the URL. If the first pattern\nmatches, the ``page()`` function will use its default argument for ``num``,\n``'1'``. If the second pattern matches, ``page()`` will use whatever ``num``\nvalue was captured by the regular expression.\n\n(Note that we've been careful to set the default argument's value to the\n*string* ``'1'``, not the integer ``1``. That's for consistency, because\nany captured value for ``num`` will always be a string.)\n\nIt's common to use this technique in conjunction with configuration options,\nas explained earlier. This example makes a slight improvement to the example in\nthe \"Giving a View Configuration Options\" section by providing a default\nvalue for ``template_name``::\n\n    def my_view(request, template_name='mysite/my_view.html'):\n        var = do_something()\n        return render(request, template_name, {'var': var})\n\n.. SL Again wonder whether default should be unicode?\n\nSpecial-Casing Views\n--------------------\n\nSometimes you'll have a pattern in your URLconf that handles a large set of\nURLs, but you'll need to special-case one of them. In this case, take advantage\nof the linear way a URLconf is processed and put the special case first.\n\nFor example, you can think of the \"add an object\" pages in Django's admin site\nas represented by a URLpattern like this::\n\n    urlpatterns = patterns('',\n        # ...\n        ('^([^/]+)/([^/]+)/add/$', views.add_stage),\n        # ...\n    )\n\nThis matches URLs such as ``/myblog/entries/add/`` and ``/auth/groups/add/``.\nHowever, the \"add\" page for a user object (``/auth/user/add/``) is a special\ncase -- it doesn't display all of the form fields, it displays two password\nfields, and so forth. We *could* solve this problem by special-casing in the\nview, like so::\n\n    def add_stage(request, app_label, model_name):\n        if app_label == 'auth' and model_name == 'user':\n            # do special-case code\n        else:\n            # do normal code\n\n.. SL It's not strictly relevant to the point you're making here, but\n.. SL the view func in the admin is now called 'add_view'\n\nbut that's inelegant for a reason we've touched on multiple times in this\nchapter: it puts URL logic in the view. As a more elegant solution, we can take\nadvantage of the fact that URLconfs are processed in order from top to bottom::\n\n    urlpatterns = patterns('',\n        # ...\n        ('^auth/user/add/$', views.user_add_stage),\n        ('^([^/]+)/([^/]+)/add/$', views.add_stage),\n        # ...\n    )\n\nWith this in place, a request to ``/auth/user/add/`` will be handled by the\n``user_add_stage`` view. Although that URL matches the second pattern, it\nmatches the top one first. (This is short-circuit logic.)\n\nCapturing Text in URLs\n----------------------\n\nEach captured argument is sent to the view as a plain Python Unicode string,\nregardless of what sort of match the regular expression makes. For example, in\nthis URLconf line::\n\n    (r'^articles/(?P<year>\\d{4})/$', views.year_archive),\n\nthe ``year`` argument to ``views.year_archive()`` will be a string, not\nan integer, even though ``\\d{4}`` will only match integer strings.\n\nThis is important to keep in mind when you're writing view code. Many built-in\nPython functions are fussy (and rightfully so) about accepting only objects of\na certain type. A common error is to attempt to create a ``datetime.date``\nobject with string values instead of integer values::\n\n    >>> import datetime\n    >>> datetime.date('1993', '7', '9')\n    Traceback (most recent call last):\n        ...\n    TypeError: an integer is required\n    >>> datetime.date(1993, 7, 9)\n    datetime.date(1993, 7, 9)\n\nTranslated to a URLconf and view, the error looks like this::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        (r'^articles/(\\d{4})/(\\d{2})/(\\d{2})/$', views.day_archive),\n    )\n\n    # views.py\n\n    import datetime\n\n    def day_archive(request, year, month, day):\n        # The following statement raises a TypeError!\n        date = datetime.date(year, month, day)\n\nInstead, ``day_archive()`` can be written correctly like this::\n\n    def day_archive(request, year, month, day):\n        date = datetime.date(int(year), int(month), int(day))\n\nNote that ``int()`` itself raises a ``ValueError`` when you pass it a string\nthat is not composed solely of digits, but we're avoiding that error in this\ncase because the regular expression in our URLconf has ensured that only\nstrings containing digits are passed to the view function.\n\nDetermining What the URLconf Searches Against\n---------------------------------------------\n\nWhen a request comes in, Django tries to match the URLconf patterns against the\nrequested URL, as a Python string. This does not include ``GET`` or ``POST``\nparameters, or the domain name. It also does not include the leading slash,\nbecause every URL has a leading slash.\n\nFor example, in a request to ``http://www.example.com/myapp/``, Django will try\nto match ``myapp/``. In a request to ``http://www.example.com/myapp/?page=3``,\nDjango will try to match ``myapp/``.\n\nThe request method (e.g., ``POST``, ``GET``) is *not* taken into account when\ntraversing the URLconf. In other words, all request methods will be routed to\nthe same function for the same URL. It's the responsibility of a view function\nto perform branching based on request method.\n\nHigher-Level Abstractions of View Functions\n-------------------------------------------\n\nAnd speaking of branching based on request method, let's take a look at how we\nmight build a nice way of doing that. Consider this URLconf/view layout::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        # ...\n        (r'^somepage/$', views.some_page),\n        # ...\n    )\n\n    # views.py\n\n    from django.http import Http404, HttpResponseRedirect\n    from django.shortcuts import render\n\n    def some_page(request):\n        if request.method == 'POST':\n            do_something_for_post()\n            return HttpResponseRedirect('/someurl/')\n        elif request.method == 'GET':\n            do_something_for_get()\n            return render(request, 'page.html')\n        else:\n            raise Http404()\n\nIn this example, the ``some_page()`` view's handling of ``POST`` vs. ``GET``\nrequests is quite different. The only thing they have in common is a shared\nURL: ``/somepage/``. As such, it's kind of inelegant to deal with both ``POST``\nand ``GET`` in the same view function. It would be nice if we could have two\nseparate view functions -- one handling ``GET`` requests and the other handling\n``POST`` -- and ensuring each one was only called when appropriate.\n\nWe can do that by writing a view function that delegates to other views,\neither before or after executing some custom logic. Here's an example of how\nthis technique could help simplify our ``some_page()`` view::\n\n    # views.py\n\n    from django.http import Http404, HttpResponseRedirect\n    from django.shortcuts import render\n\n    def method_splitter(request, GET=None, POST=None):\n        if request.method == 'GET' and GET is not None:\n            return GET(request)\n        elif request.method == 'POST' and POST is not None:\n            return POST(request)\n        raise Http404\n\n    def some_page_get(request):\n        assert request.method == 'GET'\n        do_something_for_get()\n        return render(request, 'page.html')\n\n    def some_page_post(request):\n        assert request.method == 'POST'\n        do_something_for_post()\n        return HttpResponseRedirect('/someurl/')\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n    from mysite import views\n\n    urlpatterns = patterns('',\n        # ...\n        (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}),\n        # ...\n    )\n\nLet's go through what this does:\n\n* We've written a new view, ``method_splitter()``, that delegates to other\n  views based on ``request.method``. It looks for two keyword arguments,\n  ``GET`` and ``POST``, which should be *view functions*. If\n  ``request.method`` is ``'GET'``, then it calls the ``GET`` view. If\n  ``request.method`` is ``'POST'``, then it calls the ``POST`` view. If\n  ``request.method`` is something else (``HEAD``, etc.), or if ``GET`` or\n  ``POST`` were not supplied to the function, then it raises an\n  ``Http404``.\n\n* In the URLconf, we point ``/somepage/`` at ``method_splitter()`` and pass\n  it extra arguments -- the view functions to use for ``GET`` and ``POST``,\n  respectively.\n\n* Finally, we've split the ``some_page()`` view into two view functions --\n  ``some_page_get()`` and ``some_page_post()``. This is much nicer than\n  shoving all of that logic into a single view.\n\n  Note that these view functions technically no longer have to check\n  ``request.method``, because ``method_splitter()`` does that. (By the time\n  ``some_page_post()`` is called, for example, we can be confident\n  ``request.method`` is ``'post'``.) Still, just to be safe, and also to\n  serve as documentation, we stuck in an ``assert`` that makes sure\n  ``request.method`` is what we expect it to be.\n\nNow we have ourselves a nice, generic view function that encapsulates the logic\nof delegating a view by ``request.method``. Nothing about ``method_splitter()``\nis tied to our specific application, of course, so we can reuse it in other\nprojects.\n\nBut, while we're at it, there's one way to improve on ``method_splitter()``.\nAs it's written, it assumes that the ``GET`` and ``POST`` views take no\narguments other than ``request``. What if we wanted to use\n``method_splitter()`` with views that, for example, capture text from URLs,\nor take optional keyword arguments themselves?\n\nTo do that, we can use a nice Python feature: variable arguments with\nasterisks. We'll show the example first, then explain it::\n\n    def method_splitter(request, *args, **kwargs):\n        get_view = kwargs.pop('GET', None)\n        post_view = kwargs.pop('POST', None)\n        if request.method == 'GET' and get_view is not None:\n            return get_view(request, *args, **kwargs)\n        elif request.method == 'POST' and post_view is not None:\n            return post_view(request, *args, **kwargs)\n        raise Http404\n\nHere, we've refactored ``method_splitter()`` to remove the ``GET`` and ``POST``\nkeyword arguments, in favor of ``*args`` and ``**kwargs`` (note the asterisks).\nThis is a Python feature that allows a function to accept a dynamic, arbitrary\nnumber of arguments whose names aren't known until runtime. If you put a single\nasterisk in front of a parameter in a function definition, any *positional*\narguments to that function will be rolled up into a single tuple. If you put\ntwo asterisks in front of a parameter in a function definition, any *keyword*\narguments to that function will be rolled up into a single dictionary.\n\nFor example, with this function::\n\n    def foo(*args, **kwargs):\n        print \"Positional arguments are:\"\n        print args\n        print \"Keyword arguments are:\"\n        print kwargs\n\nHere's how it would work::\n\n    >>> foo(1, 2, 3)\n    Positional arguments are:\n    (1, 2, 3)\n    Keyword arguments are:\n    {}\n    >>> foo(1, 2, name='Adrian', framework='Django')\n    Positional arguments are:\n    (1, 2)\n    Keyword arguments are:\n    {'framework': 'Django', 'name': 'Adrian'}\n\n.. SL Tested ok\n\nBringing this back to ``method_splitter()``, you can see we're using ``*args``\nand ``**kwargs`` to accept *any* arguments to the function and pass them along\nto the appropriate view. But before we do that, we make two calls to\n``kwargs.pop()`` to get the ``GET`` and ``POST`` arguments, if they're\navailable. (We're using ``pop()`` with a default value of ``None`` to avoid\n``KeyError`` if one or the other isn't defined.)\n\nWrapping View Functions\n-----------------------\n\nOur final view trick takes advantage of an advanced Python technique. Say you\nfind yourself repeating a bunch of code throughout various views, as in this\nexample::\n\n    def my_view1(request):\n        if not request.user.is_authenticated():\n            return HttpResponseRedirect('/accounts/login/')\n        # ...\n        return render(request, 'template1.html')\n\n    def my_view2(request):\n        if not request.user.is_authenticated():\n            return HttpResponseRedirect('/accounts/login/')\n        # ...\n        return render(request, 'template2.html')\n\n    def my_view3(request):\n        if not request.user.is_authenticated():\n            return HttpResponseRedirect('/accounts/login/')\n        # ...\n        return render(request, 'template3.html')\n\nHere, each view starts by checking that ``request.user`` is authenticated\n-- that is, the current user has successfully logged into the site -- and\nredirects to ``/accounts/login/`` if not. (Note that we haven't yet covered\n``request.user`` -- Chapter 14 does -- but, as you might imagine,\n``request.user`` represents the current user, either logged-in or anonymous.)\n\nIt would be nice if we could remove that bit of repetitive code from each of\nthese views and just mark them as requiring authentication. We can do that by\nmaking a view wrapper. Take a moment to study this::\n\n    def requires_login(view):\n        def new_view(request, *args, **kwargs):\n            if not request.user.is_authenticated():\n                return HttpResponseRedirect('/accounts/login/')\n            return view(request, *args, **kwargs)\n        return new_view\n\nThis function, ``requires_login``, takes a view function (``view``) and returns\na new view function (``new_view``). The new function, ``new_view`` is defined\n*within* ``requires_login`` and handles the logic of checking\n``request.user.is_authenticated()`` and delegating to the original view\n(``view``).\n\nNow, we can remove the ``if not request.user.is_authenticated()`` checks from\nour views and simply wrap them with ``requires_login`` in our URLconf::\n\n    from django.conf.urls.defaults import *\n    from mysite.views import requires_login, my_view1, my_view2, my_view3\n\n    urlpatterns = patterns('',\n        (r'^view1/$', requires_login(my_view1)),\n        (r'^view2/$', requires_login(my_view2)),\n        (r'^view3/$', requires_login(my_view3)),\n    )\n\nThis has the same effect as before, but with less code redundancy. Now we've\ncreated a nice, generic function -- ``requires_login()`` that we can wrap\naround any view in order to make it require login.\n\nIncluding Other URLconfs\n========================\n\nIf you intend your code to be used on multiple Django-based sites, you should\nconsider arranging your URLconfs in such a way that allows for \"including.\"\n\nAt any point, your URLconf can \"include\" other URLconf modules. This\nessentially \"roots\" a set of URLs below other ones. For example, this\nURLconf includes other URLconfs::\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^weblog/', include('mysite.blog.urls')),\n        (r'^photos/', include('mysite.photos.urls')),\n        (r'^about/$', 'mysite.views.about'),\n    )\n\n(We saw this before in Chapter 6, when we introduced the Django admin site. The\nadmin site has its own URLconf that you merely ``include()`` within yours.)\n\nThere's an important gotcha here: the regular expressions in this example that\npoint to an ``include()`` do *not* have a ``$`` (end-of-string match character)\nbut *do* include a trailing slash. Whenever Django encounters ``include()``, it\nchops off whatever part of the URL matched up to that point and sends the\nremaining string to the included URLconf for further processing.\n\nContinuing this example, here's the URLconf ``mysite.blog.urls``::\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^(\\d\\d\\d\\d)/$', 'mysite.blog.views.year_detail'),\n        (r'^(\\d\\d\\d\\d)/(\\d\\d)/$', 'mysite.blog.views.month_detail'),\n    )\n\nWith these two URLconfs, here's how a few sample requests would be handled:\n\n* ``/weblog/2007/``: In the first URLconf, the pattern ``r'^weblog/'``\n  matches. Because it is an ``include()``, Django strips all the matching\n  text, which is ``'weblog/'`` in this case. The remaining part of the URL\n  is ``2007/``, which matches the first line in the ``mysite.blog.urls``\n  URLconf.\n\n* ``/weblog//2007/`` (with two slashes): In the first URLconf, the pattern\n  ``r'^weblog/'`` matches. Because it is an ``include()``, Django strips\n  all the matching text, which is ``'weblog/'`` in this case. The remaining\n  part of the URL is ``/2007/`` (with a leading slash), which does not\n  match any of the lines in the ``mysite.blog.urls`` URLconf.\n\n* ``/about/``: This matches the view ``mysite.views.about`` in the first\n  URLconf, demonstrating that you can mix ``include()`` patterns with\n  non-``include()`` patterns.\n\nHow Captured Parameters Work with include()\n-------------------------------------------\n\nAn included URLconf receives any captured parameters from parent URLconfs, for\nexample::\n\n    # root urls.py\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^(?P<username>\\w+)/blog/', include('foo.urls.blog')),\n    )\n\n    # foo/urls/blog.py\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^$', 'foo.views.blog_index'),\n        (r'^archive/$', 'foo.views.blog_archive'),\n    )\n\nIn this example, the captured ``username`` variable is passed to the\nincluded URLconf and, hence, to *every* view function within that URLconf.\n\nNote that the captured parameters will *always* be passed to *every* line in\nthe included URLconf, regardless of whether the line's view actually accepts\nthose parameters as valid. For this reason, this technique is useful only if\nyou're certain that every view in the included URLconf accepts the\nparameters you're passing.\n\nHow Extra URLconf Options Work with include()\n---------------------------------------------\n\nSimilarly, you can pass extra URLconf options to ``include()``, just as you can\npass extra URLconf options to a normal view -- as a dictionary. When you do\nthis, *each* line in the included URLconf will be passed the extra options.\n\nFor example, the following two URLconf sets are functionally identical.\n\nSet one::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^blog/', include('inner'), {'blogid': 3}),\n    )\n\n    # inner.py\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^archive/$', 'mysite.views.archive'),\n        (r'^about/$', 'mysite.views.about'),\n        (r'^rss/$', 'mysite.views.rss'),\n    )\n\nSet two::\n\n    # urls.py\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^blog/', include('inner')),\n    )\n\n    # inner.py\n\n    from django.conf.urls.defaults import *\n\n    urlpatterns = patterns('',\n        (r'^archive/$', 'mysite.views.archive', {'blogid': 3}),\n        (r'^about/$', 'mysite.views.about', {'blogid': 3}),\n        (r'^rss/$', 'mysite.views.rss', {'blogid': 3}),\n    )\n\nAs is the case with captured parameters (explained in the previous section),\nextra options will *always* be passed to *every* line in the included\nURLconf, regardless of whether the line's view actually accepts those options\nas valid. For this reason, this technique is useful only if you're certain that\nevery view in the included URLconf accepts the extra options you're passing.\n\nWhat's Next?\n============\n\nThis chapter has provided many advanced tips and tricks for views and URLconfs.\nNext, in `Chapter 9`_, we'll give this advanced treatment to Django's template\nsystem.\n\n.. _Chapter 9: ../chapter09/\n"
  },
  {
    "path": "Python/DjangoBook/chapter09.rst",
    "content": "=============================\nChapter 9: Advanced Templates\n=============================\n\nAlthough most of your interactions with Django's template language will be in\nthe role of template author, you may want to customize and extend the template\nengine -- either to make it do something it doesn't already do, or to make your\njob easier in some other way.\n\nThis chapter delves deep into the guts of Django's template system. It covers\nwhat you need to know if you plan to extend the system or if you're just\ncurious about how it works. It also covers the auto-escaping feature, a\nsecurity measure you'll no doubt notice over time as you continue to use\nDjango.\n\nIf you're looking to use the Django template system as part of another\napplication (i.e., without the rest of the framework), make sure to read the\n\"Configuring the Template System in Standalone Mode\" section later in the\nchapter.\n\nTemplate Language Review\n========================\n\nFirst, let's quickly review a number of terms introduced in Chapter 4:\n\n* A *template* is a text document, or a normal Python string, that is\n  marked up using the Django template language. A template can contain\n  template tags and variables.\n\n* A *template tag* is a symbol within a template that does something. This\n  definition is deliberately vague. For example, a template tag can produce\n  content, serve as a control structure (an ``if`` statement or ``for``\n  loop), grab content from a database, or enable access to other template\n  tags.\n\n  Template tags are surrounded by ``{%`` and ``%}``::\n\n      {% if is_logged_in %}\n          Thanks for logging in!\n      {% else %}\n          Please log in.\n      {% endif %}\n\n* A *variable* is a symbol within a template that outputs a value.\n\n  Variable tags are surrounded by ``{{`` and ``}}``::\n\n      My first name is {{ first_name }}. My last name is {{ last_name }}.\n\n* A *context* is a name -> value mapping (similar to a Python\n  dictionary) that is passed to a template.\n\n* A template *renders* a context by replacing the variable \"holes\" with\n  values from the context and executing all template tags.\n\nFor more details about the basics of these terms, refer back to Chapter 4.\n\nThe rest of this chapter discusses ways of extending the template engine. First,\nthough, let's take a quick look at a few internals left out of Chapter 4 for\nsimplicity.\n\nRequestContext and Context Processors\n=====================================\n\nWhen rendering a template, you need a context. This can be an instance of\n``django.template.Context``, but Django also comes with a subclass,\n``django.template.RequestContext``, that acts slightly differently.\n``RequestContext`` adds a bunch of variables to your template context by\ndefault -- things like the ``HttpRequest`` object or information about the\ncurrently logged-in user. The ``render()`` shortcut creates a ``RequestContext`` \nunless it is passed a different context instance explicitly.\n\n\nUse ``RequestContext`` when you don't want to have to specify the same set of\nvariables in a series of templates. For example, consider these two views::\n\n    from django.template import loader, Context\n\n    def view_1(request):\n        # ...\n        t = loader.get_template('template1.html')\n        c = Context({\n            'app': 'My app',\n            'user': request.user,\n            'ip_address': request.META['REMOTE_ADDR'],\n            'message': 'I am view 1.'\n        })\n        return t.render(c)\n\n    def view_2(request):\n        # ...\n        t = loader.get_template('template2.html')\n        c = Context({\n            'app': 'My app',\n            'user': request.user,\n            'ip_address': request.META['REMOTE_ADDR'],\n            'message': 'I am the second view.'\n        })\n        return t.render(c)\n\n(Note that we're deliberately *not* using the ``render()`` shortcut\nin these examples -- we're manually loading the templates, constructing the\ncontext objects and rendering the templates. We're \"spelling out\" all of the\nsteps for the purpose of clarity.)\n\nEach view passes the same three variables -- ``app``, ``user`` and\n``ip_address`` -- to its template. Wouldn't it be nice if we could remove that\nredundancy?\n\n``RequestContext`` and **context processors** were created to solve this\nproblem. Context processors let you specify a number of variables that get set\nin each context automatically -- without you having to specify the variables in\neach ``render()`` call. The catch is that you have to use\n``RequestContext`` instead of ``Context`` when you render a template.\n\nThe most low-level way of using context processors is to create some processors\nand pass them to ``RequestContext``. Here's how the above example could be\nwritten with context processors::\n\n    from django.template import loader, RequestContext\n\n    def custom_proc(request):\n        \"A context processor that provides 'app', 'user' and 'ip_address'.\"\n        return {\n            'app': 'My app',\n            'user': request.user,\n            'ip_address': request.META['REMOTE_ADDR']\n        }\n\n    def view_1(request):\n        # ...\n        t = loader.get_template('template1.html')\n        c = RequestContext(request, {'message': 'I am view 1.'},\n                processors=[custom_proc])\n        return t.render(c)\n\n    def view_2(request):\n        # ...\n        t = loader.get_template('template2.html')\n        c = RequestContext(request, {'message': 'I am the second view.'},\n                processors=[custom_proc])\n        return t.render(c)\n\nLet's step through this code:\n\n* First, we define a function ``custom_proc``. This is a context processor\n  -- it takes an ``HttpRequest`` object and returns a dictionary of\n  variables to use in the template context. That's all it does.\n\n* We've changed the two view functions to use ``RequestContext`` instead\n  of ``Context``. There are two differences in how the context is\n  constructed. One, ``RequestContext`` requires the first argument to be an\n  ``HttpRequest`` object -- the one that was passed into the view function\n  in the first place (``request``). Two, ``RequestContext`` takes an\n  optional ``processors`` argument, which is a list or tuple of context\n  processor functions to use. Here, we pass in ``custom_proc``, the custom\n  processor we defined above.\n\n* Each view no longer has to include ``app``, ``user`` or ``ip_address`` in\n  its context construction, because those are provided by ``custom_proc``.\n\n* Each view *still* has the flexibility to introduce any custom template\n  variables it might need. In this example, the ``message`` template\n  variable is set differently in each view.\n\nIn Chapter 4, we introduced the ``render()`` shortcut, which saves\nyou from having to call ``loader.get_template()``, then create a ``Context``,\nthen call the ``render()`` method on the template. In order to demonstrate the\nlower-level workings of context processors, the above examples didn't use\n``render()``, . But it's possible -- and preferable -- to use\ncontext processors with ``render()``. Do this with the\n``context_instance`` argument, like so::\n\n    from django.shortcuts import render\n    from django.template import RequestContext\n\n    def custom_proc(request):\n        \"A context processor that provides 'app', 'user' and 'ip_address'.\"\n        return {\n            'app': 'My app',\n            'user': request.user,\n            'ip_address': request.META['REMOTE_ADDR']\n        }\n\n    def view_1(request):\n        # ...\n        return render(request, 'template1.html',\n            {'message': 'I am view 1.'},\n            context_instance=RequestContext(request, processors=[custom_proc]))\n\n    def view_2(request):\n        # ...\n        return render(request, 'template2.html',\n            {'message': 'I am the second view.'},\n            context_instance=RequestContext(request, processors=[custom_proc]))\n\nHere, we've trimmed down each view's template rendering code to a single\n(wrapped) line.\n\nThis is an improvement, but, evaluating the conciseness of this code, we have\nto admit we're now almost overdosing on the *other* end of the spectrum. We've\nremoved redundancy in data (our template variables) at the cost of adding\nredundancy in code (in the ``processors`` call). Using context processors\ndoesn't save you much typing if you have to type ``processors`` all the time.\n\nFor that reason, Django provides support for *global* context processors. The\n``TEMPLATE_CONTEXT_PROCESSORS`` setting (in your ``settings.py``) designates\nwhich context processors should *always* be applied to ``RequestContext``. This\nremoves the need to specify ``processors`` each time you use\n``RequestContext``.\n\nBy default, ``TEMPLATE_CONTEXT_PROCESSORS`` is set to the following::\n\n    TEMPLATE_CONTEXT_PROCESSORS = (\n        'django.core.context_processors.auth',\n        'django.core.context_processors.debug',\n        'django.core.context_processors.i18n',\n        'django.core.context_processors.media',\n    )\n\nThis setting is a tuple of callables that use the same interface as our\n``custom_proc`` function above -- functions that take a request object as their\nargument and return a dictionary of items to be merged into the context. Note\nthat the values in ``TEMPLATE_CONTEXT_PROCESSORS`` are specified as *strings*,\nwhich means the processors are required to be somewhere on your Python path\n(so you can refer to them from the setting).\n\nEach processor is applied in order. That is, if one processor adds a variable\nto the context and a second processor adds a variable with the same name, the\nsecond will override the first.\n\nDjango provides a number of simple context processors, including the ones that\nare enabled by default:\n\ndjango.core.context_processors.auth\n-----------------------------------\n\nIf ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every\n``RequestContext`` will contain these variables:\n\n* ``user``: A ``django.contrib.auth.models.User`` instance representing the\n  current logged-in user (or an ``AnonymousUser`` instance, if the client\n  isn't logged in).\n\n* ``messages``: A list of messages (as strings) for the current logged-in\n  user. Behind the scenes, this variable calls\n  ``request.user.get_and_delete_messages()`` for every request. That method\n  collects the user's messages and deletes them from the database.\n\n* ``perms``: An instance of ``django.core.context_processors.PermWrapper``,\n  which represents the permissions the current logged-in user has.\n\nSee Chapter 14 for more information on users, permissions, and messages.\n\ndjango.core.context_processors.debug\n------------------------------------\n\nThis processor pushes debugging information down to the template layer. If\n``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every\n``RequestContext`` will contain these variables:\n\n* ``debug``: The value of your ``DEBUG`` setting (either ``True`` or\n  ``False``). You can use this variable in templates to test whether you're\n  in debug mode.\n\n* ``sql_queries``: A list of ``{'sql': ..., 'time': ...}`` dictionaries\n  representing every SQL query that has happened so far during the request\n  and how long it took. The list is in the order in which the queries were\n  issued.\n\nBecause debugging information is sensitive, this context processor will only\nadd variables to the context if both of the following conditions are true:\n\n* The ``DEBUG`` setting is ``True``.\n\n* The request came from an IP address in the ``INTERNAL_IPS`` setting.\n\nAstute readers will notice that the ``debug`` template variable will never have\nthe value ``False`` because, if ``DEBUG`` is ``False``, then the ``debug``\ntemplate variable won't be populated in the first place.\n\ndjango.core.context_processors.i18n\n-----------------------------------\n\nIf this processor is enabled, every ``RequestContext`` will contain these\nvariables:\n\n* ``LANGUAGES``: The value of the ``LANGUAGES`` setting.\n\n* ``LANGUAGE_CODE``: ``request.LANGUAGE_CODE`` if it exists; otherwise, the\n  value of the ``LANGUAGE_CODE`` setting.\n\nAppendix D provides more information about these two settings.\n\ndjango.core.context_processors.request\n--------------------------------------\n\nIf this processor is enabled, every ``RequestContext`` will contain a variable\n``request``, which is the current ``HttpRequest`` object. Note that this\nprocessor is not enabled by default; you have to activate it.\n\nYou might want to use this if you find your templates needing to access\nattributes of the current ``HttpRequest`` such as the IP address::\n\n    {{ request.REMOTE_ADDR }}\n\nGuidelines for Writing Your Own Context Processors\n--------------------------------------------------\n\nHere are a few tips for rolling your own:\n\n* Make each context processor responsible for the smallest subset of\n  functionality possible. It's easy to use multiple processors, so you\n  might as well split functionality into logical pieces for future reuse.\n\n* Keep in mind that any context processor in ``TEMPLATE_CONTEXT_PROCESSORS``\n  will be available in *every* template powered by that settings file, so\n  try to pick variable names that are unlikely to conflict with variable\n  names your templates might be using independently. As variable names are\n  case-sensitive, it's not a bad idea to use all caps for variables that a\n  processor provides.\n\n* It doesn't matter where on the filesystem they live, as long as they're\n  on your Python path so you can point to them from the\n  ``TEMPLATE_CONTEXT_PROCESSORS`` setting. With that said, the convention\n  is to save them in a file called ``context_processors.py`` within your\n  app or project.\n\nAutomatic HTML Escaping\n=======================\n\nWhen generating HTML from templates, there's always a risk that a variable will\ninclude characters that affect the resulting HTML. For example, consider this\ntemplate fragment::\n\n    Hello, {{ name }}.\n\nAt first, this seems like a harmless way to display a user's name, but consider\nwhat would happen if the user entered his name as this::\n\n    <script>alert('hello')</script>\n\nWith this name value, the template would be rendered as::\n\n    Hello, <script>alert('hello')</script>\n\n...which means the browser would pop-up a JavaScript alert box!\n\nSimilarly, what if the name contained a ``'<'`` symbol, like this?\n\n::\n\n    <b>username\n\nThat would result in a rendered template like this::\n\n    Hello, <b>username\n\n...which, in turn, would result in the remainder of the Web page being bolded!\n\nClearly, user-submitted data shouldn't be trusted blindly and inserted directly\ninto your Web pages, because a malicious user could use this kind of hole to\ndo potentially bad things. This type of security exploit is called a\nCross Site Scripting (XSS) attack. (For more on security, see Chapter 20.)\n\nTo avoid this problem, you have two options:\n\n* One, you can make sure to run each untrusted variable through the\n  ``escape`` filter, which converts potentially harmful HTML characters to\n  unharmful ones. This was the default solution in Django for its first few\n  years, but the problem is that it puts the onus on *you*, the developer /\n  template author, to ensure you're escaping everything. It's easy to forget\n  to escape data.\n\n* Two, you can take advantage of Django's automatic HTML escaping. The\n  remainder of this section describes how auto-escaping works.\n\nBy default in Django, every template automatically escapes the output\nof every variable tag. Specifically, these five characters are\nescaped:\n\n* ``<`` is converted to ``&lt;``\n* ``>`` is converted to ``&gt;``\n* ``'`` (single quote) is converted to ``&#39;``\n* ``\"`` (double quote) is converted to ``&quot;``\n* ``&`` is converted to ``&amp;``\n\nAgain, we stress that this behavior is on by default. If you're using Django's\ntemplate system, you're protected.\n\nHow to Turn it Off\n------------------\n\nIf you don't want data to be auto-escaped, on a per-site, per-template level or\nper-variable level, you can turn it off in several ways.\n\nWhy would you want to turn it off? Because sometimes, template variables\ncontain data that you *intend* to be rendered as raw HTML, in which case you\ndon't want their contents to be escaped. For example, you might store a blob of\ntrusted HTML in your database and want to embed that directly into your\ntemplate. Or, you might be using Django's template system to produce text that\nis *not* HTML -- like an e-mail message, for instance.\n\nFor Individual Variables\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo disable auto-escaping for an individual variable, use the ``safe`` filter::\n\n    This will be escaped: {{ data }}\n    This will not be escaped: {{ data|safe }}\n\nThink of *safe* as shorthand for *safe from further escaping* or *can be\nsafely interpreted as HTML*. In this example, if ``data`` contains ``'<b>'``,\nthe output will be::\n\n    This will be escaped: &lt;b&gt;\n    This will not be escaped: <b>\n\nFor Template Blocks\n~~~~~~~~~~~~~~~~~~~\n\nTo control auto-escaping for a template, wrap the template (or just a\nparticular section of the template) in the ``autoescape`` tag, like so::\n\n    {% autoescape off %}\n        Hello {{ name }}\n    {% endautoescape %}\n\nThe ``autoescape`` tag takes either ``on`` or ``off`` as its argument. At\ntimes, you might want to force auto-escaping when it would otherwise be\ndisabled. Here is an example template::\n\n    Auto-escaping is on by default. Hello {{ name }}\n\n    {% autoescape off %}\n        This will not be auto-escaped: {{ data }}.\n\n        Nor this: {{ other_data }}\n        {% autoescape on %}\n            Auto-escaping applies again: {{ name }}\n        {% endautoescape %}\n    {% endautoescape %}\n\nThe auto-escaping tag passes its effect on to templates that extend the\ncurrent one as well as templates included via the ``include`` tag, just like\nall block tags. For example::\n\n    # base.html\n\n    {% autoescape off %}\n    <h1>{% block title %}{% endblock %}</h1>\n    {% block content %}\n    {% endblock %}\n    {% endautoescape %}\n\n    # child.html\n\n    {% extends \"base.html\" %}\n    {% block title %}This & that{% endblock %}\n    {% block content %}{{ greeting }}{% endblock %}\n\nBecause auto-escaping is turned off in the base template, it will also be\nturned off in the child template, resulting in the following rendered\nHTML when the ``greeting`` variable contains the string ``<b>Hello!</b>``::\n\n    <h1>This & that</h1>\n    <b>Hello!</b>\n\nNotes\n-----\n\nGenerally, template authors don't need to worry about auto-escaping very much.\nDevelopers on the Python side (people writing views and custom filters) need to\nthink about the cases in which data shouldn't be escaped, and mark data\nappropriately, so things work in the template.\n\nIf you're creating a template that might be used in situations where you're\nnot sure whether auto-escaping is enabled, then add an ``escape`` filter to any\nvariable that needs escaping. When auto-escaping is on, there's no danger of\nthe ``escape`` filter *double-escaping* data -- the ``escape`` filter does not\naffect auto-escaped variables.\n\nAutomatic Escaping of String Literals in Filter Arguments\n---------------------------------------------------------\n\nAs we mentioned earlier, filter arguments can be strings::\n\n    {{ data|default:\"This is a string literal.\" }}\n\nAll string literals are inserted *without* any automatic escaping into the\ntemplate -- they act as if they were all passed through the ``safe`` filter.\nThe reasoning behind this is that the template author is in control of what\ngoes into the string literal, so they can make sure the text is correctly\nescaped when the template is written.\n\nThis means you would write ::\n\n    {{ data|default:\"3 &lt; 2\" }}\n\n...rather than ::\n\n    {{ data|default:\"3 < 2\" }}  <-- Bad! Don't do this.\n\nThis doesn't affect what happens to data coming from the variable itself.\nThe variable's contents are still automatically escaped, if necessary, because\nthey're beyond the control of the template author.\n\nInside Template Loading\n=======================\n\nGenerally, you'll store templates in files on your filesystem, but you can use\ncustom *template loaders* to load templates from other sources.\n\nDjango has two ways to load templates:\n\n* ``django.template.loader.get_template(template_name)``: ``get_template``\n  returns the compiled template (a ``Template`` object) for the template\n  with the given name. If the template doesn't exist, a\n  ``TemplateDoesNotExist`` exception will be raised.\n\n* ``django.template.loader.select_template(template_name_list)``:\n  ``select_template`` is just like ``get_template``, except it takes a list\n  of template names. Of the list, it returns the first template that exists.\n  If none of the templates exist, a ``TemplateDoesNotExist`` exception will\n  be raised.\n\nAs covered in Chapter 4, each of these functions by default uses your\n``TEMPLATE_DIRS`` setting to load templates. Internally, however, these\nfunctions actually delegate to a template loader for the heavy lifting.\n\nSome of loaders are disabled by default, but you can activate them by editing\nthe ``TEMPLATE_LOADERS`` setting. ``TEMPLATE_LOADERS`` should be a tuple of\nstrings, where each string represents a template loader. These template loaders\nship with Django:\n\n* ``django.template.loaders.filesystem.load_template_source``: This loader\n  loads templates from the filesystem, according to ``TEMPLATE_DIRS``. It is\n  enabled by default.\n\n* ``django.template.loaders.app_directories.load_template_source``: This\n  loader loads templates from Django applications on the filesystem. For\n  each application in ``INSTALLED_APPS``, the loader looks for a\n  ``templates`` subdirectory. If the directory exists, Django looks for\n  templates there.\n\n  This means you can store templates with your individual applications,\n  making it easy to distribute Django applications with default templates.\n  For example, if ``INSTALLED_APPS`` contains ``('myproject.polls',\n  'myproject.music')``, then ``get_template('foo.html')`` will look for\n  templates in this order:\n\n  * ``/path/to/myproject/polls/templates/foo.html``\n  * ``/path/to/myproject/music/templates/foo.html``\n\n  Note that the loader performs an optimization when it is first imported:\n  it caches a list of which ``INSTALLED_APPS`` packages have a ``templates``\n  subdirectory.\n\n  This loader is enabled by default.\n\n* ``django.template.loaders.eggs.load_template_source``: This loader is just\n  like ``app_directories``, except it loads templates from Python eggs\n  rather than from the filesystem. This loader is disabled by default;\n  you'll need to enable it if you're using eggs to distribute your\n  application. (Python eggs are a way of compressing Python code into a\n  single file.)\n\nDjango uses the template loaders in order according to the ``TEMPLATE_LOADERS``\nsetting. It uses each loader until a loader finds a match.\n\nExtending the Template System\n=============================\n\nNow that you understand a bit more about the internals of the template system,\nlet's look at how to extend the system with custom code.\n\nMost template customization comes in the form of custom template tags and/or\nfilters. Although the Django template language comes with many built-in tags and\nfilters, you'll probably assemble your own libraries of tags and filters that\nfit your own needs. Fortunately, it's quite easy to define your own\nfunctionality.\n\nCreating a Template Library\n---------------------------\n\nWhether you're writing custom tags or filters, the first thing to do is to\ncreate a **template library** -- a small bit of infrastructure Django can hook\ninto.\n\nCreating a template library is a two-step process:\n\n* First, decide which Django application should house the template library.\n  If you've created an app via ``manage.py startapp``, you can put it in\n  there, or you can create another app solely for the template library.\n  We'd recommend the latter, because your filters might be useful to you\n  in future projects.\n\n  Whichever route you take, make sure to add the app to your\n  ``INSTALLED_APPS`` setting. We'll explain this shortly.\n\n* Second, create a ``templatetags`` directory in the appropriate Django\n  application's package. It should be on the same level as ``models.py``,\n  ``views.py``, and so forth. For example::\n\n      books/\n          __init__.py\n          models.py\n          templatetags/\n          views.py\n\n  Create two empty files in the ``templatetags`` directory: an ``__init__.py``\n  file (to indicate to Python that this is a package containing Python code)\n  and a file that will contain your custom tag/filter definitions. The name\n  of the latter file is what you'll use to load the tags later. For example,\n  if your custom tags/filters are in a file called ``poll_extras.py``, you'd\n  write the following in a template::\n\n      {% load poll_extras %}\n\n  The ``{% load %}`` tag looks at your ``INSTALLED_APPS`` setting and only\n  allows the loading of template libraries within installed Django\n  applications. This is a security feature; it allows you to host Python\n  code for many template libraries on a single computer without enabling\n  access to all of them for every Django installation.\n\nIf you write a template library that isn't tied to any particular models/views,\nit's valid and quite normal to have a Django application package that contains\nonly a ``templatetags`` package. There's no limit on how many modules you put in\nthe ``templatetags`` package. Just keep in mind that a ``{% load %}`` statement\nwill load tags/filters for the given Python module name, not the name of the\napplication.\n\nOnce you've created that Python module, you'll just have to write a bit of\nPython code, depending on whether you're writing filters or tags.\n\nTo be a valid tag library, the module must contain a module-level variable named\n``register`` that is an instance of ``template.Library``. This is the data\nstructure in which all the tags and filters are registered. So, near the top of\nyour module, insert the following::\n\n    from django import template\n\n    register = template.Library()\n\n.. note::\n\n    For a fine selection of examples, read the source code for Django's default\n    filters and tags. They're in ``django/template/defaultfilters.py`` and\n    ``django/template/defaulttags.py``, respectively. Some applications in\n    ``django.contrib`` also contain template libraries.\n\nOnce you've created this ``register`` variable, you'll use it to create template\nfilters and tags.\n\nWriting Custom Template Filters\n-------------------------------\n\nCustom filters are just Python functions that take one or two arguments:\n\n* The value of the variable (input)\n\n* The value of the argument, which can have a default value or be left out\n  altogether\n\nFor example, in the filter ``{{ var|foo:\"bar\" }}``, the filter ``foo`` would be\npassed the contents of the variable ``var`` and the argument ``\"bar\"``.\n\nFilter functions should always return something. They shouldn't raise\nexceptions, and they should fail silently. If there's an error, they should\nreturn either the original input or an empty string, whichever makes more sense.\n\nHere's an example filter definition::\n\n    def cut(value, arg):\n        \"Removes all values of arg from the given string\"\n        return value.replace(arg, '')\n\nAnd here's an example of how that filter would be used to cut spaces from a\nvariable's value::\n\n    {{ somevariable|cut:\" \" }}\n\nMost filters don't take arguments. In this case, just leave the argument out\nof your function::\n\n    def lower(value): # Only one argument.\n        \"Converts a string into all lowercase\"\n        return value.lower()\n\nWhen you've written your filter definition, you need to register it with your\n``Library`` instance, to make it available to Django's template language::\n\n    register.filter('cut', cut)\n    register.filter('lower', lower)\n\n.. SL Tested ok\n\nThe ``Library.filter()`` method takes two arguments:\n\n* The name of the filter (a string)\n* The filter function itself\n\nIf you're using Python 2.4 or above, you can use ``register.filter()`` as a\ndecorator instead::\n\n    @register.filter(name='cut')\n    def cut(value, arg):\n        return value.replace(arg, '')\n\n    @register.filter\n    def lower(value):\n        return value.lower()\n\n.. SL Tested ok\n\nIf you leave off the ``name`` argument, as in the second example, Django\nwill use the function's name as the filter name.\n\nHere, then, is a complete template library example, supplying the ``cut`` filter::\n\n    from django import template\n\n    register = template.Library()\n\n    @register.filter(name='cut')\n    def cut(value, arg):\n        return value.replace(arg, '')\n\n.. SL Tested ok\n\nWriting Custom Template Tags\n----------------------------\n\nTags are more complex than filters, because tags can do nearly anything.\n\nChapter 4 describes how the template system works in a two-step process:\ncompiling and rendering. To define a custom template tag, you need to tell\nDjango how to manage *both* of these steps when it gets to your tag.\n\nWhen Django compiles a template, it splits the raw template text into\n*nodes*. Each node is an instance of ``django.template.Node`` and has\na ``render()`` method. Thus, a compiled template is simply a list of ``Node``\nobjects. For example, consider this template::\n\n    Hello, {{ person.name }}.\n\n    {% ifequal name.birthday today %}\n        Happy birthday!\n    {% else %}\n        Be sure to come back on your birthday\n        for a splendid surprise message.\n    {% endifequal %}\n\nIn compiled template form, this template is represented as this list of\nnodes:\n\n* Text node: ``\"Hello, \"``\n* Variable node: ``person.name``\n* Text node: ``\".\\n\\n\"``\n* IfEqual node: ``name.birthday`` and ``today``\n\nWhen you call ``render()`` on a compiled template, the template calls\n``render()`` on each ``Node`` in its node list, with the given context. The\nresults are all concatenated together to form the output of the template. Thus,\nto define a custom template tag, you specify how the raw template tag is\nconverted into a ``Node`` (the compilation function) and what the node's\n``render()`` method does.\n\nIn the sections that follow, we cover all the steps in writing a custom tag.\n\nWriting the Compilation Function\n--------------------------------\n\nFor each template tag the parser encounters, it calls a Python function with\nthe tag contents and the parser object itself. This function is responsible for\nreturning a ``Node`` instance based on the contents of the tag.\n\nFor example, let's write a template tag, ``{% current_time %}``, that displays\nthe current date/time, formatted according to a parameter given in the tag, in\n``strftime`` syntax (see ``http://www.djangoproject.com/r/python/strftime/``).\nIt's a good idea to decide the tag syntax before anything else. In our case,\nlet's say the tag should be used like this::\n\n    <p>The time is {% current_time \"%Y-%m-%d %I:%M %p\" %}.</p>\n\n.. note::\n\n    Yes, this template tag is redundant--Django's default ``{% now %}`` tag does\n    the same task with simpler syntax. This template tag is presented here just\n    for example purposes.\n\nThe parser for this function should grab the parameter and create a ``Node``\nobject::\n\n    from django import template\n\n    register = template.Library()\n\n    def do_current_time(parser, token):\n        try:\n            # split_contents() knows not to split quoted strings.\n            tag_name, format_string = token.split_contents()\n        except ValueError:\n            msg = '%r tag requires a single argument' % token.split_contents()[0]\n            raise template.TemplateSyntaxError(msg)\n        return CurrentTimeNode(format_string[1:-1])\n\nThere's a lot going here:\n\n* Each template tag compilation function takes two arguments, ``parser``\n  and ``token``. ``parser`` is the template parser object. We don't use it\n  in this example. ``token`` is the token currently being parsed by the\n  parser.\n\n* ``token.contents`` is a string of the raw contents of the tag. In our\n  example, it's ``'current_time \"%Y-%m-%d %I:%M %p\"'``.\n\n* The ``token.split_contents()`` method separates the arguments on spaces\n  while keeping quoted strings together. Avoid using\n  ``token.contents.split()`` (which just uses Python's standard\n  string-splitting semantics). It's not as robust, as it naively splits on\n  *all* spaces, including those within quoted strings.\n\n* This function is responsible for raising\n  ``django.template.TemplateSyntaxError``, with helpful messages, for any\n  syntax error.\n\n* Don't hard-code the tag's name in your error messages, because that\n  couples the tag's name to your function. ``token.split_contents()[0]``\n  will *always* be the name of your tag -- even when the tag has no\n  arguments.\n\n* The function returns a ``CurrentTimeNode`` (which we'll create shortly)\n  containing everything the node needs to know about this tag. In this\n  case, it just passes the argument ``\"%Y-%m-%d %I:%M %p\"``. The\n  leading and trailing quotes from the template tag are removed with\n  ``format_string[1:-1]``.\n\n* Template tag compilation functions *must* return a ``Node`` subclass;\n  any other return value is an error.\n\nWriting the Template Node\n-------------------------\n\nThe second step in writing custom tags is to define a ``Node`` subclass that\nhas a ``render()`` method. Continuing the preceding example, we need to define\n``CurrentTimeNode``::\n\n    import datetime\n\n    class CurrentTimeNode(template.Node):\n        def __init__(self, format_string):\n            self.format_string = str(format_string)\n\n        def render(self, context):\n            now = datetime.datetime.now()\n            return now.strftime(self.format_string)\n\nThese two functions (``__init__()`` and ``render()``) map directly to the two\nsteps in template processing (compilation and rendering). Thus, the\ninitialization function only needs to store the format string for later use,\nand the ``render()`` function does the real work.\n\nLike template filters, these rendering functions should fail silently instead\nof raising errors. The only time that template tags are allowed to raise\nerrors is at compilation time.\n\nRegistering the Tag\n-------------------\n\nFinally, you need to register the tag with your module's ``Library`` instance.\nRegistering custom tags is very similar to registering custom filters (as\nexplained above). Just instantiate a ``template.Library`` instance and call\nits ``tag()`` method. For example::\n\n    register.tag('current_time', do_current_time)\n\nThe ``tag()`` method takes two arguments:\n\n* The name of the template tag (string).\n* The compilation function.\n\nAs with filter registration, it is also possible to use ``register.tag`` as a\ndecorator in Python 2.4 and above::\n\n    @register.tag(name=\"current_time\")\n    def do_current_time(parser, token):\n        # ...\n\n    @register.tag\n    def shout(parser, token):\n        # ...\n\nIf you leave off the ``name`` argument, as in the second example, Django\nwill use the function's name as the tag name.\n\nSetting a Variable in the Context\n---------------------------------\n\nThe previous section's example simply returned a value. Often it's useful to set\ntemplate variables instead of returning values. That way, template authors can\njust use the variables that your template tags set.\n\nTo set a variable in the context, use dictionary assignment on the context\nobject in the ``render()`` method. Here's an updated version of\n``CurrentTimeNode`` that sets a template variable, ``current_time``, instead of\nreturning it::\n\n    class CurrentTimeNode2(template.Node):\n        def __init__(self, format_string):\n            self.format_string = str(format_string)\n\n        def render(self, context):\n            now = datetime.datetime.now()\n            context['current_time'] = now.strftime(self.format_string)\n            return ''\n\n(We'll leave the creation of a ``do_current_time2`` function, plus the\nregistration of that function to a ``current_time2`` template tag, as exercises\nfor the reader.)\n\nNote that ``render()`` returns an empty string. ``render()`` should always\nreturn a string, so if all the template tag does is set a variable,\n``render()`` should return an empty string.\n\nHere's how you'd use this new version of the tag::\n\n    {% current_time2 \"%Y-%M-%d %I:%M %p\" %}\n    <p>The time is {{ current_time }}.</p>\n\nBut there's a problem with ``CurrentTimeNode2``: the variable name\n``current_time`` is hard-coded. This means you'll need to make sure your\ntemplate doesn't use ``{{ current_time }}`` anywhere else, because\n``{% current_time2 %}`` will blindly overwrite that variable's value.\n\nA cleaner solution is to make the template tag specify the name of the variable\nto be set, like so::\n\n    {% get_current_time \"%Y-%M-%d %I:%M %p\" as my_current_time %}\n    <p>The current time is {{ my_current_time }}.</p>\n\nTo do so, you'll need to refactor both the compilation function and the\n``Node`` class, as follows::\n\n    import re\n\n    class CurrentTimeNode3(template.Node):\n        def __init__(self, format_string, var_name):\n            self.format_string = str(format_string)\n            self.var_name = var_name\n\n        def render(self, context):\n            now = datetime.datetime.now()\n            context[self.var_name] = now.strftime(self.format_string)\n            return ''\n\n    def do_current_time(parser, token):\n        # This version uses a regular expression to parse tag contents.\n        try:\n            # Splitting by None == splitting by spaces.\n            tag_name, arg = token.contents.split(None, 1)\n        except ValueError:\n            msg = '%r tag requires arguments' % token.contents[0]\n            raise template.TemplateSyntaxError(msg)\n\n        m = re.search(r'(.*?) as (\\w+)', arg)\n        if m:\n            fmt, var_name = m.groups()\n        else:\n            msg = '%r tag had invalid arguments' % tag_name\n            raise template.TemplateSyntaxError(msg)\n\n        if not (fmt[0] == fmt[-1] and fmt[0] in ('\"', \"'\")):\n            msg = \"%r tag's argument should be in quotes\" % tag_name\n            raise template.TemplateSyntaxError(msg)\n\n        return CurrentTimeNode3(fmt[1:-1], var_name)\n\nNow ``do_current_time()`` passes the format string and the variable name to\n``CurrentTimeNode3``.\n\nParsing Until Another Template Tag\n----------------------------------\n\nTemplate tags can work as blocks containing other tags (like ``{% if %}``,\n``{% for %}``, etc.). To create a template tag like this, use\n``parser.parse()`` in your compilation function.\n\nHere's how the standard ``{% comment %}`` tag is implemented::\n\n    def do_comment(parser, token):\n        nodelist = parser.parse(('endcomment',))\n        parser.delete_first_token()\n        return CommentNode()\n\n    class CommentNode(template.Node):\n        def render(self, context):\n            return ''\n\n.. SL Tested ok\n\n``parser.parse()`` takes a tuple of names of template tags to parse until. It\nreturns an instance of ``django.template.NodeList``, which is a list of all\n``Node`` objects that the parser encountered *before* it encountered any of\nthe tags named in the tuple.\n\nSo in the preceding example, ``nodelist`` is a list of all nodes between\n``{% comment %}`` and ``{% endcomment %}``, not counting ``{% comment %}`` and\n``{% endcomment %}`` themselves.\n\nAfter ``parser.parse()`` is called, the parser hasn't yet \"consumed\" the ``{%\nendcomment %}`` tag, so the code needs to explicitly call\n``parser.delete_first_token()`` to prevent that tag from being processed\ntwice.\n\nThen ``CommentNode.render()`` simply returns an empty string. Anything\nbetween ``{% comment %}`` and ``{% endcomment %}`` is ignored.\n\nParsing Until Another Template Tag and Saving Contents\n------------------------------------------------------\n\nIn the previous example, ``do_comment()`` discarded everything between\n``{% comment %}`` and ``{% endcomment %}``. It's also\npossible to do something with the code between template tags instead.\n\nFor example, here's a custom template tag, ``{% upper %}``, that capitalizes\neverything between itself and ``{% endupper %}``::\n\n    {% upper %}\n        This will appear in uppercase, {{ user_name }}.\n    {% endupper %}\n\nAs in the previous example, we'll use ``parser.parse()``. This time, we\npass the resulting ``nodelist`` to ``Node``::\n\n    def do_upper(parser, token):\n        nodelist = parser.parse(('endupper',))\n        parser.delete_first_token()\n        return UpperNode(nodelist)\n\n    class UpperNode(template.Node):\n        def __init__(self, nodelist):\n            self.nodelist = nodelist\n\n        def render(self, context):\n            output = self.nodelist.render(context)\n            return output.upper()\n\n.. SL Tested ok\n\nThe only new concept here is ``self.nodelist.render(context)`` in\n``UpperNode.render()``. This simply calls ``render()`` on each ``Node`` in the\nnode list.\n\nFor more examples of complex rendering, see the source code for ``{% if %}``,\n``{% for %}``, ``{% ifequal %}``, and ``{% ifchanged %}``. They live in\n``django/template/defaulttags.py``.\n\nShortcut for Simple Tags\n------------------------\n\nMany template tags take a single argument -- a string or a template variable\nreference -- and return a string after doing some processing based solely on\nthe input argument and some external information. For example, the\n``current_time`` tag we wrote earlier is of this variety. We give it a format\nstring, and it returns the time as a string.\n\nTo ease the creation of these types of tags, Django provides a helper function,\n``simple_tag``. This function, which is a method of ``django.template.Library``,\ntakes a function that accepts one argument, wraps it in a ``render`` function\nand the other necessary bits mentioned previously, and registers it with the\ntemplate system.\n\nOur earlier ``current_time`` function could thus be written like this::\n\n    def current_time(format_string):\n        try:\n            return datetime.datetime.now().strftime(str(format_string))\n        except UnicodeEncodeError:\n            return ''\n\n    register.simple_tag(current_time)\n\nIn Python 2.4, the decorator syntax also works::\n\n    @register.simple_tag\n    def current_time(token):\n        # ...\n\nNotice a couple of things to notice about the ``simple_tag`` helper function:\n\n* Only the (single) argument is passed into our function.\n\n* Checking for the required number of arguments has already been\n  done by the time our function is called, so we don't need to do that.\n\n* The quotes around the argument (if any) have already been stripped away,\n  so we receive a plain Unicode string.\n\nInclusion Tags\n--------------\n\nAnother common template tag is the type that displays some data by\nrendering *another* template. For example, Django's admin interface uses\ncustom template tags to display the buttons along the bottom of the\n\"add/change\" form pages. Those buttons always look the same, but the link\ntargets change depending on the object being edited. They're a perfect case\nfor using a small template that is filled with details from the current object.\n\nThese sorts of tags are called *inclusion tags*. Writing inclusion tags is\nprobably best demonstrated by example. Let's write a tag that produces a list\nof books for a given ``Author`` object. We'll use the tag like this::\n\n    {% books_for_author author %}\n\nThe result will be something like this::\n\n    <ul>\n        <li>The Cat In The Hat</li>\n        <li>Hop On Pop</li>\n        <li>Green Eggs And Ham</li>\n    </ul>\n\nFirst, we define the function that takes the argument and produces a\ndictionary of data for the result. Notice that we need to return only a\ndictionary, not anything more complex. This will be used as the context for\nthe template fragment::\n\n    def books_for_author(author):\n        books = Book.objects.filter(authors__id=author.id)\n        return {'books': books}\n\nNext, we create the template used to render the tag's output. Following our\nexample, the template is very simple::\n\n    <ul>\n    {% for book in books %}\n        <li>{{ book.title }}</li>\n    {% endfor %}\n    </ul>\n\nFinally, we create and register the inclusion tag by calling the\n``inclusion_tag()`` method on a ``Library`` object.\n\nFollowing our example, if the preceding template is in a file called\n``book_snippet.html``, we register the tag like this::\n\n    register.inclusion_tag('book_snippet.html')(books_for_author)\n\nPython 2.4 decorator syntax works as well, so we could have written this,\ninstead::\n\n    @register.inclusion_tag('book_snippet.html')\n    def books_for_author(author):\n        # ...\n\nSometimes, your inclusion tags need access to values from the parent template's\ncontext. To solve this, Django provides a ``takes_context`` option for\ninclusion tags. If you specify ``takes_context`` in creating an inclusion tag,\nthe tag will have no required arguments, and the underlying Python function\nwill have one argument: the template context as of when the tag was called.\n\nFor example, say you're writing an inclusion tag that will always be used in a\ncontext that contains ``home_link`` and ``home_title`` variables that point\nback to the main page. Here's what the Python function would look like::\n\n    @register.inclusion_tag('link.html', takes_context=True)\n    def jump_link(context):\n        return {\n            'link': context['home_link'],\n            'title': context['home_title'],\n        }\n\n(Note that the first parameter to the function *must* be called ``context``.)\n\nThe template ``link.html`` might contain the following::\n\n    Jump directly to <a href=\"{{ link }}\">{{ title }}</a>.\n\nThen, anytime you want to use that custom tag, load its library and call it\nwithout any arguments, like so::\n\n    {% jump_link %}\n\nWriting Custom Template Loaders\n===============================\n\nDjango's built-in template loaders (described in the \"Inside Template Loading\"\nsection above) will usually cover all your template-loading needs, but it's\npretty easy to write your own if you need special loading logic. For example,\nyou could load templates from a database, or directly from a Subversion\nrepository using Subversion's Python bindings, or (as shown shortly) from a ZIP\narchive.\n\nA template loader -- that is, each entry in the ``TEMPLATE_LOADERS`` setting\n-- is expected to be a callable object with this interface::\n\n    load_template_source(template_name, template_dirs=None)\n\nThe ``template_name`` argument is the name of the template to load (as passed\nto ``loader.get_template()`` or ``loader.select_template()``), and\n``template_dirs`` is an optional list of directories to search instead of\n``TEMPLATE_DIRS``.\n\nIf a loader is able to successfully load a template, it should return a tuple:\n``(template_source, template_path)``. Here, ``template_source`` is the\ntemplate string that will be compiled by the template engine, and\n``template_path`` is the path the template was loaded from. That path might be\nshown to the user for debugging purposes, so it should quickly identify where\nthe template was loaded from.\n\nIf the loader is unable to load a template, it should raise\n``django.template.TemplateDoesNotExist``.\n\nEach loader function should also have an ``is_usable`` function attribute.\nThis is a Boolean that informs the template engine whether this loader\nis available in the current Python installation. For example, the eggs loader\n(which is capable of loading templates from Python eggs) sets ``is_usable``\nto ``False`` if the ``pkg_resources`` module isn't installed, because\n``pkg_resources`` is necessary to read data from eggs.\n\nAn example should help clarify all of this. Here's a template loader function\nthat can load templates from a ZIP file. It uses a custom setting,\n``TEMPLATE_ZIP_FILES``, as a search path instead of ``TEMPLATE_DIRS``, and it\nexpects each item on that path to be a ZIP file containing templates::\n\n    from django.conf import settings\n    from django.template import TemplateDoesNotExist\n    import zipfile\n\n    def load_template_source(template_name, template_dirs=None):\n        \"Template loader that loads templates from a ZIP file.\"\n\n        template_zipfiles = getattr(settings, \"TEMPLATE_ZIP_FILES\", [])\n\n        # Try each ZIP file in TEMPLATE_ZIP_FILES.\n        for fname in template_zipfiles:\n            try:\n                z = zipfile.ZipFile(fname)\n                source = z.read(template_name)\n            except (IOError, KeyError):\n                continue\n            z.close()\n            # We found a template, so return the source.\n            template_path = \"%s:%s\" % (fname, template_name)\n            return (source, template_path)\n\n        # If we reach here, the template couldn't be loaded\n        raise TemplateDoesNotExist(template_name)\n\n    # This loader is always usable (since zipfile is included with Python)\n    load_template_source.is_usable = True\n\n.. SL Tested ok\n\nThe only step left if we want to use this loader is to add it to the\n``TEMPLATE_LOADERS`` setting. If we put this code in a package called\n``mysite.zip_loader``, then we add\n``mysite.zip_loader.load_template_source`` to ``TEMPLATE_LOADERS``.\n\nConfiguring the Template System in Standalone Mode\n==================================================\n\n.. note::\n\n    This section is only of interest to people trying to use the template\n    system as an output component in another application. If you are using the\n    template system as part of a Django application, the information presented\n    here doesn't apply to you.\n\nNormally, Django loads all the configuration information it needs from its own\ndefault configuration file, combined with the settings in the module given\nin the ``DJANGO_SETTINGS_MODULE`` environment variable. (This was explained in\n\"A special Python prompt\" in Chapter 4.) But if you're using the template\nsystem independently of the rest of Django, the environment variable approach\nisn't very convenient, because you probably want to configure the template\nsystem in line with the rest of your application rather than dealing with\nsettings files and pointing to them via environment variables.\n\nTo solve this problem, you need to use the manual configuration option described\nfully in Appendix D. In a nutshell, you need to import the appropriate pieces of\nthe template system and then, *before* you call any of the template functions,\ncall ``django.conf.settings.configure()`` with any settings you wish to specify.\n\nYou might want to consider setting at least ``TEMPLATE_DIRS`` (if you are\ngoing to use template loaders), ``DEFAULT_CHARSET`` (although the default of\n``utf-8`` is probably fine) and ``TEMPLATE_DEBUG``. All available settings are\ndescribed in Appendix D, and any setting starting with ``TEMPLATE_`` is of\nobvious interest.\n\nWhat's Next\n===========\n\nContinuing this section's theme of advanced topics, the `next chapter`_ covers\nadvanced usage of Django models.\n\n.. _next chapter: ../chapter10/\n"
  },
  {
    "path": "Python/DjangoBook/chapter10.rst",
    "content": "===========================\nChapter 10: Advanced Models\n===========================\n\nIn Chapter 5, we presented an introduction to Django's database layer --\nhow to define models and how to use the database API to create, retrieve,\nupdate and delete records. In this chapter, we'll introduce you to some more\nadvanced features of this part of Django.\n\nRelated Objects\n===============\n\nRecall our book models from Chapter 5::\n\n    from django.db import models\n\n    class Publisher(models.Model):\n        name = models.CharField(max_length=30)\n        address = models.CharField(max_length=50)\n        city = models.CharField(max_length=60)\n        state_province = models.CharField(max_length=30)\n        country = models.CharField(max_length=50)\n        website = models.URLField()\n\n        def __unicode__(self):\n            return self.name\n\n    class Author(models.Model):\n        first_name = models.CharField(max_length=30)\n        last_name = models.CharField(max_length=40)\n        email = models.EmailField()\n\n        def __unicode__(self):\n            return u'%s %s' % (self.first_name, self.last_name)\n\n    class Book(models.Model):\n        title = models.CharField(max_length=100)\n        authors = models.ManyToManyField(Author)\n        publisher = models.ForeignKey(Publisher)\n        publication_date = models.DateField()\n\n        def __unicode__(self):\n            return self.title\n\nAs we explained in Chapter 5, accessing the value for a particular field on\na database object is as straightforward as using an attribute. For example,\nto determine the title of the book with ID 50, we'd do the following::\n\n    >>> from mysite.books.models import Book\n    >>> b = Book.objects.get(id=50)\n    >>> b.title\n    u'The Django Book'\n\nBut one thing we didn't mention previously is that related objects -- fields\nexpressed as either a ``ForeignKey`` or ``ManyToManyField`` -- act slightly\ndifferently.\n\nAccessing Foreign Key Values\n----------------------------\n\nWhen you access a field that's a ``ForeignKey``, you'll get the\nrelated model object. For example::\n\n    >>> b = Book.objects.get(id=50)\n    >>> b.publisher\n    <Publisher: Apress Publishing>\n    >>> b.publisher.website\n    u'http://www.apress.com/'\n\nWith ``ForeignKey`` fields, it works the other way, too, but it's slightly\ndifferent due to the non-symmetrical nature of the relationship. To get a list\nof books for a given publisher, use ``publisher.book_set.all()``, like this::\n\n    >>> p = Publisher.objects.get(name='Apress Publishing')\n    >>> p.book_set.all()\n    [<Book: The Django Book>, <Book: Dive Into Python>, ...]\n\nBehind the scenes, ``book_set`` is just a ``QuerySet`` (as covered in\nChapter 5), and it can be filtered and sliced like any other ``QuerySet``.\nFor example::\n\n    >>> p = Publisher.objects.get(name='Apress Publishing')\n    >>> p.book_set.filter(name__icontains='django')\n    [<Book: The Django Book>, <Book: Pro Django>]\n\nThe attribute name ``book_set`` is generated by appending the lower case\nmodel name to ``_set``.\n\nAccessing Many-to-Many Values\n-----------------------------\n\nMany-to-many values work like foreign-key values, except we deal with\n``QuerySet`` values instead of model instances. For example, here's how to\nview the authors for a book::\n\n    >>> b = Book.objects.get(id=50)\n    >>> b.authors.all()\n    [<Author: Adrian Holovaty>, <Author: Jacob Kaplan-Moss>]\n    >>> b.authors.filter(first_name='Adrian')\n    [<Author: Adrian Holovaty>]\n    >>> b.authors.filter(first_name='Adam')\n    []\n\nIt works in reverse, too. To view all of the books for an author, use\n``author.book_set``, like this::\n\n    >>> a = Author.objects.get(first_name='Adrian', last_name='Holovaty')\n    >>> a.book_set.all()\n    [<Book: The Django Book>, <Book: Adrian's Other Book>]\n\nHere, as with ``ForeignKey`` fields, the attribute name ``book_set`` is\ngenerated by appending the lower case model name to ``_set``.\n\nMaking Changes to a Database Schema\n===================================\n\nWhen we introduced the ``syncdb`` command in Chapter 5, we noted that\n``syncdb`` merely creates tables that don't yet exist in your database --\nit does *not* sync changes in models or perform deletions of models. If you\nadd or change a model's field, or if you delete a model, you'll need to make\nthe change in your database manually. This section explains how to do that.\n\nWhen dealing with schema changes, it's important to keep a few things in mind\nabout how Django's database layer works:\n\n* Django will complain loudly if a model contains a field that has not yet\n  been created in the database table. This will cause an error the first\n  time you use the Django database API to query the given table (i.e., it\n  will happen at code execution time, not at compilation time).\n\n* Django does *not* care if a database table contains columns that are not\n  defined in the model.\n\n* Django does *not* care if a database contains a table that is not\n  represented by a model.\n\nMaking schema changes is a matter of changing the various pieces -- the Python\ncode and the database itself -- in the right order.\n\nAdding Fields\n-------------\n\nWhen adding a field to a table/model in a production setting, the trick is to\ntake advantage of the fact that Django doesn't care if a table contains columns\nthat aren't defined in the model. The strategy is to add the column in the\ndatabase, and then update the Django model to include the new field.\n\nHowever, there's a bit of a chicken-and-egg problem here, because in order to\nknow how the new database column should be expressed in SQL, you need to look\nat the output of Django's ``manage.py sqlall`` command, which requires that the\nfield exist in the model. (Note that you're not *required* to create your\ncolumn with exactly the same SQL that Django would, but it's a good idea to do\nso, just to be sure everything's in sync.)\n\nThe solution to the chicken-and-egg problem is to use a development environment\ninstead of making the changes on a production server. (You *are* using a\ntesting/development environment, right?) Here are the detailed steps to take.\n\nFirst, take these steps in the development environment (i.e., not on the production server):\n\n1. Add the field to your model.\n\n2. Run ``manage.py sqlall [yourapp]`` to see the new ``CREATE TABLE``\n   statement for the model. Note the column definition for the new field.\n\n3. Start your database's interactive shell (e.g., ``psql`` or ``mysql``, or\n   you can use ``manage.py dbshell``). Execute an ``ALTER TABLE`` statement\n   that adds your new column.\n\n4. Launch the Python interactive shell with ``manage.py shell``\n   and verify that the new field was added properly by importing the model\n   and selecting from the table (e.g., ``MyModel.objects.all()[:5]``).\n   If you updated the database correctly, the statement should work without\n   errors.\n\nThen on the production server perform these steps:\n\n1. Start your database's interactive shell.\n\n2. Execute the ``ALTER TABLE`` statement you used in step 3 of the\n   development environment steps.\n\n3. Add the field to your model. If you're using source-code revision\n   control and you checked in your change in development environment step\n   1, now is the time to update the code (e.g., ``svn update``, with\n   Subversion) on the production server.\n\n4. Restart the Web server for the code changes to take effect.\n\nFor example, let's walk through what we'd do if we added a ``num_pages`` field\nto the ``Book`` model from Chapter 5. First, we'd alter the\nmodel in our development environment to look like this:\n\n.. parsed-literal::\n\n    class Book(models.Model):\n        title = models.CharField(max_length=100)\n        authors = models.ManyToManyField(Author)\n        publisher = models.ForeignKey(Publisher)\n        publication_date = models.DateField()\n        **num_pages = models.IntegerField(blank=True, null=True)**\n\n        def __unicode__(self):\n            return self.title\n\n.. SL Tested ok\n\n(Note: Read the section \"Making Fields Optional\" in Chapter 6, plus the\nsidebar \"Adding NOT NULL Columns\" below for important details on why we\nincluded ``blank=True`` and ``null=True``.)\n\nThen we'd run the command ``manage.py sqlall books`` to see the\n``CREATE TABLE`` statement. Depending on your database backend, it would\nlook something like this::\n\n    CREATE TABLE \"books_book\" (\n        \"id\" serial NOT NULL PRIMARY KEY,\n        \"title\" varchar(100) NOT NULL,\n        \"publisher_id\" integer NOT NULL REFERENCES \"books_publisher\" (\"id\"),\n        \"publication_date\" date NOT NULL,\n        \"num_pages\" integer NULL\n    );\n\nThe new column is represented like this::\n\n    \"num_pages\" integer NULL\n\nNext, we'd start the database's interactive shell for our development database\nby typing ``psql`` (for PostgreSQL), and we'd execute the following statements::\n\n    ALTER TABLE books_book ADD COLUMN num_pages integer;\n\n.. SL Tested ok\n\n.. admonition:: Adding NOT NULL Columns\n\n    There's a subtlety here that deserves mention. When we added the\n    ``num_pages`` field to our model, we included the ``blank=True`` and\n    ``null=True`` options. We did this because a database column will contain\n    NULL values when you first create it.\n\n    However, it's also possible to add columns that cannot contain NULL values.\n    To do this, you have to create the column as ``NULL``, then populate the\n    column's values using some default(s), and then alter the column to set the\n    ``NOT NULL`` modifier. For example::\n\n        BEGIN;\n        ALTER TABLE books_book ADD COLUMN num_pages integer;\n        UPDATE books_book SET num_pages=0;\n        ALTER TABLE books_book ALTER COLUMN num_pages SET NOT NULL;\n        COMMIT;\n\n    If you go down this path, remember that you should leave off\n    ``blank=True`` and ``null=True`` in your model (obviously).\n\nAfter the ``ALTER TABLE`` statement, we'd verify that the change worked\nproperly by starting the Python shell and running this code::\n\n    >>> from mysite.books.models import Book\n    >>> Book.objects.all()[:5]\n\n.. SL Tested ok\n\nIf that code didn't cause errors, we'd switch to our production server and\nexecute the ``ALTER TABLE`` statement on the production database. Then, we'd\nupdate the model in the production environment and restart the Web server.\n\nRemoving Fields\n---------------\n\nRemoving a field from a model is a lot easier than adding one. To remove a\nfield, just follow these steps:\n\n1. Remove the field from your model and restart the Web server.\n\n2. Remove the column from your database, using a command like this::\n\n       ALTER TABLE books_book DROP COLUMN num_pages;\n\n.. SL Tested ok\n\nMake sure to do it in this order. If you remove the column from your database\nfirst, Django will immediately begin raising errors.\n\nRemoving Many-to-Many Fields\n----------------------------\n\nBecause many-to-many fields are different than normal fields, the removal\nprocess is different:\n\n1. Remove the ``ManyToManyField`` from your model and restart the Web\n   server.\n\n2. Remove the many-to-many table from your database, using a command like\n   this::\n\n       DROP TABLE books_book_authors;\n\nAs in the previous section, make sure to do it in this order.\n\nRemoving Models\n---------------\n\nRemoving a model entirely is as easy as removing a field. To remove a model,\njust follow these steps:\n\n1. Remove the model from your ``models.py`` file and restart the Web server.\n\n2. Remove the table from your database, using a command like this::\n\n       DROP TABLE books_book;\n\n   Note that you might need to remove any dependent tables from your\n   database first -- e.g., any tables that have foreign keys to\n   ``books_book``.\n\nAs in the previous sections, make sure to do it in this order.\n\nManagers\n========\n\nIn the statement ``Book.objects.all()``, ``objects`` is a special attribute\nthrough which you query your database. In Chapter 5, we briefly identified this\nas the model's *manager*. Now it's time to dive a bit deeper into what managers\nare and how you can use them.\n\nIn short, a model's manager is an object through which Django models perform\ndatabase queries. Each Django model has at least one manager, and you can\ncreate custom managers in order to customize database access.\n\nThere are two reasons you might want to create a custom manager: to add extra\nmanager methods, and/or to modify the initial ``QuerySet`` the manager\nreturns.\n\nAdding Extra Manager Methods\n----------------------------\n\nAdding extra manager methods is the preferred way to add \"table-level\"\nfunctionality to your models. (For \"row-level\" functionality -- i.e., functions\nthat act on a single instance of a model object -- use model methods, which are\nexplained later in this chapter.)\n\nFor example, let's give our ``Book`` model a manager method ``title_count()``\nthat takes a keyword and returns the number of books that have a title\ncontaining that keyword. (This example is slightly contrived, but it\ndemonstrates how managers work.)\n\n.. parsed-literal::\n\n    # models.py\n\n    from django.db import models\n\n    # ... Author and Publisher models here ...\n\n    **class BookManager(models.Manager):**\n        **def title_count(self, keyword):**\n            **return self.filter(title__icontains=keyword).count()**\n\n    class Book(models.Model):\n        title = models.CharField(max_length=100)\n        authors = models.ManyToManyField(Author)\n        publisher = models.ForeignKey(Publisher)\n        publication_date = models.DateField()\n        num_pages = models.IntegerField(blank=True, null=True)\n        **objects = BookManager()**\n\n        def __unicode__(self):\n            return self.title\n\nWith this manager in place, we can now do this::\n\n    >>> Book.objects.title_count('django')\n    4\n    >>> Book.objects.title_count('python')\n    18\n\nHere are some notes about the code:\n\n* We've created a ``BookManager`` class that extends\n  ``django.db.models.Manager``. This has a single method,\n  ``title_count()``, which does the calculation. Note that the method uses\n  ``self.filter()``, where ``self`` refers to the manager itself.\n\n* We've assigned ``BookManager()`` to the ``objects`` attribute on the\n  model. This has the effect of replacing the \"default\" manager for the\n  model, which is called ``objects`` and is automatically created if you\n  don't specify a custom manager. We call it ``objects`` rather than\n  something else, so as to be consistent with automatically created\n  managers.\n\nWhy would we want to add a method such as ``title_count()``? To encapsulate\ncommonly executed queries so that we don't have to duplicate code.\n\nModifying Initial Manager QuerySets\n-----------------------------------\n\nA manager's base ``QuerySet`` returns all objects in the system. For\nexample, ``Book.objects.all()`` returns all books in the book database.\n\nYou can override a manager's base ``QuerySet`` by overriding the\n``Manager.get_query_set()`` method. ``get_query_set()`` should return a\n``QuerySet`` with the properties you require.\n\nFor example, the following model has *two* managers -- one that returns\nall objects, and one that returns only the books by Roald Dahl.\n\n.. parsed-literal::\n\n    from django.db import models\n\n    **# First, define the Manager subclass.**\n    **class DahlBookManager(models.Manager):**\n        **def get_query_set(self):**\n            **return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl')**\n\n    **# Then hook it into the Book model explicitly.**\n    class Book(models.Model):\n        title = models.CharField(max_length=100)\n        author = models.CharField(max_length=50)\n        # ...\n\n        **objects = models.Manager() # The default manager.**\n        **dahl_objects = DahlBookManager() # The Dahl-specific manager.**\n\n.. SL Tested ok\n\nWith this sample model, ``Book.objects.all()`` will return all books in the\ndatabase, but ``Book.dahl_objects.all()`` will only return the ones written by\nRoald Dahl. Note that we explicitly set ``objects`` to a vanilla ``Manager``\ninstance, because if we hadn't, the only available manager would be\n``dahl_objects``.\n\nOf course, because ``get_query_set()`` returns a ``QuerySet`` object, you can\nuse ``filter()``, ``exclude()`` and all the other ``QuerySet`` methods on it.\nSo these statements are all legal::\n\n    Book.dahl_objects.all()\n    Book.dahl_objects.filter(title='Matilda')\n    Book.dahl_objects.count()\n\nThis example also pointed out another interesting technique: using multiple\nmanagers on the same model. You can attach as many ``Manager()`` instances to\na model as you'd like. This is an easy way to define common \"filters\" for your\nmodels.\n\nFor example::\n\n    class MaleManager(models.Manager):\n        def get_query_set(self):\n            return super(MaleManager, self).get_query_set().filter(sex='M')\n\n    class FemaleManager(models.Manager):\n        def get_query_set(self):\n            return super(FemaleManager, self).get_query_set().filter(sex='F')\n\n    class Person(models.Model):\n        first_name = models.CharField(max_length=50)\n        last_name = models.CharField(max_length=50)\n        sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))\n        people = models.Manager()\n        men = MaleManager()\n        women = FemaleManager()\n\nThis example allows you to request ``Person.men.all()``, ``Person.women.all()``,\nand ``Person.people.all()``, yielding predictable results.\n\n.. SL Tested ok\n\nIf you use custom ``Manager`` objects, take note that the first\n``Manager`` Django encounters (in the order in which they're defined\nin the model) has a special status. Django interprets this first\n``Manager`` defined in a class as the \"default\" ``Manager``, and\nseveral parts of Django (though not the admin application) will use\nthat ``Manager`` exclusively for that model. As a result, it's often a\ngood idea to be careful in your choice of default manager, in order to\navoid a situation where overriding of ``get_query_set()`` results in\nan inability to retrieve objects you'd like to work with.\n\nModel methods\n=============\n\nDefine custom methods on a model to add custom \"row-level\" functionality to your\nobjects. Whereas managers are intended to do \"table-wide\" things, model methods\nshould act on a particular model instance.\n\nThis is a valuable technique for keeping business logic in one place -- the\nmodel.\n\nAn example is the easiest way to explain this. Here's a model with a few custom\nmethods::\n\n    from django.contrib.localflavor.us.models import USStateField\n    from django.db import models\n\n    class Person(models.Model):\n        first_name = models.CharField(max_length=50)\n        last_name = models.CharField(max_length=50)\n        birth_date = models.DateField()\n        address = models.CharField(max_length=100)\n        city = models.CharField(max_length=50)\n        state = USStateField() # Yes, this is U.S.-centric...\n\n        def baby_boomer_status(self):\n            \"Returns the person's baby-boomer status.\"\n            import datetime\n            if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):\n                return \"Baby boomer\"\n            if self.birth_date < datetime.date(1945, 8, 1):\n                return \"Pre-boomer\"\n            return \"Post-boomer\"\n\n        def is_midwestern(self):\n            \"Returns True if this person is from the Midwest.\"\n            return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')\n\n        def _get_full_name(self):\n            \"Returns the person's full name.\"\n            return u'%s %s' % (self.first_name, self.last_name)\n        full_name = property(_get_full_name)\n\nThe last method in this example is a \"property.\" Read more about properties\nat http://www.python.org/download/releases/2.2/descrintro/#property\n\nAnd here's example usage::\n\n    >>> p = Person.objects.get(first_name='Barack', last_name='Obama')\n    >>> p.birth_date\n    datetime.date(1961, 8, 4)\n    >>> p.baby_boomer_status()\n    'Baby boomer'\n    >>> p.is_midwestern()\n    True\n    >>> p.full_name  # Note this isn't a method -- it's treated as an attribute\n    u'Barack Obama'\n\nExecuting Raw SQL Queries\n=========================\n\nSometimes you'll find that the Django database API can only take you so far,\nand you'll want to write custom SQL queries against your database. You can do\nthis very easily by accessing the object ``django.db.connection``, which\nrepresents the current database connection. To use it, call\n``connection.cursor()`` to get a cursor object. Then, call\n``cursor.execute(sql, [params])`` to execute the SQL and\n``cursor.fetchone()`` or ``cursor.fetchall()`` to return the resulting\nrows. For example::\n\n    >>> from django.db import connection\n    >>> cursor = connection.cursor()\n    >>> cursor.execute(\"\"\"\n    ...    SELECT DISTINCT first_name\n    ...    FROM people_person\n    ...    WHERE last_name = %s\"\"\", ['Lennon'])\n    >>> row = cursor.fetchone()\n    >>> print row\n    ['John']\n\n.. SL Tested ok\n\n``connection`` and ``cursor`` mostly implement the standard Python \"DB-API,\"\nwhich you can read about at http://www.python.org/peps/pep-0249.html. If you're\nnot familiar with the Python DB-API, note that the SQL statement in\n``cursor.execute()`` uses placeholders, ``\"%s\"``, rather than adding parameters\ndirectly within the SQL. If you use this technique, the underlying database\nlibrary will automatically add quotes and escaping to your parameter(s) as\nnecessary.\n\nRather than littering your view code with these ``django.db.connection``\nstatements, it's a good idea to put them in custom model methods or manager\nmethods. For example, the above example could be integrated into a custom\nmanager method like this::\n\n    from django.db import connection, models\n\n    class PersonManager(models.Manager):\n        def first_names(self, last_name):\n            cursor = connection.cursor()\n            cursor.execute(\"\"\"\n                SELECT DISTINCT first_name\n                FROM people_person\n                WHERE last_name = %s\"\"\", [last_name])\n            return [row[0] for row in cursor.fetchone()]\n\n    class Person(models.Model):\n        first_name = models.CharField(max_length=50)\n        last_name = models.CharField(max_length=50)\n        objects = PersonManager()\n\nAnd sample usage::\n\n    >>> Person.objects.first_names('Lennon')\n    ['John', 'Cynthia']\n\nWhat's Next?\n============\n\nIn the `next chapter`_, we'll show you Django's \"generic views\" framework, which\nlets you save time in building Web sites that follow common patterns.\n\n.. _next chapter: ../chapter11/\n"
  },
  {
    "path": "Python/DjangoBook/chapter11.rst",
    "content": "=========================\nChapter 11: Generic Views\n=========================\n\nHere again is a recurring theme of this book: at its worst, Web development is\nboring and monotonous. So far, we've covered how Django tries to take away\nsome of that monotony at the model and template layers, but Web developers\nalso experience this boredom at the view level.\n\nDjango's *generic views* were developed to ease that pain. They take certain\ncommon idioms and patterns found in view development and abstract them so that\nyou can quickly write common views of data without having to write too much\ncode. In fact, nearly every view example in the preceding chapters could be\nrewritten with the help of generic views.\n\nChapter 8 touched briefly on how you'd go about making a view \"generic.\" To\nreview, we can recognize certain common tasks, like displaying a list of\nobjects, and write code that displays a list of *any* object. Then the model in\nquestion can be passed as an extra argument to the URLconf.\n\nDjango ships with generic views to do the following:\n\n* Perform common \"simple\" tasks: redirect to a different page, or\n  render a given template.\n\n* Display \"list\" and \"detail\" pages for a single object. The ``event_list``\n  and ``entry_list`` views from Chapter 8 are examples of list views. A\n  single event page is an example of what we call a \"detail\" view.\n\n* Present date-based objects in year/month/day archive pages,\n  associated detail, and \"latest\" pages. The Django Weblog's\n  (http://www.djangoproject.com/weblog/) year, month, and\n  day archives are built with these, as would be a typical\n  newspaper's archives.\n\nTaken together, these views provide easy interfaces to perform the most common\ntasks developers encounter.\n\nUsing Generic Views\n===================\n\nAll of these views are used by creating configuration dictionaries in\nyour URLconf files and passing those dictionaries as the third member of the\nURLconf tuple for a given pattern. (See \"Passing Extra Options to View\nFunctions\" in Chapter 8 for an overview of this technique.)\n\nFor example, here's a simple URLconf you could use to present a static \"about\"\npage::\n\n    from django.conf.urls.defaults import *\n    from django.views.generic.simple import direct_to_template\n\n    urlpatterns = patterns('',\n        (r'^about/$', direct_to_template, {\n            'template': 'about.html'\n        })\n    )\n\nThough this might seem a bit \"magical\" at first glance  -- look, a view with no\ncode! --, it's actually exactly the same as the examples in Chapter 8: the\n``direct_to_template`` view simply grabs information from the extra-parameters\ndictionary and uses that information when rendering the view.\n\nBecause this generic view -- and all the others -- is a regular view function\nlike any other, we can reuse it inside our own views. As an example, let's\nextend our \"about\" example to map URLs of the form ``/about/<whatever>/`` to\nstatically rendered ``about/<whatever>.html``. We'll do this by first modifying\nthe URLconf to point to a view function:\n\n.. parsed-literal::\n\n    from django.conf.urls.defaults import *\n    from django.views.generic.simple import direct_to_template\n    **from mysite.books.views import about_pages**\n\n    urlpatterns = patterns('',\n        (r'^about/$', direct_to_template, {\n            'template': 'about.html'\n        }),\n        **(r'^about/(\\\\w+)/$', about_pages),**\n    )\n\nNext, we'll write the ``about_pages`` view::\n\n    from django.http import Http404\n    from django.template import TemplateDoesNotExist\n    from django.views.generic.simple import direct_to_template\n\n    def about_pages(request, page):\n        try:\n            return direct_to_template(request, template=\"about/%s.html\" % page)\n        except TemplateDoesNotExist:\n            raise Http404()\n\nHere we're treating ``direct_to_template`` like any other function. Since it\nreturns an ``HttpResponse``, we can simply return it as-is. The only slightly\ntricky business here is dealing with missing templates. We don't want a\nnonexistent template to cause a server error, so we catch\n``TemplateDoesNotExist`` exceptions and return 404 errors instead.\n\n.. admonition:: Is There a Security Vulnerability Here?\n\n    Sharp-eyed readers may have noticed a possible security hole: we're\n    constructing the template name using interpolated content from the browser\n    (``template=\"about/%s.html\" % page``). At first glance, this looks like a\n    classic *directory traversal* vulnerability (discussed in detail in Chapter\n    20). But is it really?\n\n    Not exactly. Yes, a maliciously crafted value of ``page`` could cause\n    directory traversal, but although ``page`` *is* taken from the request URL,\n    not every value will be accepted. The key is in the URLconf: we're using\n    the regular expression ``\\w+`` to match the ``page`` part of the URL, and\n    ``\\w`` only accepts letters and numbers. Thus, any malicious characters\n    (such as dots and slashes) will be rejected by the URL resolver before they\n    reach the view itself.\n\nGeneric Views of Objects\n========================\n\nThe ``direct_to_template`` view certainly is useful, but Django's generic views\nreally shine when it comes to presenting views on your database content. Because\nit's such a common task, Django comes with a handful of built-in generic views\nthat make generating list and detail views of objects incredibly easy.\n\nLet's take a look at one of these generic views: the \"object list\" view. We'll\nbe using this ``Publisher`` object from Chapter 5::\n\n    class Publisher(models.Model):\n        name = models.CharField(max_length=30)\n        address = models.CharField(max_length=50)\n        city = models.CharField(max_length=60)\n        state_province = models.CharField(max_length=30)\n        country = models.CharField(max_length=50)\n        website = models.URLField()\n\n        def __unicode__(self):\n            return self.name\n\n        class Meta:\n            ordering = ['name']\n\nTo build a list page of all publishers, we'd use a URLconf along these lines::\n\n    from django.conf.urls.defaults import *\n    from django.views.generic import list_detail\n    from mysite.books.models import Publisher\n\n    publisher_info = {\n        'queryset': Publisher.objects.all(),\n    }\n\n    urlpatterns = patterns('',\n        (r'^publishers/$', list_detail.object_list, publisher_info)\n    )\n\nThat's all the Python code we need to write. We still need to write a template,\nhowever. We can explicitly tell the ``object_list`` view which template to use\nby including a ``template_name`` key in the extra arguments dictionary:\n\n.. parsed-literal::\n\n    from django.conf.urls.defaults import *\n    from django.views.generic import list_detail\n    from mysite.books.models import Publisher\n\n    publisher_info = {\n        'queryset': Publisher.objects.all(),\n        **'template_name': 'publisher_list_page.html',**\n    }\n\n    urlpatterns = patterns('',\n        (r'^publishers/$', list_detail.object_list, publisher_info)\n    )\n\nIn the absence of ``template_name``, though, the ``object_list`` generic view\nwill infer one from the object's name. In this case, the inferred template will\nbe ``\"books/publisher_list.html\"`` -- the \"books\" part comes from the name of\nthe app that defines the model, while the \"publisher\" bit is just the\nlowercased version of the model's name.\n\nThis template will be rendered against a context containing a variable called\n``object_list`` that contains all the publisher objects. A very simple template\nmight look like the following::\n\n    {% extends \"base.html\" %}\n\n    {% block content %}\n        <h2>Publishers</h2>\n        <ul>\n            {% for publisher in object_list %}\n                <li>{{ publisher.name }}</li>\n            {% endfor %}\n        </ul>\n    {% endblock %}\n\n.. SL Tested ok\n\n(Note that this assumes the existence of a ``base.html`` template, as we\nprovided in an example in Chapter 4.)\n\nThat's really all there is to it. All the cool features of generic views come\nfrom changing the \"info\" dictionary passed to the generic view. Appendix D\ndocuments all the generic views and all their options in detail; the rest of\nthis chapter will consider some of the common ways you might customize and\nextend generic views.\n\nExtending Generic Views\n=======================\n\nThere's no question that using generic views can speed up development\nsubstantially. In most projects, however, there comes a moment when the\ngeneric views no longer suffice. Indeed, one of the most common questions asked\nby new Django developers is how to make generic views handle a wider array of\nsituations.\n\nLuckily, in nearly every one of these cases, there are ways to simply extend\ngeneric views to handle a larger array of use cases. These situations usually\nfall into a handful of patterns dealt with in the sections that follow.\n\nMaking \"Friendly\" Template Contexts\n-----------------------------------\n\nYou might have noticed that sample publisher list template stores all the books\nin a variable named ``object_list``. While this works just fine, it isn't all\nthat \"friendly\" to template authors: they have to \"just know\" that they're\ndealing with books here. A better name for that variable would be ``publisher_list``;\nthat variable's content is pretty obvious.\n\nWe can change the name of that variable easily with the ``template_object_name``\nargument:\n\n.. parsed-literal::\n\n    from django.conf.urls.defaults import *\n    from django.views.generic import list_detail\n    from mysite.books.models import Publisher\n\n    publisher_info = {\n        'queryset': Publisher.objects.all(),\n        'template_name': 'publisher_list_page.html',\n        'template_object_name': 'publisher',\n    }\n\n    urlpatterns = patterns('',\n        (r'^publishers/$', list_detail.object_list, publisher_info)\n    )\n\nIn the template, the generic view will append ``_list`` to the\n``template_object_name`` to create the variable name representing the list\nof items.\n\nProviding a useful ``template_object_name`` is always a good idea. Your coworkers\nwho design templates will thank you.\n\nAdding Extra Context\n--------------------\n\nSometimes, you might need to present some extra information beyond that\nprovided by the generic view. For example, think of showing a list of all the\nother publishers on each publisher detail page. The ``object_detail`` generic\nview provides the publisher to the context, but it seems there's no way to get\na list of *all* publishers in that template.\n\nBut there is: all generic views take an extra optional parameter,\n``extra_context``. This is a dictionary of extra objects that will be added to\nthe template's context. So, to provide the list of all publishers on the\ndetail view, we'd use an info dictionary like this:\n\n.. parsed-literal::\n\n    publisher_info = {\n        'queryset': Publisher.objects.all(),\n        'template_object_name': 'publisher',\n        **'extra_context': {'book_list': Book.objects.all()}**\n    }\n\n.. SL Tested ok\n\nThis would populate a ``{{ book_list }}`` variable in the template context.\nThis pattern can be used to pass any information down into the template for the\ngeneric view. It's very handy.\n\nHowever, there's actually a subtle bug here -- can you spot it?\n\nThe problem has to do with when the queries in ``extra_context`` are evaluated.\nBecause this example puts ``Book.objects.all()`` in the URLconf, it will\nbe evaluated only once (when the URLconf is first loaded). Once you add or\nremove publishers, you'll notice that the generic view doesn't reflect those\nchanges until you reload the Web server (see \"Caching and QuerySets\" in\nAppendix C for more information about when ``QuerySet`` objects are cached and\nevaluated).\n\n.. note::\n\n    This problem doesn't apply to the ``queryset`` generic view argument. Since\n    Django knows that particular QuerySet should *never* be cached, the generic\n    view takes care of clearing the cache when each view is rendered.\n\nThe solution is to use a *callback* in ``extra_context`` instead of a value.\nAny callable (i.e., a function) that's passed to ``extra_context`` will be\nevaluated when the view is rendered (instead of only once). You could do this\nwith an explicitly defined function:\n\n.. parsed-literal::\n\n    **def get_books():**\n        **return Book.objects.all()**\n\n    publisher_info = {\n        'queryset': Publisher.objects.all(),\n        'template_object_name': 'publisher',\n        'extra_context': **{'book_list': get_books}**\n    }\n\nOr, you could use a less obvious but shorter version that relies on the fact\nthat ``Book.objects.all`` is itself a callable:\n\n.. parsed-literal::\n\n    publisher_info = {\n        'queryset': Publisher.objects.all(),\n        'template_object_name': 'publisher',\n        'extra_context': **{'book_list': Book.objects.all}**\n    }\n\nNotice the lack of parentheses after ``Book.objects.all``. This references\nthe function without actually calling it (which the generic view will do later).\n\nViewing Subsets of Objects\n--------------------------\n\nNow let's take a closer look at this ``queryset`` key we've been using all\nalong. Most generic views take one of these ``queryset`` arguments -- it's how the\nview knows which set of objects to display (see \"Selecting Objects\" in Chapter 5\nfor an introduction to ``QuerySet`` objects, and see Appendix B for the complete\ndetails).\n\nTo pick a simple example, we might want to order a list of books by\npublication date, with the most recent first:\n\n.. parsed-literal::\n\n    book_info = {\n        'queryset': Book.objects.order_by('-publication_date'),\n    }\n\n    urlpatterns = patterns('',\n        (r'^publishers/$', list_detail.object_list, publisher_info),\n        **(r'^books/$', list_detail.object_list, book_info),**\n    )\n\n.. SL Tested ok\n\nThat's a pretty simple example, but it illustrates the idea nicely. Of course,\nyou'll usually want to do more than just reorder objects. If you want to\npresent a list of books by a particular publisher, you can use the same\ntechnique:\n\n.. parsed-literal::\n\n    **apress_books = {**\n        **'queryset': Book.objects.filter(publisher__name='Apress Publishing'),**\n        **'template_name': 'books/apress_list.html'**\n    **}**\n\n    urlpatterns = patterns('',\n        (r'^publishers/$', list_detail.object_list, publisher_info),\n        **(r'^books/apress/$', list_detail.object_list, apress_books),**\n    )\n\n.. SL Tested ok\n\nNotice that along with a filtered ``queryset``, we're also using a custom\ntemplate name. If we didn't, the generic view would use the same template as the\n\"vanilla\" object list, which might not be what we want.\n\nAlso notice that this isn't a very elegant way of doing publisher-specific\nbooks. If we want to add another publisher page, we'd need another handful of\nlines in the URLconf, and more than a few publishers would get unreasonable.\nWe'll deal with this problem in the next section.\n\nComplex Filtering with Wrapper Functions\n----------------------------------------\n\nAnother common need is to filter the objects given in a list page by some key\nin the URL. Earlier we hard-coded the publisher's name in the URLconf, but what\nif we wanted to write a view that displayed all the books by some arbitrary\npublisher? The solution is to \"wrap\" the ``object_list`` generic view to avoid\nwriting a lot of code by hand. As usual, we'll start by writing a URLconf:\n\n.. parsed-literal::\n\n    urlpatterns = patterns('',\n        (r'^publishers/$', list_detail.object_list, publisher_info),\n        **(r'^books/(\\\\w+)/$', books_by_publisher),**\n    )\n\nNext, we'll write the ``books_by_publisher`` view itself::\n\n    from django.shortcuts import get_object_or_404\n    from django.views.generic import list_detail\n    from mysite.books.models import Book, Publisher\n\n    def books_by_publisher(request, name):\n\n        # Look up the publisher (and raise a 404 if it can't be found).\n        publisher = get_object_or_404(Publisher, name__iexact=name)\n\n        # Use the object_list view for the heavy lifting.\n        return list_detail.object_list(\n            request,\n            queryset = Book.objects.filter(publisher=publisher),\n            template_name = 'books/books_by_publisher.html',\n            template_object_name = 'book',\n            extra_context = {'publisher': publisher}\n        )\n\n.. SL Tested ok\n\nThis works because there's really nothing special about generic views --\nthey're just Python functions. Like any view function, generic views expect a\ncertain set of arguments and return ``HttpResponse`` objects. Thus, it's\nincredibly easy to wrap a small function around a generic view that does\nadditional work before (or after; see the next section) handing things off to the\ngeneric view.\n\n.. note::\n\n    Notice that in the preceding example we passed the current publisher being\n    displayed in the ``extra_context``. This is usually a good idea in wrappers\n    of this nature; it lets the template know which \"parent\" object is currently\n    being browsed.\n\nPerforming Extra Work\n---------------------\n\nThe last common pattern we'll look at involves doing some extra work before\nor after calling the generic view.\n\nImagine we had a ``last_accessed`` field on our ``Author`` object that we were\nusing to keep track of the last time anybody looked at that author. The generic\n``object_detail`` view, of course, wouldn't know anything about this field, but\nonce again we could easily write a custom view to keep that field updated.\n\nFirst, we'd need to add an author detail bit in the URLconf to point to a\ncustom view:\n\n.. parsed-literal::\n\n    from mysite.books.views import author_detail\n\n    urlpatterns = patterns('',\n        # ...\n        **(r'^authors/(?P<author_id>\\\\d+)/$', author_detail),**\n        # ...\n    )\n\nThen we'd write our wrapper function::\n\n    import datetime\n    from django.shortcuts import get_object_or_404\n    from django.views.generic import list_detail\n    from mysite.books.models import Author\n\n    def author_detail(request, author_id):\n        # Delegate to the generic view and get an HttpResponse.\n        response = list_detail.object_detail(\n            request,\n            queryset = Author.objects.all(),\n            object_id = author_id,\n        )\n\n        # Record the last accessed date. We do this *after* the call\n        # to object_detail(), not before it, so that this won't be called\n        # unless the Author actually exists. (If the author doesn't exist,\n        # object_detail() will raise Http404, and we won't reach this point.)\n        now = datetime.datetime.now()\n        Author.objects.filter(id=author_id).update(last_accessed=now)\n\n        return response\n\n.. note::\n\n    This code won't actually work unless you add a ``last_accessed`` field to\n    your ``Author`` model and create a ``books/author_detail.html`` template.\n\n.. SL Tested ok\n\nWe can use a similar idiom to alter the response returned by the generic view.\nIf we wanted to provide a downloadable plain-text version of the list of authors,\nwe could use a view like this::\n\n    def author_list_plaintext(request):\n        response = list_detail.object_list(\n            request,\n            queryset = Author.objects.all(),\n            mimetype = 'text/plain',\n            template_name = 'books/author_list.txt'\n        )\n        response[\"Content-Disposition\"] = \"attachment; filename=authors.txt\"\n        return response\n\n.. SL Tested ok\n\nThis works because the generic views return simple ``HttpResponse`` objects\nthat can be treated like dictionaries to set HTTP headers. This\n``Content-Disposition`` business, by the way, instructs the browser to\ndownload and save the page instead of displaying it in the browser.\n\nWhat's Next?\n============\n\nIn this chapter we looked at only a couple of the generic views Django ships\nwith, but the general ideas presented here should apply pretty closely to any\ngeneric view. Appendix C covers all the available views in detail, and it's\nrecommended reading if you want to get the most out of this powerful feature.\n\nThis concludes the section of this book devoted to \"advanced usage.\" In the\n`next chapter`_, we cover deployment of Django applications.\n\n.. _next chapter: ../chapter12/\n"
  },
  {
    "path": "Python/DjangoBook/chapter12.rst",
    "content": "============================\nChapter 12: Deploying Django\n============================\n\nThis chapter covers the last essential step of building a Django application:\ndeploying it to a production server.\n\nIf you've been following along with our ongoing examples, you've likely been\nusing the ``runserver``, which makes things very easy -- with ``runserver``,\nyou don't have to worry about Web server setup. But ``runserver`` is intended\nonly for development on your local machine, not for exposure on the public Web.\nTo deploy your Django application, you'll need to hook it into an\nindustrial-strength Web server such as Apache. In this chapter, we'll show you\nhow to do that -- but, first, we'll give you a checklist of things to do in\nyour codebase before you go live.\n\nPreparing Your Codebase for Production\n======================================\n\nFortunately, the ``runserver`` approximates a \"real\" Web server closely enough\nthat not very many changes need to be made to a Django application in order to\nmake it production-ready. But there are a few *essential things* you should do\nbefore you turn the switch.\n\nTurning Off Debug Mode\n----------------------\n\nWhen we created a project in Chapter 2, the command\n``django-admin.py startproject`` created a ``settings.py`` file with ``DEBUG``\nset to ``True``. Many internal parts of Django check this setting and change\ntheir behavior if ``DEBUG`` mode is on. For example, if ``DEBUG`` is set to\n``True``, then:\n\n* All database queries will be saved in memory as the object\n  ``django.db.connection.queries``. As you can imagine, this eats up\n  memory!\n\n* Any 404 error will be rendered by Django's special 404 error page\n  (covered in Chapter 3) rather than returning a proper 404 response. This\n  page contains potentially sensitive information and should *not* be\n  exposed to the public Internet.\n\n* Any uncaught exception in your Django application -- from basic Python\n  syntax errors to database errors to template syntax errors -- will be\n  rendered by the Django pretty error page that you've likely come to know\n  and love. This page contains even *more* sensitive information than the\n  404 page and should *never* be exposed to the public.\n\nIn short, setting ``DEBUG`` to ``True`` tells Django to assume only trusted\ndevelopers are using your site. The Internet is full of untrustworthy\nhooligans, and the first thing you should do when you're preparing your\napplication for deployment is set ``DEBUG`` to ``False``.\n\nTurning Off Template Debug Mode\n-------------------------------\n\nSimilarly, you should set ``TEMPLATE_DEBUG`` to ``False`` in production. If\n``True``, this setting tells Django's template system to save some extra\ninformation about every template, for use on the pretty error pages.\n\nImplementing a 404 Template\n---------------------------\n\nIf ``DEBUG`` is ``True``, Django displays the useful 404 error page. But if\n``DEBUG`` is ``False``, then it does something different: it renders a template\ncalled ``404.html`` in your root template directory. So, when you're ready to\ndeploy, you'll need to create this template and put a useful \"Page not found\"\nmessage in it.\n\nHere's a sample ``404.html`` you can use as a starting point. It assumes you're\nusing template inheritance and have defined a ``base.html`` with blocks called\n``title`` and ``content``.\n\n::\n\n    {% extends \"base.html\" %}\n\n    {% block title %}Page not found{% endblock %}\n\n    {% block content %}\n    <h1>Page not found</h1>\n\n    <p>Sorry, but the requested page could not be found.</p>\n    {% endblock %}\n\nTo test that your ``404.html`` is working, just change ``DEBUG`` to ``False``\nand visit a nonexistent URL. (This works on the ``runserver`` just as well as\nit works on a production server.)\n\nImplementing a 500 Template\n---------------------------\n\nSimilarly, if ``DEBUG`` is ``False``, then Django no longer displays its useful\nerror/traceback pages in case of an unhandled Python exception. Instead, it\nlooks for a template called ``500.html`` and renders it. Like ``404.html``,\nthis template should live in your root template directory.\n\nThere's one slightly tricky thing about ``500.html``. You can never be sure\n*why* this template is being rendered, so it shouldn't do anything that\nrequires a database connection or relies on any potentially broken part of your\ninfrastructure. (For example, it should not use custom template tags.) If it\nuses template inheritance, then the parent template(s) shouldn't rely on\npotentially broken infrastructure, either. Therefore, the best approach is to\navoid template inheritance and use something very simple. Here's an example\n``500.html`` as a starting point::\n\n    <!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n        \"http://www.w3.org/TR/html4/strict.dtd\">\n    <html lang=\"en\">\n    <head>\n        <title>Page unavailable</title>\n    </head>\n    <body>\n        <h1>Page unavailable</h1>\n\n        <p>Sorry, but the requested page is unavailable due to a\n        server hiccup.</p>\n\n        <p>Our engineers have been notified, so check back later.</p>\n    </body>\n    </html>\n\nSetting Up Error Alerts\n-----------------------\n\nWhen your Django-powered site is running and an exception is raised, you'll\nwant to know about it, so you can fix it. By default, Django is configured to\nsend an e-mail to the site developers whenever your code raises an unhandled\nexception -- but you need to do two things to set it up.\n\nFirst, change your ``ADMINS`` setting to include your e-mail address, along\nwith the e-mail addresses of any other people who need to be notified. This\nsetting takes a tuple of ``(name, email)`` tuples, like this::\n\n    ADMINS = (\n        ('John Lennon', 'jlennon@example.com'),\n        ('Paul McCartney', 'pmacca@example.com'),\n    )\n\nSecond, make sure your server is configured to send e-mail. Setting up\n``postfix``, ``sendmail`` or any other mail server is outside the scope of this\nbook, but on the Django side of things, you'll want to make sure your\n``EMAIL_HOST`` setting is set to the proper hostname for your mail server.\nIt's set to ``'localhost'`` by default, which works out of the box for most\nshared-hosting environments. You might also need to set ``EMAIL_HOST_USER``,\n``EMAIL_HOST_PASSWORD``, ``EMAIL_PORT`` or ``EMAIL_USE_TLS``, depending on the\ncomplexity of your arrangement.\n\nAlso, you can set ``EMAIL_SUBJECT_PREFIX`` to control the prefix Django uses\nin front of its error e-mails. It's set to ``'[Django] '`` by default.\n\nSetting Up Broken Link Alerts\n-----------------------------\n\nIf you have the ``CommonMiddleware`` installed (e.g., if your\n``MIDDLEWARE_CLASSES`` setting includes\n``'django.middleware.common.CommonMiddleware'``, which it does by default),\nthen you have the option of receiving an e-mail any time somebody visits a page\non your Django-powered site that raises 404 with a non-empty referrer -- that\nis, every broken link. If you want to activate this feature, set\n``SEND_BROKEN_LINK_EMAILS`` to ``True`` (it's ``False`` by default), and set\nyour ``MANAGERS`` setting to a person or people who will receive these\nbroken-link e-mails. ``MANAGERS`` uses the same syntax as ``ADMINS``. For\nexample::\n\n    MANAGERS = (\n        ('George Harrison', 'gharrison@example.com'),\n        ('Ringo Starr', 'ringo@example.com'),\n    )\n\nNote that error e-mails can get annoying; they're not for everybody.\n\nUsing Different Settings for Production\n=======================================\n\nSo far in this book, we've dealt with only a single settings file: the\n``settings.py`` generated by ``django-admin.py startproject``. But as you get\nready to deploy, you'll likely find yourself needing multiple settings files to\nkeep your development environment isolated from your production environment.\n(For example, you probably won't want to change ``DEBUG`` from ``False`` to\n``True`` whenever you want to test code changes on your local machine.) Django\nmakes this very easy by allowing you to use multiple settings files.\n\nIf you'd like to organize your settings files into \"production\" and\n\"development\" settings, you can accomplish this in one of three ways:\n\n* Set up two full-blown, independent settings files.\n\n* Set up a \"base\" settings file (say, for development) and a second (say,\n  production) settings file that merely imports from the first one and\n  defines whatever overrides it needs to define.\n\n* Use only a single settings file that has Python logic to change the\n  settings based on context.\n\nWe'll take these one at a time.\n\nFirst, the most basic approach is to define two separate settings files. If\nyou're following along, you've already got ``settings.py``. Now, just make a\ncopy of it called ``settings_production.py``. (We made this name up; you can\ncall it whatever you want.) In this new file, change ``DEBUG``, etc.\n\nThe second approach is similar but cuts down on redundancy. Instead of having\ntwo settings files whose contents are mostly similar, you can treat one as the\n\"base\" file and create another file that imports from it. For example::\n\n    # settings.py\n\n    DEBUG = True\n    TEMPLATE_DEBUG = DEBUG\n\n    DATABASE_ENGINE = 'postgresql_psycopg2'\n    DATABASE_NAME = 'devdb'\n    DATABASE_USER = ''\n    DATABASE_PASSWORD = ''\n    DATABASE_PORT = ''\n\n    # ...\n\n    # settings_production.py\n\n    from settings import *\n\n    DEBUG = TEMPLATE_DEBUG = False\n    DATABASE_NAME = 'production'\n    DATABASE_USER = 'app'\n    DATABASE_PASSWORD = 'letmein'\n\nHere, ``settings_production.py`` imports everything from ``settings.py`` and\njust redefines the settings that are particular to production. In this case,\n``DEBUG`` is set to ``False``, but we've also set different database access\nparameters for the production setting. (The latter goes to show that you can\nredefine *any* setting, not just the basic ones like ``DEBUG``.)\n\nFinally, the most concise way of accomplishing two settings environments is to\nuse a single settings file that branches based on the environment. One way to\ndo this is to check the current hostname. For example::\n\n    # settings.py\n\n    import socket\n\n    if socket.gethostname() == 'my-laptop':\n        DEBUG = TEMPLATE_DEBUG = True\n    else:\n        DEBUG = TEMPLATE_DEBUG = False\n\n    # ...\n\nHere, we import the ``socket`` module from Python's standard library and use it\nto check the current system's hostname. We can check the hostname to determine\nwhether the code is being run on the production server.\n\nA core lesson here is that settings files are *just Python code*. They can\nimport from other files, they can execute arbitrary logic, etc. Just make sure\nthat, if you go down this road, the Python code in your settings files is\nbulletproof. If it raises any exceptions, Django will likely crash badly.\n\n.. admonition:: Renaming settings.py\n\n    Feel free to rename your ``settings.py`` to ``settings_dev.py`` or\n    ``settings/dev.py`` or ``foobar.py`` -- Django doesn't care, as long as\n    you tell it what settings file you're using.\n\n    But if you *do* rename the ``settings.py`` file that is generated by\n    ``django-admin.py startproject``, you'll find that ``manage.py`` will give\n    you an error message saying that it can't find the settings. That's because\n    it tries to import a module called ``settings``. You can fix this either by\n    editing ``manage.py`` to change ``settings`` to the name of your module, or\n    by using ``django-admin.py`` instead of ``manage.py``. In the latter case,\n    you'll need to set the ``DJANGO_SETTINGS_MODULE`` environment variable to\n    the Python path to your settings file (e.g., ``'mysite.settings'``).\n\nDJANGO_SETTINGS_MODULE\n======================\n\nWith those code changes out of the way, the next part of this chapter will\nfocus on deployment instructions for specific environments, such as Apache.\nThe instructions are different for each environment, but one thing remains the\nsame: in each case, you will have to tell the Web server your\n``DJANGO_SETTINGS_MODULE``. This is the entry point into your Django\napplication. The ``DJANGO_SETTINGS_MODULE`` points to your settings file, which\npoints to your ``ROOT_URLCONF``, which points to your views, and so on.\n\n``DJANGO_SETTINGS_MODULE`` is the Python path to your settings file. For\nexample, assuming the ``mysite`` directory is on your Python path, the\n``DJANGO_SETTINGS_MODULE`` for our ongoing example is ``'mysite.settings'``.\n\nUsing Django with Apache and mod_python\n=======================================\n\nApache with mod_python historically has been the suggested setup for using\nDjango on a production server.\n\nmod_python (http://www.djangoproject.com/r/mod_python/) is an Apache plug-in\nthat embeds Python within Apache and loads Python code into memory when the\nserver starts. Code stays in memory throughout the life of an Apache process,\nwhich leads to significant performance gains over other server arrangements.\n\nDjango requires Apache 2.x and mod_python 3.x.\n\n.. note::\n\n    Configuring Apache is *well* beyond the scope of this book, so\n    we'll simply mention details as needed. Luckily, many great resources are\n    available if you need to learn more about Apache. A few of them we like\n    are:\n\n    * The free online Apache documentation, available via\n      http://www.djangoproject.com/r/apache/docs/\n\n    * *Pro Apache, Third Edition* (Apress, 2004) by Peter Wainwright,\n      available via http://www.djangoproject.com/r/books/pro-apache/\n\n    * *Apache: The Definitive Guide, Third Edition* (O'Reilly, 2002) by Ben\n      Laurie and Peter Laurie, available via\n      http://www.djangoproject.com/r/books/pro-apache/\n\nBasic Configuration\n-------------------\n\nTo configure Django with mod_python, first make sure you have Apache installed\nwith the mod_python module activated. This usually means having a\n``LoadModule`` directive in your Apache configuration file. It will look something\nlike this::\n\n    LoadModule python_module /usr/lib/apache2/modules/mod_python.so\n\nThen, edit your Apache configuration file and add a ``<Location>`` directive\nthat ties a specific URL path to a specific Django installation. For example::\n\n    <Location \"/\">\n        SetHandler python-program\n        PythonHandler django.core.handlers.modpython\n        SetEnv DJANGO_SETTINGS_MODULE mysite.settings\n        PythonDebug Off\n    </Location>\n\nMake sure to replace ``mysite.settings`` with the appropriate\n``DJANGO_SETTINGS_MODULE`` for your site.\n\nThis tells Apache, \"Use mod_python for any URL at or under '/', using the\nDjango mod_python handler.\" It passes the value of ``DJANGO_SETTINGS_MODULE``\nso mod_python knows which settings to use.\n\nNote that we're using the ``<Location>`` directive, not the ``<Directory>``\ndirective. The latter is used for pointing at places on your filesystem,\nwhereas ``<Location>`` points at places in the URL structure of a Web site.\n``<Directory>`` would be meaningless here.\n\nApache likely runs as a different user than your normal login and may have a\ndifferent path and sys.path.  You may need to tell mod_python how to find your\nproject and Django itself. ::\n\n    PythonPath \"['/path/to/project', '/path/to/django'] + sys.path\"\n\nYou can also add directives such as ``PythonAutoReload Off`` for performance.\nSee the mod_python documentation for a full list of options.\n\nNote that you should set ``PythonDebug Off`` on a production server. If you\nleave ``PythonDebug On``, your users will see ugly (and revealing) Python\ntracebacks if something goes wrong within mod_python.\n\nRestart Apache, and any request to your site (or virtual host if you've put\nthis directive inside a ``<VirtualHost>`` block) will be served by Django.\n\nRunning Multiple Django Installations on the Same Apache Instance\n-----------------------------------------------------------------\n\nIt's entirely possible to run multiple Django installations on the same Apache\ninstance. You might want to do this if you're an independent Web developer with\nmultiple clients but only a single server.\n\nTo accomplish this, just use ``VirtualHost`` like so::\n\n    NameVirtualHost *\n\n    <VirtualHost *>\n        ServerName www.example.com\n        # ...\n        SetEnv DJANGO_SETTINGS_MODULE mysite.settings\n    </VirtualHost>\n\n    <VirtualHost *>\n        ServerName www2.example.com\n        # ...\n        SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings\n    </VirtualHost>\n\nIf you need to put two Django installations within the same ``VirtualHost``,\nyou'll need to take a special precaution to ensure mod_python's code cache\ndoesn't mess things up. Use the ``PythonInterpreter`` directive to give\ndifferent ``<Location>`` directives separate interpreters::\n\n    <VirtualHost *>\n        ServerName www.example.com\n        # ...\n        <Location \"/something\">\n            SetEnv DJANGO_SETTINGS_MODULE mysite.settings\n            PythonInterpreter mysite\n        </Location>\n\n        <Location \"/otherthing\">\n            SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings\n            PythonInterpreter mysite_other\n        </Location>\n    </VirtualHost>\n\nThe values of ``PythonInterpreter`` don't really matter, as long as they're\ndifferent between the two ``Location`` blocks.\n\nRunning a Development Server with mod_python\n--------------------------------------------\n\nBecause mod_python caches loaded Python code, when deploying Django sites on\nmod_python you'll need to restart Apache each time you make changes to your\ncode. This can be a hassle, so here's a quick trick to avoid it: just add\n``MaxRequestsPerChild 1`` to your config file to force Apache to reload\neverything for each request. But don't do that on a production server, or we'll\nrevoke your Django privileges.\n\nIf you're the type of programmer who debugs using scattered ``print``\nstatements (we are), note that ``print`` statements have no effect in\nmod_python; they don't appear in the Apache log, as you might expect. If you\nhave the need to print debugging information in a mod_python setup, you'll\nprobably want to use Python's standard logging package.  More information is\navailable at http://docs.python.org/lib/module-logging.html.\n\nServing Django and Media Files from the Same Apache Instance\n------------------------------------------------------------\n\nDjango should not be used to serve media files itself; leave that job to\nwhichever Web server you choose. We recommend using a separate Web server\n(i.e., one that's not also running Django) for serving media. For more\ninformation, see the \"Scaling\" section.\n\nIf, however, you have no option but to serve media files on the same Apache\n``VirtualHost`` as Django, here's how you can turn off mod_python for a\nparticular part of the site::\n\n    <Location \"/media/\">\n        SetHandler None\n    </Location>\n\nChange ``Location`` to the root URL of your media files.\n\nYou can also use ``<LocationMatch>`` to match a regular expression. For\nexample, this sets up Django at the site root but explicitly disables Django\nfor the ``media`` subdirectory and any URL that ends with ``.jpg``, ``.gif``,\nor ``.png``::\n\n    <Location \"/\">\n        SetHandler python-program\n        PythonHandler django.core.handlers.modpython\n        SetEnv DJANGO_SETTINGS_MODULE mysite.settings\n    </Location>\n\n    <Location \"/media/\">\n        SetHandler None\n    </Location>\n\n    <LocationMatch \"\\.(jpg|gif|png)$\">\n        SetHandler None\n    </LocationMatch>\n\nIn all of these cases, you'll need to set the ``DocumentRoot`` directive so\nApache knows where to find your static files.\n\nError Handling\n--------------\n\nWhen you use Apache/mod_python, errors will be caught by Django -- in other\nwords, they won't propagate to the Apache level and won't appear in the Apache\n``error_log``.\n\nThe exception to this is if something is really messed up in your Django\nsetup. In that case, you'll see an ominous \"Internal Server Error\" page in your\nbrowser and the full Python traceback in your Apache ``error_log`` file. The\n``error_log`` traceback is spread over multiple lines. (Yes, this is ugly and\nrather hard to read, but it's how mod_python does things.)\n\nHandling a Segmentation Fault\n-----------------------------\n\nSometimes, Apache segfaults when you install Django. When this happens, it's\nalmost *always* one of two causes mostly unrelated to Django itself:\n\n* It may be that your Python code is importing the ``pyexpat`` module\n  (used for XML parsing), which may conflict with the version embedded in\n  Apache. For full information, see \"Expat Causing Apache Crash\" at\n  http://www.djangoproject.com/r/articles/expat-apache-crash/.\n\n* It may be because you're running mod_python and mod_php in the same\n  Apache instance, with MySQL as your database backend. In some cases, this\n  causes a known mod_python issue due to version conflicts in PHP and the\n  Python MySQL back-end. There's full information in a mod_python FAQ entry,\n  accessible via http://www.djangoproject.com/r/articles/php-modpython-faq/.\n\nIf you continue to have problems setting up mod_python, a good thing to do is\nget a bare-bones mod_python site working, without the Django framework. This is\nan easy way to isolate mod_python-specific problems. The article \"Getting mod_python\nWorking\" details this procedure:\nhttp://www.djangoproject.com/r/articles/getting-modpython-working/.\n\nThe next step should be to edit your test code and add an import of any\nDjango-specific code you're using -- your views, your models, your URLconf,\nyour RSS configuration, and so forth. Put these imports in your test handler function\nand access your test URL in a browser. If this causes a crash, you've\nconfirmed it's the importing of Django code that causes the problem. Gradually\nreduce the set of imports until it stops crashing, so as to find the specific\nmodule that causes the problem. Drop down further into modules and look into\ntheir imports as necessary.  For more help, system tools like ``ldconfig`` on\nLinux, ``otool`` on Mac OS, and ``ListDLLs`` (from SysInternals) on Windows\ncan help you identify shared dependencies and possible version conflicts.\n\nAn Alternative: mod_wsgi\n------------------------\n\nAs an alternative to mod_python, you might consider using mod_wsgi\n(http://code.google.com/p/modwsgi/), which has been developed more recently\nthan mod_python and is getting some traction in the Django community. A full\noverview is outside the scope of this book, but see the official Django\ndocumentation for more information.\n\nUsing Django with FastCGI\n=========================\n\nAlthough Django under Apache and mod_python is the most robust deployment\nsetup, many people use shared hosting, on which FastCGI is the only available\ndeployment option.\n\nAdditionally, in some situations, FastCGI allows better security and possibly\nbetter performance than mod_python. For small sites, FastCGI can also be more\nlightweight than Apache.\n\nFastCGI Overview\n----------------\n\nFastCGI is an efficient way of letting an external application serve pages to\na Web server. The Web server delegates the incoming Web requests (via a\nsocket) to FastCGI, which executes the code and passes the response back to\nthe Web server, which, in turn, passes it back to the client's Web browser.\n\nLike mod_python, FastCGI allows code to stay in memory, allowing requests to\nbe served with no startup time. Unlike mod_python, a FastCGI process doesn't\nrun inside the Web server process, but in a separate, persistent process.\n\n.. admonition:: Why Run Code in a Separate Process?\n\n    The traditional ``mod_*`` arrangements in Apache embed various scripting\n    languages (most notably PHP, Python/mod_python, and Perl/mod_perl) inside\n    the process space of your Web server. Although this lowers startup time\n    (because code doesn't have to be read off disk for every request), it comes\n    at the cost of memory use.\n\n    Each Apache process gets a copy of the Apache engine, complete with all\n    the features of Apache that Django simply doesn't take advantage of.\n    FastCGI processes, on the other hand, only have the memory overhead of\n    Python and Django.\n\n    Due to the nature of FastCGI, it's also possible to have processes that\n    run under a different user account than the Web server process. That's a\n    nice security benefit on shared systems, because it means you can secure\n    your code from other users.\n\nBefore you can start using FastCGI with Django, you'll need to install ``flup``,\na Python library for dealing with FastCGI. Some users have reported\nstalled pages with older ``flup`` versions, so you may want to use the latest\nSVN version. Get ``flup`` at http://www.djangoproject.com/r/flup/.\n\nRunning Your FastCGI Server\n---------------------------\n\nFastCGI operates on a client/server model, and in most cases you'll be\nstarting the FastCGI server process on your own. Your Web server (be it\nApache, lighttpd, or otherwise) contacts your Django-FastCGI process only when\nthe server needs a dynamic page to be loaded. Because the daemon is already\nrunning with the code in memory, it's able to serve the response very quickly.\n\n.. admonition:: Note\n\n    If you're on a shared hosting system, you'll probably be forced to use Web\n    server-managed FastCGI processes. If you're in this situation, you should\n    read the section titled \"Running Django on a Shared-Hosting Provider with\n    Apache,\" below.\n\nA Web server can connect to a FastCGI server in one of two ways: it can use\neither a Unix domain socket (a *named pipe* on Win32 systems) or a\nTCP socket. What you choose is a manner of preference; a TCP socket is usually\neasier due to permissions issues.\n\nTo start your server, first change into the directory of your project\n(wherever your ``manage.py`` is), and then run ``manage.py`` with the\n``runfcgi`` command::\n\n    ./manage.py runfcgi [options]\n\nIf you specify ``help`` as the only option after ``runfcgi``, a\nlist of all the available options will display.\n\nYou'll need to specify either a ``socket`` or both ``host`` and ``port``.\nThen, when you set up your Web server, you'll just need to point it at the\nsocket or host/port you specified when starting the FastCGI server.\n\nA few examples should help explain this:\n\n* Running a threaded server on a TCP port::\n\n    ./manage.py runfcgi method=threaded host=127.0.0.1 port=3033\n\n* Running a preforked server on a Unix domain socket::\n\n    ./manage.py runfcgi method=prefork socket=/home/user/mysite.sock pidfile=django.pid\n\n* Run without daemonizing (backgrounding) the process (good for\n  debugging)::\n\n    ./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock\n\nStopping the FastCGI Daemon\n```````````````````````````\n\nIf you have the process running in the foreground, it's easy enough to stop\nit: simply press Ctrl+C to stop and quit the FastCGI server. However,\nwhen you're dealing with background processes, you'll need to resort to the\nUnix ``kill`` command.\n\nIf you specify the ``pidfile`` option to your ``manage.py runfcgi``, you can\nkill the running FastCGI daemon like this::\n\n    kill `cat $PIDFILE`\n\nwhere ``$PIDFILE`` is the ``pidfile`` you specified.\n\nTo easily restart your FastCGI daemon on Unix, you can use this small shell\nscript::\n\n    #!/bin/bash\n\n    # Replace these three settings.\n    PROJDIR=\"/home/user/myproject\"\n    PIDFILE=\"$PROJDIR/mysite.pid\"\n    SOCKET=\"$PROJDIR/mysite.sock\"\n\n    cd $PROJDIR\n    if [ -f $PIDFILE ]; then\n        kill `cat -- $PIDFILE`\n        rm -f -- $PIDFILE\n    fi\n\n    exec /usr/bin/env - \\\n      PYTHONPATH=\"../python:..\" \\\n      ./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE\n\nUsing Django with Apache and FastCGI\n------------------------------------\n\nTo use Django with Apache and FastCGI, you'll need Apache installed and\nconfigured, with mod_fastcgi installed and enabled. Consult the Apache and\nmod_fastcgi documentation for instructions:\nhttp://www.djangoproject.com/r/mod_fastcgi/.\n\nOnce you've completed the setup, point Apache at your Django FastCGI instance by\nediting the ``httpd.conf`` (Apache configuration) file. You'll need to do two\nthings:\n\n* Use the ``FastCGIExternalServer`` directive to specify the location of\n  your FastCGI server.\n\n* Use ``mod_rewrite`` to point URLs at FastCGI as appropriate.\n\nSpecifying the Location of the FastCGI Server\n`````````````````````````````````````````````\n\nThe ``FastCGIExternalServer`` directive tells Apache how to find your FastCGI\nserver. As the FastCGIExternalServer docs\n(http://www.djangoproject.com/r/mod_fastcgi/FastCGIExternalServer/) explain, you\ncan specify either a ``socket`` or a ``host``. Here are examples of both::\n\n    # Connect to FastCGI via a socket/named pipe:\n    FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock\n\n    # Connect to FastCGI via a TCP host/port:\n    FastCGIExternalServer /home/user/public_html/mysite.fcgi -host 127.0.0.1:3033\n\nIn either case, the the directory /home/user/public_html/ should exist,\nthough the file ``/home/user/public_html/mysite.fcgi`` doesn't\nactually have to exist. It's just a URL used by the Web server internally -- a\nhook for signifying which requests at a URL should be handled by FastCGI.\n(More on this in the next section.)\n\nUsing mod_rewrite to Point URLs at FastCGI\n``````````````````````````````````````````\n\nThe second step is telling Apache to use FastCGI for URLs that match a certain\npattern. To do this, use the mod_rewrite module and rewrite URLs to\n``mysite.fcgi`` (or whatever you specified in the ``FastCGIExternalServer``\ndirective, as explained in the previous section).\n\nIn this example, we tell Apache to use FastCGI to handle any request that\ndoesn't represent a file on the filesystem and doesn't start with ``/media/``.\nThis is probably the most common case, if you're using Django's admin site::\n\n    <VirtualHost 12.34.56.78>\n      ServerName example.com\n      DocumentRoot /home/user/public_html\n      Alias /media /home/user/python/django/contrib/admin/media\n      RewriteEngine On\n      RewriteRule ^/(media.*)$ /$1 [QSA,L]\n      RewriteCond %{REQUEST_FILENAME} !-f\n      RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]\n    </VirtualHost>\n\nFastCGI and lighttpd\n--------------------\n\nlighttpd (http://www.djangoproject.com/r/lighttpd/) is a lightweight Web server\ncommonly used for serving static files. It supports FastCGI natively and thus\nis also an ideal choice for serving both static and dynamic pages, if your site\ndoesn't have any Apache-specific needs.\n\nMake sure ``mod_fastcgi`` is in your modules list, somewhere after\n``mod_rewrite`` and ``mod_access``, but not after ``mod_accesslog``. You'll\nprobably want ``mod_alias`` as well, for serving admin media.\n\nAdd the following to your lighttpd config file::\n\n    server.document-root = \"/home/user/public_html\"\n    fastcgi.server = (\n        \"/mysite.fcgi\" => (\n            \"main\" => (\n                # Use host / port instead of socket for TCP fastcgi\n                # \"host\" => \"127.0.0.1\",\n                # \"port\" => 3033,\n                \"socket\" => \"/home/user/mysite.sock\",\n                \"check-local\" => \"disable\",\n            )\n        ),\n    )\n    alias.url = (\n        \"/media/\" => \"/home/user/django/contrib/admin/media/\",\n    )\n\n    url.rewrite-once = (\n        \"^(/media.*)$\" => \"$1\",\n        \"^/favicon\\.ico$\" => \"/media/favicon.ico\",\n        \"^(/.*)$\" => \"/mysite.fcgi$1\",\n    )\n\nRunning Multiple Django Sites on One lighttpd Instance\n``````````````````````````````````````````````````````\n\nlighttpd lets you use \"conditional configuration\" to allow configuration to be\ncustomized per host. To specify multiple FastCGI sites, just add a conditional\nblock around your FastCGI config for each site::\n\n    # If the hostname is 'www.example1.com'...\n    $HTTP[\"host\"] == \"www.example1.com\" {\n        server.document-root = \"/foo/site1\"\n        fastcgi.server = (\n           ...\n        )\n        ...\n    }\n\n    # If the hostname is 'www.example2.com'...\n    $HTTP[\"host\"] == \"www.example2.com\" {\n        server.document-root = \"/foo/site2\"\n        fastcgi.server = (\n           ...\n        )\n        ...\n    }\n\nYou can also run multiple Django installations on the same site simply by\nspecifying multiple entries in the ``fastcgi.server`` directive. Add one\nFastCGI host for each.\n\nRunning Django on a Shared-Hosting Provider with Apache\n-------------------------------------------------------\n\nMany shared-hosting providers don't allow you to run your own server daemons\nor edit the ``httpd.conf`` file. In these cases, it's still possible to run\nDjango using Web server-spawned processes.\n\n.. admonition:: Note\n\n    If you're using Web server-spawned processes, as explained in this\n    section, there's no need for you to start the FastCGI server on your own.\n    Apache will spawn a number of processes, scaling as it needs to.\n\nIn your Web root directory, add this to a file named ``.htaccess`` ::\n\n    AddHandler fastcgi-script .fcgi\n    RewriteEngine On\n    RewriteCond %{REQUEST_FILENAME} !-f\n    RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]\n\nThen, create a small script that tells Apache how to spawn your FastCGI\nprogram. Create a file, ``mysite.fcgi``, and place it in your Web directory, and\nbe sure to make it executable ::\n\n    #!/usr/bin/python\n    import sys, os\n\n    # Add a custom Python path.\n    sys.path.insert(0, \"/home/user/python\")\n\n    # Switch to the directory of your project. (Optional.)\n    # os.chdir(\"/home/user/myproject\")\n\n    # Set the DJANGO_SETTINGS_MODULE environment variable.\n    os.environ['DJANGO_SETTINGS_MODULE'] = \"myproject.settings\"\n\n    from django.core.servers.fastcgi import runfastcgi\n    runfastcgi(method=\"threaded\", daemonize=\"false\")\n\nRestarting the Spawned Server\n`````````````````````````````\n\nIf you change any Python code on your site, you'll need to tell FastCGI the\ncode has changed. But there's no need to restart Apache in this case. Rather,\njust reupload ``mysite.fcgi`` -- or edit the file -- so that the timestamp\non the file changes. When Apache sees the file has been updated, it will\nrestart your Django application for you.\n\nIf you have access to a command shell on a Unix system, you can accomplish\nthis easily by using the ``touch`` command::\n\n    touch mysite.fcgi\n\nScaling\n=======\n\nNow that you know how to get Django running on a single server, let's look at\nhow you can scale out a Django installation. This section walks through how\na site might scale from a single server to a large-scale cluster that could\nserve millions of hits an hour.\n\nIt's important to note, however, that nearly every large site is large in\ndifferent ways, so scaling is anything but a one-size-fits-all operation. The\nfollowing coverage should suffice to show the general principle, and whenever\npossible we'll try to point out where different choices could be made.\n\nFirst off, we'll make a pretty big assumption and exclusively talk about\nscaling under Apache and mod_python. Though we know of a number of successful\nmedium- to large-scale FastCGI deployments, we're much more familiar with\nApache.\n\nRunning on a Single Server\n--------------------------\n\nMost sites start out running on a single server, with an architecture that\nlooks something like Figure 12-1.\n\n.. figure:: graphics/chapter12/scaling-1.png\n\n   Figure 12-1: a single server Django setup.\n\nThis works just fine for small- to medium-sized sites, and it's relatively cheap -- you\ncan put together a single-server site designed for Django for well under $3,000.\n\nHowever, as traffic increases you'll quickly run into *resource contention*\nbetween the different pieces of software. Database servers and Web servers\n*love* to have the entire server to themselves, so when run on the same server\nthey often end up \"fighting\" over the same resources (RAM, CPU) that they'd\nprefer to monopolize.\n\nThis is solved easily by moving the database server to a second machine,\nas explained in the following section.\n\nSeparating Out the Database Server\n----------------------------------\n\nAs far as Django is concerned, the process of separating out the database server\nis extremely easy: you'll simply need to change the ``DATABASE_HOST``\nsetting to the IP or DNS name of your database server. It's probably a good idea\nto use the IP if at all possible, as relying on DNS for the connection between\nyour Web server and database server isn't recommended.\n\nWith a separate database server, our architecture now looks like Figure 12-2.\n\n.. figure:: graphics/chapter12/scaling-2.png\n\n   Figure 12-2: Moving the database onto a dedicated server.\n\nHere we're starting to move into what's usually called *n-tier*\narchitecture. Don't be scared by the buzzword -- it just refers to the fact that\ndifferent \"tiers\" of the Web stack get separated out onto different physical\nmachines.\n\nAt this point, if you anticipate ever needing to grow beyond a single database\nserver, it's probably a good idea to start thinking about connection pooling\nand/or database replication. Unfortunately, there's not nearly enough space to do\nthose topics justice in this book, so you'll need to consult your database's\ndocumentation and/or community for more information.\n\nRunning a Separate Media Server\n-------------------------------\n\nWe still have a big problem left over from the single-server setup:\nthe serving of media from the same box that handles dynamic content.\n\nThose two activities perform best under different circumstances, and by smashing\nthem together on the same box you end up with neither performing particularly\nwell. So the next step is to separate out the media -- that is, anything *not*\ngenerated by a Django view -- onto a dedicated server (see Figure 12-3).\n\n.. figure:: graphics/chapter12/scaling-3.png\n\n   Figure 12-3: Separating out the media server.\n\nIdeally, this media server should run a stripped-down Web server optimized for\nstatic media delivery. lighttpd and tux (http://www.djangoproject.com/r/tux/)\nare both excellent choices here, but a heavily stripped down Apache could work,\ntoo.\n\nFor sites heavy in static content (photos, videos, etc.), moving to a\nseparate media server is doubly important and should likely be the *first*\nstep in scaling up.\n\nThis step can be slightly tricky, however. If your application involves file\nuploads, Django needs to be able to write uploaded media to the media server.\nIf media lives on another server, you'll need to arrange a way for that write\nto happen across the network.\n\nImplementing Load Balancing and Redundancy\n------------------------------------------\n\nAt this point, we've broken things down as much as possible. This\nthree-server setup should handle a very large amount of traffic -- we served\naround 10 million hits a day from an architecture of this sort -- so if you\ngrow further, you'll need to start adding redundancy.\n\nThis is a good thing, actually. One glance at Figure 12-3 shows you that\nif even a single one of your three servers fails, you'll bring down your\nentire site. So as you add redundant servers, not only do you increase capacity,\nbut you also increase reliability.\n\nFor the sake of this example, let's assume that the Web server hits capacity\nfirst. It's relatively easy to get multiple copies of a Django site running on\ndifferent hardware -- just copy all the code onto multiple machines, and start\nApache on both of them.\n\nHowever, you'll need another piece of software to distribute traffic over your\nmultiple servers: a *load balancer*. You can buy expensive and proprietary\nhardware load balancers, but there are a few high-quality open source software\nload balancers out there.\n\nApache's ``mod_proxy`` is one option, but we've found Perlbal\n(http://www.djangoproject.com/r/perlbal/) to be fantastic. It's a load\nbalancer and reverse proxy written by the same folks who wrote ``memcached``\n(see `Chapter 15`_).\n\n.. note::\n\n    If you're using FastCGI, you can accomplish this same distribution/load\n    balancing step by separating your front-end Web servers and back-end\n    FastCGI processes onto different machines. The front-end server\n    essentially becomes the load balancer, and the back-end FastCGI processes\n    replace the Apache/mod_python/Django servers.\n\nWith the Web servers now clustered, our evolving architecture starts to look\nmore complex, as shown in Figure 12-4.\n\n.. figure:: graphics/chapter12/scaling-4.png\n\n   Figure 12-4: A load-balanced, redundant server setup.\n\nNotice that in the diagram the Web servers are referred to as a \"cluster\" to\nindicate that the number of servers is basically variable. Once you have a\nload balancer out front, you can easily add and remove back-end Web servers\nwithout a second of downtime.\n\nGoing Big\n---------\n\nAt this point, the next few steps are pretty much derivatives of the last one:\n\n* As you need more database performance, you might want to add replicated\n  database servers. MySQL includes built-in replication; PostgreSQL\n  users should look into Slony (http://www.djangoproject.com/r/slony/)\n  and pgpool (http://www.djangoproject.com/r/pgpool/) for replication and\n  connection pooling, respectively.\n\n* If the single load balancer isn't enough, you can add more load\n  balancer machines out front and distribute among them using\n  round-robin DNS.\n\n* If a single media server doesn't suffice, you can add more media\n  servers and distribute the load with your load-balancing cluster.\n\n* If you need more cache storage, you can add dedicated cache servers.\n\n* At any stage, if a cluster isn't performing well, you can add more\n  servers to the cluster.\n\nAfter a few of these iterations, a large-scale architecture might look like Figure 12-5.\n\n.. figure:: graphics/chapter12/scaling-5.png\n\n   Figure 12-5. An example large-scale Django setup.\n\nThough we've shown only two or three servers at each level, there's no\nfundamental limit to how many you can add.\n\nPerformance Tuning\n==================\n\nIf you have huge amount of money, you can just keep throwing hardware at\nscaling problems. For the rest of us, though, performance tuning is a must.\n\n.. note::\n\n    Incidentally, if anyone with monstrous gobs of cash is actually reading\n    this book, please consider a substantial donation to the Django Foundation.\n    We accept uncut diamonds and gold ingots, too.\n\nUnfortunately, performance tuning is much more of an art than a science, and it\nis even more difficult to write about than scaling. If you're serious about\ndeploying a large-scale Django application, you should spend a great deal of\ntime learning how to tune each piece of your stack.\n\nThe following sections, though, present a few Django-specific tuning tips we've\ndiscovered over the years.\n\nThere's No Such Thing As Too Much RAM\n-------------------------------------\n\nEven the really expensive RAM is relatively affordable these days. Buy as much\nRAM as you can possibly afford, and then buy a little bit more.\n\nFaster processors won't improve performance all that much; most Web\nservers spend up to 90% of their time waiting on disk I/O. As soon as you start\nswapping, performance will just die. Faster disks might help slightly, but\nthey're much more expensive than RAM, such that it doesn't really matter.\n\nIf you have multiple servers, the first place to put your RAM is in the\ndatabase server. If you can afford it, get enough RAM to get fit your entire\ndatabase into memory. This shouldn't be too hard; we've developed a site\nwith more than half a million newspaper articles, and it took under 2GB of\nspace.\n\nNext, max out the RAM on your Web server. The ideal situation is one where\nneither server swaps -- ever. If you get to that point, you should be able to\nwithstand most normal traffic.\n\nTurn Off Keep-Alive\n-------------------\n\n``Keep-Alive`` is a feature of HTTP that allows multiple HTTP requests to be\nserved over a single TCP connection, avoiding the TCP setup/teardown overhead.\n\nThis looks good at first glance, but it can kill the performance of a Django\nsite. If you're properly serving media from a separate server, each user\nbrowsing your site will only request a page from your Django server every ten\nseconds or so. This leaves HTTP servers waiting around for the next\nkeep-alive request, and an idle HTTP server just consumes RAM that an active one\nshould be using.\n\nUse memcached\n-------------\n\nAlthough Django supports a number of different cache back-ends, none of them\neven come *close* to being as fast as memcached. If you have a high-traffic\nsite, don't even bother with the other backends -- go straight to memcached.\n\nUse memcached Often\n-------------------\n\nOf course, selecting memcached does you no good if you don't actually use it.\n`Chapter 15`_ is your best friend here: learn how to use Django's cache\nframework, and use it everywhere possible. Aggressive, preemptive caching is\nusually the only thing that will keep a site up under major traffic.\n\n.. _Chapter 15: ../chapter15/\n\nJoin the Conversation\n---------------------\n\nEach piece of the Django stack -- from Linux to Apache to PostgreSQL or MySQL\n-- has an awesome community behind it. If you really want to get that last 1%\nout of your servers, join the open source communities behind your software and\nask for help. Most free-software community members will be happy to help.\n\nAnd also be sure to join the Django community. Your humble authors are only two\nmembers of an incredibly active, growing group of Django developers. Our\ncommunity has a huge amount of collective experience to offer.\n\nWhat's Next?\n============\n\nThe remaining chapters focus on other Django features that you may or may not\nneed, depending on your application. Feel free to read them in any order you\nchoose.\n"
  },
  {
    "path": "Python/DjangoBook/chapter13.rst",
    "content": "=======================================\nChapter 13: Generating Non-HTML Content\n=======================================\n\nUsually when we talk about developing Web sites, we're talking about producing\nHTML. Of course, there's a lot more to the Web than HTML; we use the Web\nto distribute data in all sorts of formats: RSS, PDFs, images, and so forth.\n\nSo far, we've focused on the common case of HTML production, but in this chapter\nwe'll take a detour and look at using Django to produce other types of content.\n\nDjango has convenient built-in tools that you can use to produce some common\nnon-HTML content:\n\n* RSS/Atom syndication feeds\n\n* Sitemaps (an XML format originally developed by Google that gives hints to\n  search engines)\n\nWe'll examine each of those tools a little later, but first we'll cover the\nbasic principles.\n\nThe basics: views and MIME-types\n================================\n\nRecall from Chapter 3 that a view function is simply a Python function that\ntakes a Web request and returns a Web response. This response can be the HTML\ncontents of a Web page, or a redirect, or a 404 error, or an XML document,\nor an image...or anything, really.\n\nMore formally, a Django view function *must*\n\n* Accept an ``HttpRequest`` instance as its first argument\n\n* Return an ``HttpResponse`` instance\n\nThe key to returning non-HTML content from a view lies in the ``HttpResponse``\nclass, specifically the ``mimetype`` argument. By tweaking the MIME type, we\ncan indicate to the browser that we've returned a response of a different\nformat.\n\nFor example, let's look at a view that returns a PNG image. To\nkeep things simple, we'll just read the file off the disk::\n\n    from django.http import HttpResponse\n\n    def my_image(request):\n        image_data = open(\"/path/to/my/image.png\", \"rb\").read()\n        return HttpResponse(image_data, mimetype=\"image/png\")\n\n.. SL Tested ok\n\nThat's it! If you replace the image path in the ``open()`` call with a path to\na real image, you can use this very simple view to serve an image, and the\nbrowser will display it correctly.\n\nThe other important thing to keep in mind is that ``HttpResponse`` objects\nimplement Python's standard \"file-like object\" API. This means that you can use\nan ``HttpResponse`` instance in any place Python (or a third-party library)\nexpects a file.\n\nFor an example of how that works, let's take a look at producing CSV with\nDjango.\n\nProducing CSV\n=============\n\nCSV is a simple data format usually used by spreadsheet software. It's basically\na series of table rows, with each cell in the row separated by a comma (CSV\nstands for *comma-separated values*). For example, here's some data on \"unruly\"\nairline passengers in CSV format::\n\n    Year,Unruly Airline Passengers\n    1995,146\n    1996,184\n    1997,235\n    1998,200\n    1999,226\n    2000,251\n    2001,299\n    2002,273\n    2003,281\n    2004,304\n    2005,203\n    2006,134\n    2007,147\n\n.. note::\n\n    The preceding listing contains real numbers! They come from the U.S.\n    Federal Aviation Administration.\n\nThough CSV looks simple, its formatting details haven't been universally agreed\nupon. Different pieces of software produce and consume different variants of\nCSV, making it a bit tricky to use. Luckily, Python comes with a standard CSV\nlibrary, ``csv``, that is pretty much bulletproof.\n\nBecause the ``csv`` module operates on file-like objects, it's a snap to use\nan ``HttpResponse`` instead::\n\n    import csv\n    from django.http import HttpResponse\n\n    # Number of unruly passengers each year 1995 - 2005. In a real application\n    # this would likely come from a database or some other back-end data store.\n    UNRULY_PASSENGERS = [146,184,235,200,226,251,299,273,281,304,203]\n\n    def unruly_passengers_csv(request):\n        # Create the HttpResponse object with the appropriate CSV header.\n        response = HttpResponse(mimetype='text/csv')\n        response['Content-Disposition'] = 'attachment; filename=unruly.csv'\n\n        # Create the CSV writer using the HttpResponse as the \"file.\"\n        writer = csv.writer(response)\n        writer.writerow(['Year', 'Unruly Airline Passengers'])\n        for (year, num) in zip(range(1995, 2006), UNRULY_PASSENGERS):\n            writer.writerow([year, num])\n\n        return response\n\n.. SL Tested ok\n\nThe code and comments should be pretty clear, but a few things deserve special\nmention:\n\n* The response is given the ``text/csv`` MIME type (instead of the default\n  ``text/html``). This tells browsers that the document is a CSV file.\n\n* The response gets an additional ``Content-Disposition`` header, which\n  contains the name of the CSV file. This header (well, the \"attachment\"\n  part) will instruct the browser to prompt for a location to save the\n  file instead of just displaying it. This file name is arbitrary; call\n  it whatever you want. It will be used by browsers in the \"Save As\"\n  dialog.\n\n  To assign a header on an ``HttpResponse``, just treat the\n  ``HttpResponse`` as a dictionary and set a key/value.\n\n* Hooking into the CSV-generation API is easy: just pass ``response`` as\n  the first argument to ``csv.writer``. The ``csv.writer`` function\n  expects a file-like object, and ``HttpResponse`` objects fit the bill.\n\n* For each row in your CSV file, call ``writer.writerow``, passing it an\n  iterable object such as a list or tuple.\n\n* The CSV module takes care of quoting for you, so you don't have to worry\n  about escaping strings with quotes or commas in them. Just pass\n  information to ``writerow()``, and it will do the right thing.\n\nThis is the general pattern you'll use any time you need to return non-HTML\ncontent: create an ``HttpResponse`` response object (with a special MIME type),\npass it to something expecting a file, and then return the response.\n\nLet's look at a few more examples.\n\nGenerating PDFs\n===============\n\nPortable Document Format (PDF) is a format developed by Adobe that's used to\nrepresent printable documents, complete with pixel-perfect formatting,\nembedded fonts, and 2D vector graphics. You can think of a PDF document as the\ndigital equivalent of a printed document; indeed, PDFs are often used in\ndistributing documents for the purpose of printing them.\n\nYou can easily generate PDFs with Python and Django thanks to the excellent\nopen source ReportLab library (http://www.reportlab.org/rl_toolkit.html).\nThe advantage of generating PDF files dynamically is that you can create\ncustomized PDFs for different purposes -- say, for different users or\ndifferent pieces of content.\n\nFor example, your humble authors used Django and ReportLab at KUSports.com to\ngenerate customized, printer-ready NCAA tournament brackets.\n\nInstalling ReportLab\n--------------------\n\nBefore you do any PDF generation, however, you'll need to install ReportLab.\nIt's usually simple: just download and install the library from\nhttp://www.reportlab.org/downloads.html.\n\n.. note::\n\n    If you're using a modern Linux distribution, you might want to check your\n    package management utility before installing ReportLab. Most\n    package repositories have added ReportLab.\n\n    For example, if you're using Ubuntu, a simple\n    ``apt-get install python-reportlab`` will do the trick nicely.\n\nThe user guide (naturally available only as a PDF file) at\nhttp://www.reportlab.org/rsrc/userguide.pdf has additional installation\ninstructions.\n\nTest your installation by importing it in the Python interactive interpreter::\n\n    >>> import reportlab\n\nIf that command doesn't raise any errors, the installation worked.\n\nWriting Your View\n-----------------\n\nLike CSV, generating PDFs dynamically with Django is easy because the ReportLab\nAPI acts on file-like objects.\n\nHere's a \"Hello World\" example::\n\n    from reportlab.pdfgen import canvas\n    from django.http import HttpResponse\n\n    def hello_pdf(request):\n        # Create the HttpResponse object with the appropriate PDF headers.\n        response = HttpResponse(mimetype='application/pdf')\n        response['Content-Disposition'] = 'attachment; filename=hello.pdf'\n\n        # Create the PDF object, using the response object as its \"file.\"\n        p = canvas.Canvas(response)\n\n        # Draw things on the PDF. Here's where the PDF generation happens.\n        # See the ReportLab documentation for the full list of functionality.\n        p.drawString(100, 100, \"Hello world.\")\n\n        # Close the PDF object cleanly, and we're done.\n        p.showPage()\n        p.save()\n        return response\n\n.. SL Tested ok\n\nA few notes are in order:\n\n* Here we use the ``application/pdf`` MIME type. This tells browsers that\n  the document is a PDF file, rather than an HTML file. If you leave off\n  this information, browsers will probably interpret the response as HTML,\n  which will result in scary gobbledygook in the browser window.\n\n* Hooking into the ReportLab API is easy: just pass ``response`` as the\n  first argument to ``canvas.Canvas``. The ``Canvas`` class expects a\n  file-like object, and ``HttpResponse`` objects fit the bill.\n\n* All subsequent PDF-generation methods are called on the PDF\n  object (in this case, ``p``), not on ``response``.\n\n* Finally, it's important to call ``showPage()`` and ``save()`` on the PDF\n  file -- or else, you'll end up with a corrupted PDF file.\n\nComplex PDFs\n------------\n\nIf you're creating a complex PDF document (or any large data blob), consider\nusing the ``cStringIO`` library as a temporary holding place for your PDF\nfile. The ``cStringIO`` library provides a file-like object interface that is\nwritten in C for maximum efficiency.\n\nHere's the previous \"Hello World\" example rewritten to use ``cStringIO``::\n\n    from cStringIO import StringIO\n    from reportlab.pdfgen import canvas\n    from django.http import HttpResponse\n\n    def hello_pdf(request):\n        # Create the HttpResponse object with the appropriate PDF headers.\n        response = HttpResponse(mimetype='application/pdf')\n        response['Content-Disposition'] = 'attachment; filename=hello.pdf'\n\n        temp = StringIO()\n\n        # Create the PDF object, using the StringIO object as its \"file.\"\n        p = canvas.Canvas(temp)\n\n        # Draw things on the PDF. Here's where the PDF generation happens.\n        # See the ReportLab documentation for the full list of functionality.\n        p.drawString(100, 100, \"Hello world.\")\n\n        # Close the PDF object cleanly.\n        p.showPage()\n        p.save()\n\n        # Get the value of the StringIO buffer and write it to the response.\n        response.write(temp.getvalue())\n        return response\n\n.. SL Tested ok\n\nOther Possibilities\n===================\n\nThere's a whole host of other types of content you can generate in Python.\nHere are a few more ideas and some pointers to libraries you could use to\nimplement them:\n\n* *ZIP files*: Python's standard library ships with the\n  ``zipfile`` module, which can both read and write compressed ZIP files.\n  You could use it to provide on-demand archives of a bunch of files, or\n  perhaps compress large documents when requested. You could similarly\n  produce TAR files using the standard library's ``tarfile`` module.\n\n* *Dynamic images*: The Python Imaging Library\n  (PIL; http://www.pythonware.com/products/pil/) is a fantastic toolkit for\n  producing images (PNG, JPEG, GIF, and a whole lot more). You could use\n  it to automatically scale down images into thumbnails, composite\n  multiple images into a single frame, or even do Web-based image\n  processing.\n\n* *Plots and charts*: There are a number of powerful Python plotting and\n  charting libraries you could use to produce on-demand maps, charts,\n  plots, and graphs. We can't possibly list them all, so here are\n  a couple of the highlights:\n\n* ``matplotlib`` (http://matplotlib.sourceforge.net/) can be\n  used to produce the type of high-quality plots usually generated\n  with MatLab or Mathematica.\n\n* ``pygraphviz`` (http://networkx.lanl.gov/pygraphviz/), an\n  interface to the Graphviz graph layout toolkit\n  (http://graphviz.org/), can be used for generating structured diagrams of\n  graphs and networks.\n\nIn general, any Python library capable of writing to a file can be hooked into\nDjango. The possibilities are immense.\n\nNow that we've looked at the basics of generating non-HTML content, let's step\nup a level of abstraction. Django ships with some pretty nifty built-in tools\nfor generating some common types of non-HTML content.\n\nThe Syndication Feed Framework\n==============================\n\nDjango comes with a high-level syndication-feed-generating framework that\nmakes creating RSS and Atom feeds easy.\n\n.. admonition:: What's RSS? What's Atom?\n\n    RSS and Atom are both XML-based formats you can use to provide\n    automatically updating \"feeds\" of your site's content. Read more about RSS\n    at http://www.whatisrss.com/, and get information on Atom at\n    http://www.atomenabled.org/.\n\nTo create any syndication feed, all you have to do is write a short Python\nclass. You can create as many feeds as you want.\n\nThe high-level feed-generating framework is a view that's hooked to ``/feeds/``\nby convention. Django uses the remainder of the URL (everything after\n``/feeds/``) to determine which feed to return.\n\nTo create a feed, you'll write a ``Feed`` class and point to it in your\nURLconf.\n\nInitialization\n--------------\n\nTo activate syndication feeds on your Django site, add this URLconf::\n\n    (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',\n        {'feed_dict': feeds}\n    ),\n\nThis line tells Django to use the RSS framework to handle all URLs starting with\n``\"feeds/\"``. (You can change that ``\"feeds/\"`` prefix to fit your own needs.)\n\nThis URLconf line has an extra argument: ``{'feed_dict': feeds}``. Use this\nextra argument to pass the syndication framework the feeds that should be\npublished under that URL.\n\nSpecifically, ``feed_dict`` should be a dictionary that maps a feed's slug\n(short URL label) to its ``Feed`` class. You can define the ``feed_dict``\nin the URLconf itself. Here's a full example URLconf::\n\n    from django.conf.urls.defaults import *\n    from mysite.feeds import LatestEntries, LatestEntriesByCategory\n\n    feeds = {\n        'latest': LatestEntries,\n        'categories': LatestEntriesByCategory,\n    }\n\n    urlpatterns = patterns('',\n        # ...\n        (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',\n            {'feed_dict': feeds}),\n        # ...\n    )\n\nThe preceding example registers two feeds:\n\n* The feed represented by ``LatestEntries`` will live at\n  ``feeds/latest/``.\n\n* The feed represented by ``LatestEntriesByCategory`` will live at\n  ``feeds/categories/``.\n\nOnce that's set up, you'll need to define the ``Feed`` classes themselves.\n\nA ``Feed`` class is a simple Python class that represents a syndication feed.\nA feed can be simple (e.g., a \"site news\" feed, or a basic feed displaying the\nlatest entries of a blog) or more complex (e.g., a feed displaying all the\nblog entries in a particular category, where the category is variable).\n\n``Feed`` classes must subclass ``django.contrib.syndication.feeds.Feed``. They\ncan live anywhere in your code tree.\n\nA Simple Feed\n-------------\n\nThis simple example describes a feed of the latest five blog entries for a\ngiven blog::\n\n    from django.contrib.syndication.feeds import Feed\n    from mysite.blog.models import Entry\n\n    class LatestEntries(Feed):\n        title = \"My Blog\"\n        link = \"/archive/\"\n        description = \"The latest news about stuff.\"\n\n        def items(self):\n            return Entry.objects.order_by('-pub_date')[:5]\n\nThe important things to notice here are as follows:\n\n* The class subclasses ``django.contrib.syndication.feeds.Feed``.\n\n* ``title``, ``link``, and ``description`` correspond to the standard RSS\n  ``<title>``, ``<link>``, and ``<description>`` elements, respectively.\n\n* ``items()`` is simply a method that returns a list of objects that\n  should be included in the feed as ``<item>`` elements. Although this\n  example returns ``Entry`` objects using Django's database API,\n  ``items()`` doesn't have to return model instances.\n\nThere's just one more step. In an RSS feed, each ``<item>`` has a ``<title>``,\n``<link>``, and ``<description>``. We need to tell the framework what data to\nput into those elements.\n\n* To specify the contents of ``<title>`` and ``<description>``, create\n  Django templates called ``feeds/latest_title.html`` and\n  ``feeds/latest_description.html``, where ``latest`` is the ``slug``\n  specified in the URLconf for the given feed. Note that the ``.html``\n  extension is required.\n\n  The RSS system renders that template for each item, passing it two\n  template context variables:\n\n  * ``obj``: The current object (one of whichever objects you\n    returned in ``items()``).\n\n  * ``site``: A ``django.models.core.sites.Site`` object representing the\n    current site. This is useful for ``{{ site.domain }}`` or ``{{\n    site.name }}``.\n\n  If you don't create a template for either the title or description, the\n  framework will use the template ``\"{{ obj }}\"`` by default -- that is,\n  the normal string representation of the object. (For model objects, this\n  will be the ``__unicode__()`` method.\n\n  You can also change the names of these two templates by specifying\n  ``title_template`` and ``description_template`` as attributes of your\n  ``Feed`` class.\n\n* To specify the contents of ``<link>``, you have two options. For each\n  item in ``items()``, Django first tries executing a\n  ``get_absolute_url()`` method on that object. If that method doesn't\n  exist, it tries calling a method ``item_link()`` in the ``Feed`` class,\n  passing it a single parameter, ``item``, which is the object itself.\n\n  Both ``get_absolute_url()`` and ``item_link()`` should return the item's\n  URL as a normal Python string.\n\n* For the previous ``LatestEntries`` example, we could have very simple feed\n  templates. ``latest_title.html`` contains::\n\n        {{ obj.title }}\n\n  and ``latest_description.html`` contains::\n\n        {{ obj.description }}\n\n  It's almost *too* easy...\n\n.. SL Tested ok\n\nA More Complex Feed\n-------------------\n\nThe framework also supports more complex feeds, via parameters.\n\nFor example, say your blog offers an RSS feed for every distinct \"tag\" you've\nused to categorize your entries. It would be silly to create a separate\n``Feed`` class for each tag; that would violate the Don't Repeat Yourself\n(DRY) principle and would couple data to programming logic.\n\nInstead, the syndication framework lets you make generic\nfeeds that return items based on information in the feed's URL.\n\nYour tag-specific feeds could use URLs like this:\n\n* ``http://example.com/feeds/tags/python/``:\n  Returns recent entries tagged with \"python\"\n\n* ``http://example.com/feeds/tags/cats/``:\n  Returns recent entries tagged with \"cats\"\n\nThe slug here is ``\"tags\"``. The syndication framework sees the extra URL\nbits after the slug -- ``'python'`` and ``'cats'`` -- and gives you a hook\nto tell it what those URL bits mean and how they should influence which items\nget published in the feed.\n\nAn example makes this clear. Here's the code for these tag-specific feeds::\n\n    from django.core.exceptions import ObjectDoesNotExist\n    from mysite.blog.models import Entry, Tag\n\n    class TagFeed(Feed):\n        def get_object(self, bits):\n            # In case of \"/feeds/tags/cats/dogs/mice/\", or other such\n            # clutter, check that bits has only one member.\n            if len(bits) != 1:\n                raise ObjectDoesNotExist\n            return Tag.objects.get(tag=bits[0])\n\n        def title(self, obj):\n            return \"My Blog: Entries tagged with %s\" % obj.tag\n\n        def link(self, obj):\n            return obj.get_absolute_url()\n\n        def description(self, obj):\n            return \"Entries tagged with %s\" % obj.tag\n\n        def items(self, obj):\n            entries = Entry.objects.filter(tags__id__exact=obj.id)\n            return entries.order_by('-pub_date')[:30]\n\nHere's the basic algorithm of the RSS framework, given this class and a\nrequest to the URL ``/feeds/tags/python/``:\n\n#. The framework gets the URL ``/feeds/tags/python/`` and notices there's an\n   extra bit of URL after the slug. It splits that remaining string by the\n   slash character (``\"/\"``) and calls the ``Feed`` class's\n   ``get_object()`` method, passing it the bits.\n\n   In this case, bits is ``['python']``. For a request to\n   ``/feeds/tags/python/django/``, bits would be ``['python', 'django']``.\n\n#. ``get_object()`` is responsible for retrieving the given ``Tag`` object,\n   from the given ``bits``.\n\n   In this case, it uses the Django database API to\n   retrieve the ``Tag``. Note that ``get_object()`` should raise\n   ``django.core.exceptions.ObjectDoesNotExist`` if given invalid\n   parameters. There's no ``try``/``except`` around the\n   ``Tag.objects.get()`` call, because it's not necessary. That function\n   raises ``Tag.DoesNotExist`` on failure, and ``Tag.DoesNotExist`` is a\n   subclass of ``ObjectDoesNotExist``. Raising ``ObjectDoesNotExist`` in\n   ``get_object()`` tells Django to produce a 404 error for that request.\n\n#. To generate the feed's ``<title>``, ``<link>``, and ``<description>``,\n   Django uses the ``title()``, ``link()``, and ``description()`` methods.\n   In the previous example, they were simple string class attributes, but\n   this example illustrates that they can be either strings *or* methods.\n   For each of ``title``, ``link``, and ``description``, Django follows\n   this algorithm:\n\n   #. It tries to call a method, passing the ``obj`` argument,\n      where ``obj`` is the object returned by ``get_object()``.\n\n   #. Failing that, it tries to call a method with no arguments.\n\n   #. Failing that, it uses the class attribute.\n\n#. Finally, note that ``items()`` in this example also takes the ``obj``\n   argument. The algorithm for ``items`` is the same as described in the\n   previous step -- first, it tries ``items(obj)``, then ``items()``, and then\n   finally an ``items`` class attribute (which should be a list).\n\nFull documentation of all the methods and attributes of the ``Feed`` classes is\nalways available from the official Django documentation\n(http://docs.djangoproject.com/en/dev/ref/contrib/syndication/).\n\nSpecifying the Type of Feed\n---------------------------\n\nBy default, the syndication framework produces RSS 2.0. To change that,\nadd a ``feed_type`` attribute to your ``Feed`` class::\n\n    from django.utils.feedgenerator import Atom1Feed\n\n    class MyFeed(Feed):\n        feed_type = Atom1Feed\n\n.. SL Tested ok\n\nNote that you set ``feed_type`` to a class object, not an instance. Currently\navailable feed types are shown in Table 11-1.\n\n.. table:: Table 11-1. Feed Types\n\n    ===================================================  =====================\n    Feed Class                                           Format\n    ===================================================  =====================\n    ``django.utils.feedgenerator.Rss201rev2Feed``        RSS 2.01 (default)\n\n    ``django.utils.feedgenerator.RssUserland091Feed``    RSS 0.91\n\n    ``django.utils.feedgenerator.Atom1Feed``             Atom 1.0\n    ===================================================  =====================\n\nEnclosures\n----------\n\nTo specify enclosures (i.e., media resources associated with a feed item such as\nMP3 podcast feeds), use the ``item_enclosure_url``, ``item_enclosure_length``,\nand ``item_enclosure_mime_type`` hooks, for example::\n\n    from myproject.models import Song\n\n    class MyFeedWithEnclosures(Feed):\n        title = \"Example feed with enclosures\"\n        link = \"/feeds/example-with-enclosures/\"\n\n        def items(self):\n            return Song.objects.all()[:30]\n\n        def item_enclosure_url(self, item):\n            return item.song_url\n\n        def item_enclosure_length(self, item):\n            return item.song_length\n\n        item_enclosure_mime_type = \"audio/mpeg\"\n\n.. SL Tested ok\n\nThis assumes, of course, that you've created a ``Song`` object with ``song_url``\nand ``song_length`` (i.e., the size in bytes) fields.\n\nLanguage\n--------\n\nFeeds created by the syndication framework automatically include the\nappropriate ``<language>`` tag (RSS 2.0) or ``xml:lang`` attribute (Atom).\nThis comes directly from your ``LANGUAGE_CODE`` setting.\n\nURLs\n----\n\nThe ``link`` method/attribute can return either an absolute URL (e.g.,\n``\"/blog/\"``) or a URL with the fully qualified domain and protocol (e.g.,\n``\"http://www.example.com/blog/\"``). If ``link`` doesn't return the domain,\nthe syndication framework will insert the domain of the current site,\naccording to your ``SITE_ID`` setting. (See Chapter 16 for more on ``SITE_ID``\nand the sites framework.)\n\nAtom feeds require a ``<link rel=\"self\">`` that defines the feed's current\nlocation. The syndication framework populates this automatically.\n\nPublishing Atom and RSS Feeds in Tandem\n---------------------------------------\n\nSome developers like to make available both Atom *and* RSS versions of their\nfeeds. That's easy to do with Django: just create a subclass of your ``feed``\nclass and set the ``feed_type`` to something different. Then update your\nURLconf to add the extra versions. Here's a full example::\n\n    from django.contrib.syndication.feeds import Feed\n    from django.utils.feedgenerator import Atom1Feed\n    from mysite.blog.models import Entry\n\n    class RssLatestEntries(Feed):\n        title = \"My Blog\"\n        link = \"/archive/\"\n        description = \"The latest news about stuff.\"\n\n        def items(self):\n            return Entry.objects.order_by('-pub_date')[:5]\n\n    class AtomLatestEntries(RssLatestEntries):\n        feed_type = Atom1Feed\n\nAnd here's the accompanying URLconf::\n\n    from django.conf.urls.defaults import *\n    from myproject.feeds import RssLatestEntries, AtomLatestEntries\n\n    feeds = {\n        'rss': RssLatestEntries,\n        'atom': AtomLatestEntries,\n    }\n\n    urlpatterns = patterns('',\n        # ...\n        (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',\n            {'feed_dict': feeds}),\n        # ...\n    )\n\n.. SL Tested ok\n\nThe Sitemap Framework\n=====================\n\nA *sitemap* is an XML file on your Web site that tells search engine indexers\nhow frequently your pages change and how \"important\" certain pages are in\nrelation to other pages on your site. This information helps search engines\nindex your site.\n\nFor example, here's a piece of the sitemap for Django's Web site\n(http://www.djangoproject.com/sitemap.xml)::\n\n    <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n      <url>\n        <loc>http://www.djangoproject.com/documentation/</loc>\n        <changefreq>weekly</changefreq>\n        <priority>0.5</priority>\n      </url>\n      <url>\n        <loc>http://www.djangoproject.com/documentation/0_90/</loc>\n        <changefreq>never</changefreq>\n        <priority>0.1</priority>\n      </url>\n      ...\n    </urlset>\n\nFor more on sitemaps, see http://www.sitemaps.org/.\n\nThe Django sitemap framework automates the creation of this XML file by\nletting you express this information in Python code. To create a sitemap,\nyou just need to write a ``Sitemap`` class and point to it in your URLconf.\n\nInstallation\n------------\n\nTo install the sitemap application, follow these steps:\n\n#. Add ``'django.contrib.sitemaps'`` to your ``INSTALLED_APPS`` setting.\n\n#. Make sure\n   ``'django.template.loaders.app_directories.load_template_source'`` is\n   in your ``TEMPLATE_LOADERS`` setting. It's in there by default, so\n   you'll need to change this only if you've changed that setting.\n\n#. Make sure you've installed the sites framework (see Chapter 16).\n\n.. note::\n\n    The sitemap application doesn't install any database tables. The only\n    reason it needs to go into ``INSTALLED_APPS`` is so the\n    ``load_template_source`` template loader can find the default templates.\n\nInitialization\n--------------\n\nTo activate sitemap generation on your Django site, add this line to your\nURLconf::\n\n    (r'^sitemap\\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})\n\nThis line tells Django to build a sitemap when a client accesses\n``/sitemap.xml``. Note that the dot character in ``sitemap.xml`` is escaped\nwith a backslash, because dots have a special meaning in regular expressions.\n\nThe name of the sitemap file is not important, but the location is. Search\nengines will only index links in your sitemap for the current URL level and\nbelow. For instance, if ``sitemap.xml`` lives in your root directory, it may\nreference any URL in your site. However, if your sitemap lives at\n``/content/sitemap.xml``, it may only reference URLs that begin with\n``/content/``.\n\nThe sitemap view takes an extra, required argument: ``{'sitemaps':\nsitemaps}``. ``sitemaps`` should be a dictionary that maps a short section\nlabel (e.g., ``blog`` or ``news``) to its ``Sitemap`` class (e.g.,\n``BlogSitemap`` or ``NewsSitemap``). It may also map to an *instance* of a\n``Sitemap`` class (e.g., ``BlogSitemap(some_var)``).\n\nSitemap Classes\n---------------\n\nA ``Sitemap`` class is a simple Python class that represents a \"section\" of\nentries in your sitemap. For example, one ``Sitemap`` class could represent\nall the entries of your weblog, while another could represent all of the\nevents in your events calendar.\n\nIn the simplest case, all these sections get lumped together into one\n``sitemap.xml``, but it's also possible to use the framework to generate a\nsitemap index that references individual sitemap files, one per section\n(as described shortly).\n\n``Sitemap`` classes must subclass ``django.contrib.sitemaps.Sitemap``. They\ncan live anywhere in your code tree.\n\nFor example, let's assume you have a blog system, with an ``Entry`` model, and\nyou want your sitemap to include all the links to your individual blog\nentries. Here's how your ``Sitemap`` class might look::\n\n    from django.contrib.sitemaps import Sitemap\n    from mysite.blog.models import Entry\n\n    class BlogSitemap(Sitemap):\n        changefreq = \"never\"\n        priority = 0.5\n\n        def items(self):\n            return Entry.objects.filter(is_draft=False)\n\n        def lastmod(self, obj):\n            return obj.pub_date\n\n.. SL Tested ok\n\nDeclaring a ``Sitemap`` should look very similar to declaring a ``Feed``.\nThat's by design.\n\nLike ``Feed`` classes, ``Sitemap`` members can be either methods or\nattributes. See the steps in the earlier \"A Complex Example\" section for more\nabout how this works.\n\nA ``Sitemap`` class can define the following methods/attributes:\n\n* ``items`` (**required**): Provides list of objects. The framework\n  doesn't care what *type* of objects they are; all that matters is that\n  these objects get passed to the ``location()``, ``lastmod()``,\n  ``changefreq()``, and ``priority()`` methods.\n\n* ``location`` (optional): Gives the absolute URL for a given object.\n  Here, \"absolute URL\" means a URL that doesn't include the protocol or\n  domain. Here are some examples:\n\n  * Good: ``'/foo/bar/'``\n  * Bad: ``'example.com/foo/bar/'``\n  * Bad: ``'http://example.com/foo/bar/'``\n\n  If ``location`` isn't provided, the framework will call the\n  ``get_absolute_url()`` method on each object as returned by\n  ``items()``.\n\n* ``lastmod`` (optional): The object's \"last modification\" date, as a\n  Python ``datetime`` object.\n\n* ``changefreq`` (optional): How often the object changes. Possible values\n  (as given by the Sitemaps specification) are as follows:\n\n  * ``'always'``\n  * ``'hourly'``\n  * ``'daily'``\n  * ``'weekly'``\n  * ``'monthly'``\n  * ``'yearly'``\n  * ``'never'``\n\n* ``priority`` (optional): A suggested indexing priority between ``0.0``\n  and ``1.0``. The default priority of a page is ``0.5``; see the\n  http://sitemaps.org/ documentation for more about how ``priority`` works.\n\nShortcuts\n---------\n\nThe sitemap framework provides a couple convenience classes for common cases. These\nare described in the sections that follow.\n\nFlatPageSitemap\n```````````````\n\nThe ``django.contrib.sitemaps.FlatPageSitemap`` class looks at all flat pages\ndefined for the current site and creates an entry in the sitemap. These\nentries include only the ``location`` attribute -- not ``lastmod``,\n``changefreq``, or ``priority``.\n\nSee Chapter 16 for more about flat pages.\n\nGenericSitemap\n``````````````\n\nThe ``GenericSitemap`` class works with any generic views (see Chapter 11) you\nalready have.\n\nTo use it, create an instance, passing in the same ``info_dict`` you pass to\nthe generic views. The only requirement is that the dictionary have a\n``queryset`` entry. It may also have a ``date_field`` entry that specifies a\ndate field for objects retrieved from the ``queryset``. This will be used for\nthe ``lastmod`` attribute in the generated sitemap. You may also pass\n``priority`` and ``changefreq`` keyword arguments to the ``GenericSitemap``\nconstructor to specify these attributes for all URLs.\n\nHere's an example of a URLconf using both ``FlatPageSitemap`` and\n``GenericSiteMap`` (with the hypothetical ``Entry`` object from earlier)::\n\n    from django.conf.urls.defaults import *\n    from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap\n    from mysite.blog.models import Entry\n\n    info_dict = {\n        'queryset': Entry.objects.all(),\n        'date_field': 'pub_date',\n    }\n\n    sitemaps = {\n        'flatpages': FlatPageSitemap,\n        'blog': GenericSitemap(info_dict, priority=0.6),\n    }\n\n    urlpatterns = patterns('',\n        # some generic view using info_dict\n        # ...\n\n        # the sitemap\n        (r'^sitemap\\.xml$',\n         'django.contrib.sitemaps.views.sitemap',\n         {'sitemaps': sitemaps})\n    )\n\nCreating a Sitemap Index\n------------------------\n\nThe sitemap framework also has the ability to create a sitemap index that\nreferences individual sitemap files, one per each section defined in your\n``sitemaps`` dictionary. The only differences in usage are as follows:\n\n* You use two views in your URLconf:\n  ``django.contrib.sitemaps.views.index`` and\n  ``django.contrib.sitemaps.views.sitemap``.\n\n* The ``django.contrib.sitemaps.views.sitemap`` view should take a\n  ``section`` keyword argument.\n\nHere is what the relevant URLconf lines would look like for the previous example::\n\n    (r'^sitemap.xml$',\n     'django.contrib.sitemaps.views.index',\n     {'sitemaps': sitemaps}),\n\n    (r'^sitemap-(?P<section>.+).xml$',\n     'django.contrib.sitemaps.views.sitemap',\n     {'sitemaps': sitemaps})\n\nThis will automatically generate a ``sitemap.xml`` file that references both\n``sitemap-flatpages.xml`` and ``sitemap-blog.xml``. The ``Sitemap`` classes\nand the ``sitemaps`` dictionary don't change at all.\n\nPinging Google\n--------------\n\nYou may want to \"ping\" Google when your sitemap changes, to let it know to\nreindex your site. The framework provides a function to do just that:\n``django.contrib.sitemaps.ping_google()``.\n\n``ping_google()`` takes an optional argument, ``sitemap_url``, which should be\nthe absolute URL of your site's sitemap (e.g., ``'/sitemap.xml'``). If this\nargument isn't provided, ``ping_google()`` will attempt to figure out your\nsitemap by performing a reverse lookup on your URLconf.\n\n``ping_google()`` raises the exception\n``django.contrib.sitemaps.SitemapNotFound`` if it cannot determine your\nsitemap URL.\n\nOne useful way to call ``ping_google()`` is from a model's ``save()`` method::\n\n    from django.contrib.sitemaps import ping_google\n\n    class Entry(models.Model):\n        # ...\n        def save(self, *args, **kwargs):\n            super(Entry, self).save(*args, **kwargs)\n            try:\n                ping_google()\n            except Exception:\n                # Bare 'except' because we could get a variety\n                # of HTTP-related exceptions.\n                pass\n\nA more efficient solution, however, would be to call ``ping_google()`` from a\n``cron`` script or some other scheduled task. The function makes an HTTP\nrequest to Google's servers, so you may not want to introduce that network\noverhead each time you call ``save()``.\n\nFinally, if ``'django.contrib.sitemaps'`` is in your ``INSTALLED_APPS``, then\nyour ``manage.py`` will include a new command, ``ping_google``. This is useful\nfor command-line access to pinging. For example::\n\n    python manage.py ping_google /sitemap.xml\n\nWhat's Next?\n============\n\nNext, we'll continue to dig deeper into the built-in tools Django gives you.\n`Chapter 14`_ looks at all the tools you need to provide user-customized\nsites: sessions, users, and authentication.\n\n.. _Chapter 14: ../chapter14/\n"
  },
  {
    "path": "Python/DjangoBook/chapter14.rst",
    "content": "=============================================\nChapter 14: Sessions, Users, and Registration\n=============================================\n\nIt's time for a confession: we've been deliberately ignoring an important\naspect of Web development prior to this point. So far, we've thought of the\ntraffic visiting our sites as some faceless, anonymous mass hurtling itself\nagainst our carefully designed pages.\n\nThis isn't true, of course. The browsers hitting our sites have real humans\nbehind them (most of the time, at least). That's a big thing to ignore: the\nInternet is at its best when it serves to connect *people*, not machines. If\nwe're going to develop truly compelling sites, eventually we're going to have\nto deal with the bodies behind the browsers.\n\nUnfortunately, it's not all that easy. HTTP is designed to be *stateless*--\nthat is, each and every request happens in a vacuum. There's no persistence\nbetween one request and the next, and we can't count on any aspects of a\nrequest (IP address, user agent, etc.) to consistently indicate successive\nrequests from the same person.\n\nIn this chapter you'll learn how to handle this lack of state. We'll start at\nthe lowest level (*cookies*), and work up to the high-level tools for handling\nsessions, users and registration.\n\nCookies\n=======\n\nBrowser developers long ago recognized that HTTP's statelessness poses a huge\nproblem for Web developers, and thus *cookies* were born. A cookie is a\nsmall piece of information that browsers store on behalf of Web servers. Every\ntime a browser requests a page from a certain server, it gives back the cookie\nthat it initially received.\n\nLet's take a look how this might work. When you open your browser and type in\n``google.com``, your browser sends an HTTP request to Google that starts\nsomething like this::\n\n    GET / HTTP/1.1\n    Host: google.com\n    ...\n\nWhen Google replies, the HTTP response looks something like the following::\n\n    HTTP/1.1 200 OK\n    Content-Type: text/html\n    Set-Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671;\n                expires=Sun, 17-Jan-2038 19:14:07 GMT;\n                path=/; domain=.google.com\n    Server: GWS/2.1\n    ...\n\nNotice the ``Set-Cookie`` header. Your browser will store that cookie value\n(``PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671``) and serve it back\nto Google every time you access the site. So the next time you access Google,\nyour browser is going to send a request like this::\n\n    GET / HTTP/1.1\n    Host: google.com\n    Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671\n    ...\n\nGoogle then can use that ``Cookie`` value to know that you're the same person\nwho accessed the site earlier. This value might, for example, be a key into a\ndatabase that stores user information. Google could (and does) use it to\ndisplay your account's username on the page.\n\nGetting and Setting Cookies\n---------------------------\n\nWhen dealing with persistence in Django, most of the time you'll want to use the\nhigher-level session and/or user frameworks discussed a little later in this\nchapter. However, first look at how to read and write cookies at a low\nlevel. This should help you understand how the rest of the tools discussed in\nthe chapter actually work, and it will come in handy if you ever need to play\nwith cookies directly.\n\nReading cookies that are already set is simple. Every ``HttpRequest``\nobject has a ``COOKIES`` object that acts like a dictionary; you can use it to\nread any cookies that the browser has sent to the view::\n\n    def show_color(request):\n        if \"favorite_color\" in request.COOKIES:\n            return HttpResponse(\"Your favorite color is %s\" % \\\n                request.COOKIES[\"favorite_color\"])\n        else:\n            return HttpResponse(\"You don't have a favorite color.\")\n\nWriting cookies is slightly more complicated. You need to use the\n``set_cookie()`` method on an ``HttpResponse`` object. Here's an example that\nsets the ``favorite_color`` cookie based on a ``GET`` parameter::\n\n    def set_color(request):\n        if \"favorite_color\" in request.GET:\n\n            # Create an HttpResponse object...\n            response = HttpResponse(\"Your favorite color is now %s\" % \\\n                request.GET[\"favorite_color\"])\n\n            # ... and set a cookie on the response\n            response.set_cookie(\"favorite_color\",\n                                request.GET[\"favorite_color\"])\n\n            return response\n\n        else:\n            return HttpResponse(\"You didn't give a favorite color.\")\n\n.. SL Tested ok\n\nYou can also pass a number of optional arguments to ``response.set_cookie()``\nthat control aspects of the cookie, as shown in Table 14-1.\n\n.. table:: Table 14-1: Cookie options\n\n    ==============  ==========  ==============================================\n    Parameter       Default     Description\n    ==============  ==========  ==============================================\n    ``max_age``     ``None``    Age (in seconds) that the cookie should last.\n                                If this parameter is ``None``, the cookie will\n                                last only until the browser is closed.\n\n    ``expires``     ``None``    The actual date/time when the cookie should\n                                expire. It needs to be in the format ``\"Wdy,\n                                DD-Mth-YY HH:MM:SS GMT\"``. If given, this\n                                parameter overrides the ``max_age`` parameter.\n\n    ``path``        ``\"/\"``     The path prefix that this cookie is valid for.\n                                Browsers will only pass the cookie back to\n                                pages below this path prefix, so you can use\n                                this to prevent cookies from being sent to\n                                other sections of your site.\n\n                                This is especially useful when you don't\n                                control the top level of your site's domain.\n\n    ``domain``      ``None``    The domain that this cookie is valid for.  You\n                                can use this parameter to set a cross-domain\n                                cookie. For example, ``domain=\".example.com\"``\n                                will set a cookie that is readable by the\n                                domains ``www.example.com``,\n                                ``www2.example.com``, and\n                                ``an.other.sub.domain.example.com``.\n\n                                If this parameter is set to ``None``, a cookie\n                                will only be readable by the domain that set it.\n\n    ``secure``      ``False``   If set to ``True``, this parameter instructs the\n                                browser to only return this cookie to pages\n                                accessed over HTTPS.\n    ==============  ==========  ==============================================\n\nThe Mixed Blessing of Cookies\n-----------------------------\n\nYou might notice a number of potential problems with the way cookies work.\nLet's look at some of the more important ones:\n\n* Storage of cookies is voluntary; a client does not have to accept or\n  store cookies. In fact, all browsers enable users to control the policy\n  for accepting cookies. If you want to see just how vital cookies are to\n  the Web, try turning on your browser's \"prompt to accept every cookie\"\n  option.\n\n  Despite their nearly universal use, cookies are still the definition of\n  unreliability. This means that developers should check that a user\n  actually accepts cookies before relying on them.\n\n* Cookies (especially those not sent over HTTPS) are not secure. Because\n  HTTP data is sent in cleartext, cookies are extremely vulnerable to\n  snooping attacks. That is, an attacker snooping on the wire can intercept\n  a cookie and read it. This means you should never store sensitive\n  information in a cookie.\n\n  There's an even more insidious attack, known as a *man-in-the-middle*\n  attack, wherein an attacker intercepts a cookie and uses it to pose as\n  another user. Chapter 20 discusses attacks of this nature in depth, as\n  well as ways to prevent it.\n\n* Cookies aren't even secure from their intended recipients. Most browsers\n  provide easy ways to edit the content of individual cookies, and\n  resourceful users can always use tools like mechanize\n  (http://wwwsearch.sourceforge.net/mechanize/) to construct HTTP requests\n  by hand.\n\n  So you can't store data in cookies that might be sensitive to tampering.\n  The canonical mistake in this scenario is storing something like\n  ``IsLoggedIn=1`` in a cookie when a user logs in. You'd be amazed at the\n  number of sites that make mistakes of this nature; it takes only a\n  second to fool these sites' \"security\" systems.\n\nDjango's Session Framework\n==========================\n\nWith all of these limitations and potential security holes, it's obvious that\ncookies and persistent sessions are examples of those \"pain points\" in Web\ndevelopment. Of course, Django's goal is to be an effective painkiller, so\nit comes with a session framework designed to smooth over these\ndifficulties for you.\n\nThis session framework lets you store and retrieve arbitrary data on a\nper-site visitor basis. It stores data on the server side and abstracts the\nsending and receiving of cookies. Cookies use only a hashed session ID -- not\nthe data itself -- thus protecting you from most of the common cookie\nproblems.\n\nLet's look at how to enable sessions and use them in views.\n\nEnabling Sessions\n-----------------\n\nSessions are implemented via a piece of middleware (see Chapter 17) and a Django\nmodel. To enable sessions, you'll need to follow these steps:\n\n#. Edit your ``MIDDLEWARE_CLASSES`` setting and make sure\n   ``MIDDLEWARE_CLASSES`` contains\n   ``'django.contrib.sessions.middleware.SessionMiddleware'``.\n\n#. Make sure ``'django.contrib.sessions'`` is in your ``INSTALLED_APPS``\n   setting (and run ``manage.py syncdb`` if you have to add it).\n\nThe default skeleton settings created by ``startproject`` have both of these\nbits already installed, so unless you've removed them, you probably don't have\nto change anything to get sessions to work.\n\nIf you don't want to use sessions, you might want to remove the\n``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and\n``'django.contrib.sessions'`` from your ``INSTALLED_APPS``. It will save\nyou only a small amount of overhead, but every little bit counts.\n\nUsing Sessions in Views\n-----------------------\n\nWhen ``SessionMiddleware`` is activated, each ``HttpRequest`` object -- the\nfirst argument to any Django view function -- will have a ``session``\nattribute, which is a dictionary-like object. You can read it and write to it\nin the same way you'd use a normal dictionary. For example, in a view\nyou could do stuff like this::\n\n    # Set a session value:\n    request.session[\"fav_color\"] = \"blue\"\n\n    # Get a session value -- this could be called in a different view,\n    # or many requests later (or both):\n    fav_color = request.session[\"fav_color\"]\n\n    # Clear an item from the session:\n    del request.session[\"fav_color\"]\n\n    # Check if the session has a given key:\n    if \"fav_color\" in request.session:\n        ...\n\nYou can also use other dictionary methods like ``keys()`` and ``items()`` on\n``request.session``.\n\nThere are a couple of simple rules for using Django's sessions effectively:\n\n* Use normal Python strings as dictionary keys on ``request.session`` (as\n  opposed to integers, objects, etc.).\n\n* Session dictionary keys that begin with an underscore are reserved for\n  internal use by Django. In practice, the framework uses only a small\n  number of underscore-prefixed session variables, but unless you know what\n  they all are (and you are willing to keep up with any changes in Django\n  itself), staying away from underscore prefixes will keep Django from\n  interfering with your application.\n\n  For example, don't use a session key called ``_fav_color``, like\n  this::\n\n      request.session['_fav_color'] = 'blue' # Don't do this!\n\n* Don't replace ``request.session`` with a new object, and don't access or\n  set its attributes. Use it like a Python dictionary. Examples::\n\n      request.session = some_other_object # Don't do this!\n\n      request.session.foo = 'bar' # Don't do this!\n\nLet's take a look at a few quick examples. This simplistic view sets a\n``has_commented`` variable to ``True`` after a user posts a comment. It's a\nsimple (if not particularly secure) way of preventing a user from\nposting more than one comment::\n\n    def post_comment(request):\n        if request.method != 'POST':\n            raise Http404('Only POSTs are allowed')\n\n        if 'comment' not in request.POST:\n            raise Http404('Comment not submitted')\n\n        if request.session.get('has_commented', False):\n            return HttpResponse(\"You've already commented.\")\n\n        c = comments.Comment(comment=request.POST['comment'])\n        c.save()\n        request.session['has_commented'] = True\n        return HttpResponse('Thanks for your comment!')\n\nThis simplistic view logs in a \"member\" of the site::\n\n    def login(request):\n        if request.method != 'POST':\n            raise Http404('Only POSTs are allowed')\n        try:\n            m = Member.objects.get(username=request.POST['username'])\n            if m.password == request.POST['password']:\n                request.session['member_id'] = m.id\n                return HttpResponseRedirect('/you-are-logged-in/')\n        except Member.DoesNotExist:\n            return HttpResponse(\"Your username and password didn't match.\")\n\nAnd this one logs out a member who has been logged in via ``login()`` above::\n\n    def logout(request):\n        try:\n            del request.session['member_id']\n        except KeyError:\n            pass\n        return HttpResponse(\"You're logged out.\")\n\n.. note::\n\n    In practice, this is a lousy way of logging users in. The authentication\n    framework discussed shortly handles this task for you in a much more robust\n    and useful manner. These examples are deliberately simplistic so that you\n    can easily see what's going on.\n\nSetting Test Cookies\n--------------------\n\nAs mentioned above, you can't rely on every browser accepting cookies. So, as\na convenience, Django provides an easy way to test whether a user's browser\naccepts cookies. Just call ``request.session.set_test_cookie()`` in a view, and\ncheck ``request.session.test_cookie_worked()`` in a subsequent view -- not in\nthe same view call.\n\nThis awkward split between ``set_test_cookie()`` and ``test_cookie_worked()``\nis necessary due to the way cookies work. When you set a cookie, you can't\nactually tell whether a browser accepted it until the browser's next request.\n\nIt's good practice to use ``delete_test_cookie()`` to clean up after yourself.\nDo this after you've verified that the test cookie worked.\n\nHere's a typical usage example::\n\n    def login(request):\n\n        # If we submitted the form...\n        if request.method == 'POST':\n\n            # Check that the test cookie worked (we set it below):\n            if request.session.test_cookie_worked():\n\n                # The test cookie worked, so delete it.\n                request.session.delete_test_cookie()\n\n                # In practice, we'd need some logic to check username/password\n                # here, but since this is an example...\n                return HttpResponse(\"You're logged in.\")\n\n            # The test cookie failed, so display an error message. If this\n            # were a real site, we'd want to display a friendlier message.\n            else:\n                return HttpResponse(\"Please enable cookies and try again.\")\n\n        # If we didn't post, send the test cookie along with the login form.\n        request.session.set_test_cookie()\n        return render(request, 'foo/login_form.html')\n\n.. note::\n\n    Again, the built-in authentication functions handle this check for you.\n\nUsing Sessions Outside of Views\n-------------------------------\n\nInternally, each session is just a normal Django model defined in\n``django.contrib.sessions.models``. Each session is identified by a more-or-less\nrandom 32-character hash stored in a cookie. Because it's a normal model, you\ncan access sessions using the normal Django database API::\n\n    >>> from django.contrib.sessions.models import Session\n    >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')\n    >>> s.expire_date\n    datetime.datetime(2005, 8, 20, 13, 35, 12)\n\nYou'll need to call ``get_decoded()`` to get the actual session data. This is\nnecessary because the dictionary is stored in an encoded format::\n\n    >>> s.session_data\n    'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'\n    >>> s.get_decoded()\n    {'user_id': 42}\n\nWhen Sessions Are Saved\n-----------------------\n\nBy default, Django only saves to the database if the session has been modified\n-- that is, if any of its dictionary values have been assigned or deleted::\n\n    # Session is modified.\n    request.session['foo'] = 'bar'\n\n    # Session is modified.\n    del request.session['foo']\n\n    # Session is modified.\n    request.session['foo'] = {}\n\n    # Gotcha: Session is NOT modified, because this alters\n    # request.session['foo'] instead of request.session.\n    request.session['foo']['bar'] = 'baz'\n\nTo change this default behavior, set ``SESSION_SAVE_EVERY_REQUEST``\nto ``True``. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, Django\nwill save the session to the database on every single request, even if it\nwasn't changed.\n\nNote that the session cookie is sent only when a session has been created or\nmodified. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, the session cookie\nwill be sent on every request. Similarly, the ``expires`` part of a session\ncookie is updated each time the session cookie is sent.\n\nBrowser-Length Sessions vs. Persistent Sessions\n-----------------------------------------------\n\nYou might have noticed that the cookie Google sent us at the beginning of this\nchapter contained ``expires=Sun, 17-Jan-2038 19:14:07 GMT;``. Cookies can\noptionally contain an expiration date that advises the browser on when to\nremove the cookie. If a cookie doesn't contain an expiration value, the browser\nwill expire it when the user closes his or her browser window. You can control\nthe session framework's behavior in this regard with the\n``SESSION_EXPIRE_AT_BROWSER_CLOSE`` setting.\n\nBy default, ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``False``, which means\nsession cookies will be stored in users' browsers for ``SESSION_COOKIE_AGE``\nseconds (which defaults to two weeks, or 1,209,600 seconds). Use this if you\ndon't want people to have to log in every time they open a browser.\n\nIf ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``True``, Django will use\nbrowser-length cookies.\n\nOther Session Settings\n----------------------\n\nBesides the settings already mentioned, a few other settings\ninfluence how Django's session framework uses cookies, as shown in Table 14-2.\n\n.. table:: Table 14-2. Settings that influence cookie behavior\n\n    ==========================  =============================  ==============\n    Setting                     Description                    Default\n    ==========================  =============================  ==============\n    ``SESSION_COOKIE_DOMAIN``   The domain to use for session  ``None``\n                                cookies. Set this to a string\n                                such as ``\".example.com\"``\n                                for cross-domain cookies, or\n                                use ``None`` for a standard\n                                cookie.\n\n    ``SESSION_COOKIE_NAME``     The name of the cookie to use  ``\"sessionid\"``\n                                for sessions. This can be any\n                                string.\n\n    ``SESSION_COOKIE_SECURE``   Whether to use a \"secure\"       ``False``\n                                cookie for the session\n                                cookie. If this is set to\n                                ``True``,  the cookie will be\n                                marked as \"secure,\" which\n                                means that browsers will\n                                ensure that the cookie is\n                                only sent via HTTPS.\n    ==========================  =============================  ==============\n\n.. admonition:: Technical Details\n\n    For the curious, here are a few technical notes about the inner workings\n    of the session framework:\n\n    * The session dictionary accepts any Python object capable of being\n      \"pickled.\" See the documentation for Python's built-in ``pickle``\n      module for information about how this works.\n\n    * Session data is stored in a database table named ``django_session``.\n\n    * Session data is fetched upon demand. If you never access\n      ``request.session``, Django won't hit that database table.\n\n    * Django only sends a cookie if it needs to. If you don't set any\n      session data, it won't send a session cookie (unless\n      ``SESSION_SAVE_EVERY_REQUEST`` is set to ``True``).\n\n    * The Django sessions framework is entirely, and solely, cookie based.\n      It does not fall back to putting session IDs in URLs as a last\n      resort, as some other tools (PHP, JSP) do.\n\n      This is an intentional design decision. Putting sessions in URLs\n      don't just make URLs ugly, but also make your site vulnerable to a\n      certain form of session ID theft via the ``Referer`` header.\n\n    If you're still curious, the source is pretty straightforward; look in\n    ``django.contrib.sessions`` for more details.\n\nUsers and Authentication\n========================\n\nSessions give us a way of persisting data through multiple browser requests;\nthe second part of the equation is using those sessions for user login. Of\ncourse, we can't just trust that users are who they say they are, so we need\nto authenticate them along the way.\n\nNaturally, Django provides tools to handle this common task (and many others).\nDjango's user authentication system handles user accounts, groups, permissions,\nand cookie-based user sessions. This system is often referred to as an\n*auth/auth* (authentication and authorization) system. That name recognizes\nthat dealing with users is often a two-step process. We need to\n\n#. Verify (*authenticate*) that a user is who he or she claims to be\n   (usually by checking a username and password against a database of users)\n\n#. Verify that the user is *authorized* to perform some given operation\n   (usually by checking against a table of permissions)\n\nFollowing these needs, Django's auth/auth system consists of a number of\nparts:\n\n* *Users*: People registered with your site\n\n* *Permissions*: Binary (yes/no) flags designating whether a user may\n  perform a certain task\n\n* *Groups*: A generic way of applying labels and permissions to more than\n  one user\n\n* *Messages*: A simple way to queue and display system messages to users\n\nIf you've used the admin tool (discussed in Chapter 6), you've already seen many\nof these tools, and if you've edited users or groups in the admin tool, you've\nactually been editing data in the auth system's database tables.\n\nEnabling Authentication Support\n-------------------------------\n\nLike the session tools, authentication support is bundled as a Django\napplication in ``django.contrib`` that needs to be installed. Also like the\nsession tools, it's also installed by default, but if you've removed it, you'll\nneed to follow these steps to install it:\n\n#. Make sure the session framework is installed as described earlier in this\n   chapter. Keeping track of users obviously requires cookies, and thus\n   builds on the session framework.\n\n#. Put ``'django.contrib.auth'`` in your ``INSTALLED_APPS`` setting and\n   run ``manage.py syncdb`` to install the appropriate database tables.\n\n#. Make sure that\n   ``'django.contrib.auth.middleware.AuthenticationMiddleware'`` is in\n   your ``MIDDLEWARE_CLASSES`` setting -- *after* ``SessionMiddleware``.\n\nWith that installation out of the way, we're ready to deal with users in view\nfunctions. The main interface you'll use to access users within a view is\n``request.user``; this is an object that represents the currently logged-in\nuser. If the user isn't logged in, this will instead be an ``AnonymousUser``\nobject (see below for more details).\n\nYou can easily tell if a user is logged in with the ``is_authenticated()``\nmethod::\n\n    if request.user.is_authenticated():\n        # Do something for authenticated users.\n    else:\n        # Do something for anonymous users.\n\nUsing Users\n-----------\n\nOnce you have a ``User`` -- often from ``request.user``, but possibly through\none of the other methods discussed shortly -- you have a number of fields and\nmethods available on that object. ``AnonymousUser`` objects emulate *some* of\nthis interface, but not all of it, so you should always check\n``user.is_authenticated()`` before assuming you're dealing with a bona fide user\nobject. Tables 14-3 and 14-4 list the fields and methods, respectively, on ``User`` objects.\n\n.. table:: Table 14-3. Fields on ``User`` Objects\n\n    ==================  ======================================================\n    Field               Description\n    ==================  ======================================================\n    ``username``        Required; 30 characters or fewer. Alphanumeric\n                        characters only (letters, digits, and underscores).\n\n    ``first_name``      Optional; 30 characters or fewer.\n\n    ``last_name``       Optional; 30 characters or fewer.\n\n    ``email``           Optional. E-mail address.\n\n    ``password``        Required. A hash of, and metadata about, the password\n                        (Django doesn't store the raw password). See the\n                        \"Passwords\" section for more about this value.\n\n    ``is_staff``        Boolean. Designates whether this user can access the\n                        admin site.\n\n    ``is_active``       Boolean. Designates whether this account can be used\n                        to log in. Set this flag to ``False`` instead of\n                        deleting accounts.\n\n    ``is_superuser``    Boolean. Designates that this user has all permissions\n                        without explicitly assigning them.\n\n    ``last_login``      A datetime of the user's last login. This is set to the\n                        current date/time by default.\n\n    ``date_joined``     A datetime designating when the account was created.\n                        This is set to the current date/time by default when the\n                        account is created.\n    ==================  ======================================================\n\n.. table:: Table 14-4. Methods on ``User`` Objects\n\n    ================================  ==========================================\n    Method                            Description\n    ================================  ==========================================\n    ``is_authenticated()``            Always returns ``True`` for \"real\"\n                                      ``User`` objects. This is a way to tell if\n                                      the user has been authenticated. This does\n                                      not imply any permissions, and it doesn't\n                                      check if the user is active. It only\n                                      indicates that the user has sucessfully\n                                      authenticated.\n\n    ``is_anonymous()``                Returns ``True`` only for\n                                      ``AnonymousUser`` objects (and ``False``\n                                      for \"real\" ``User`` objects). Generally,\n                                      you should prefer using\n                                      ``is_authenticated()`` to this method.\n\n    ``get_full_name()``               Returns the ``first_name`` plus the\n                                      ``last_name``, with a space in between.\n\n    ``set_password(passwd)``          Sets the user's password to the given\n                                      raw string, taking care of the password\n                                      hashing. This doesn't actually save the\n                                      ``User`` object.\n\n    ``check_password(passwd)``        Returns ``True`` if the given raw\n                                      string is the correct password for the\n                                      user. This takes care of the password\n                                      hashing in making the comparison.\n\n    ``get_group_permissions()``       Returns a list of permission strings that\n                                      the user has through the groups he or she\n                                      belongs to.\n\n    ``get_all_permissions()``         Returns a list of permission strings that\n                                      the user has, both through group and user\n                                      permissions.\n\n    ``has_perm(perm)``                Returns ``True`` if the user has the\n                                      specified permission, where ``perm`` is in\n                                      the format ``\"package.codename\"``. If the\n                                      user is inactive, this method will always\n                                      return ``False``.\n\n    ``has_perms(perm_list)``          Returns ``True`` if the user has *all* of\n                                      the specified permissions. If the user is\n                                      inactive, this method will always return\n                                      ``False``.\n\n    ``has_module_perms(app_label)``   Returns ``True`` if the user has\n                                      any permissions in the given ``app_label``.\n                                      If the user is inactive, this method will\n                                      always return ``False``.\n\n    ``get_and_delete_messages()``     Returns a list of ``Message`` objects in\n                                      the user's queue and deletes the messages\n                                      from the queue.\n\n    ``email_user(subj, msg)``         Sends an email to the user. This email\n                                      is sent from the ``DEFAULT_FROM_EMAIL``\n                                      setting.  You can also pass a third\n                                      argument, ``from_email``, to override the\n                                      From address on the email.\n    ================================  ==========================================\n\nFinally, ``User`` objects have two many-to-many fields: ``groups`` and\n``permissions``. ``User`` objects can access their related objects in the same\nway as any other many-to-many field::\n\n        # Set a user's groups:\n        myuser.groups = group_list\n\n        # Add a user to some groups:\n        myuser.groups.add(group1, group2,...)\n\n        # Remove a user from some groups:\n        myuser.groups.remove(group1, group2,...)\n\n        # Remove a user from all groups:\n        myuser.groups.clear()\n\n        # Permissions work the same way\n        myuser.permissions = permission_list\n        myuser.permissions.add(permission1, permission2, ...)\n        myuser.permissions.remove(permission1, permission2, ...)\n        myuser.permissions.clear()\n\nLogging In and Out\n------------------\n\nDjango provides built-in view functions for handling logging in and out (and a\nfew other nifty tricks), but before we get to those, let's take a look at how\nto log users in and out \"by hand.\" Django provides two functions to perform\nthese actions in ``django.contrib.auth``: ``authenticate()`` and ``login()``.\n\nTo authenticate a given username and password, use ``authenticate()``. It\ntakes two keyword arguments, ``username`` and ``password``, and it returns a\n``User`` object if the password is valid for the given username. If the\npassword is invalid, ``authenticate()`` returns ``None``::\n\n    >>> from django.contrib import auth\n    >>> user = auth.authenticate(username='john', password='secret')\n    >>> if user is not None:\n    ...     print \"Correct!\"\n    ... else:\n    ...     print \"Invalid password.\"\n\n``authenticate()`` only verifies a user's credentials. To log in a user, use\n``login()``. It takes an ``HttpRequest`` object and a ``User`` object and saves\nthe user's ID in the session, using Django's session framework.\n\nThis example shows how you might use both ``authenticate()`` and ``login()``\nwithin a view function::\n\n    from django.contrib import auth\n\n    def login_view(request):\n        username = request.POST.get('username', '')\n        password = request.POST.get('password', '')\n        user = auth.authenticate(username=username, password=password)\n        if user is not None and user.is_active:\n            # Correct password, and the user is marked \"active\"\n            auth.login(request, user)\n            # Redirect to a success page.\n            return HttpResponseRedirect(\"/account/loggedin/\")\n        else:\n            # Show an error page\n            return HttpResponseRedirect(\"/account/invalid/\")\n\nTo log out a user, use ``django.contrib.auth.logout()`` within your view. It\ntakes an ``HttpRequest`` object and has no return value::\n\n    from django.contrib import auth\n\n    def logout_view(request):\n        auth.logout(request)\n        # Redirect to a success page.\n        return HttpResponseRedirect(\"/account/loggedout/\")\n\nNote that ``auth.logout()`` doesn't throw any errors if the user wasn't logged\nin.\n\nIn practice, you usually will not need to write your own login/logout functions;\nthe authentication system comes with a set of views for generically handling\nlogging in and out. The first step in using these authentication views is to\nwire them up in your URLconf. You'll need to add this snippet::\n\n    from django.contrib.auth.views import login, logout\n\n    urlpatterns = patterns('',\n        # existing patterns here...\n        (r'^accounts/login/$',  login),\n        (r'^accounts/logout/$', logout),\n    )\n\n``/accounts/login/`` and ``/accounts/logout/`` are the default URLs that\nDjango uses for these views.\n\nBy default, the ``login`` view renders a template at\n``registration/login.html`` (you can change this template name by passing an\nextra view argument ,``template_name``). This form needs to contain a\n``username`` and a ``password`` field. A simple template might look like this::\n\n    {% extends \"base.html\" %}\n\n    {% block content %}\n\n      {% if form.errors %}\n        <p class=\"error\">Sorry, that's not a valid username or password</p>\n      {% endif %}\n\n      <form action=\"\" method=\"post\">\n        <label for=\"username\">User name:</label>\n        <input type=\"text\" name=\"username\" value=\"\" id=\"username\">\n        <label for=\"password\">Password:</label>\n        <input type=\"password\" name=\"password\" value=\"\" id=\"password\">\n\n        <input type=\"submit\" value=\"login\" />\n        <input type=\"hidden\" name=\"next\" value=\"{{ next|escape }}\" />\n      </form>\n\n    {% endblock %}\n\nIf the user successfully logs in, he or she will be redirected to\n``/accounts/profile/`` by default. You can override this by providing a hidden\nfield called ``next`` with the URL to redirect to after logging in. You can\nalso pass this value as a ``GET`` parameter to the login view and it will be\nautomatically added to the context as a variable called ``next`` that you can\ninsert into that hidden field.\n\nThe logout view works a little differently. By default it renders a template\nat ``registration/logged_out.html`` (which usually contains a \"You've\nsuccessfully logged out\" message). However, you can call the view with an\nextra argument, ``next_page``, which will instruct the view to redirect after\na logout.\n\nLimiting Access to Logged-in Users\n----------------------------------\n\nOf course, the reason we're going through all this trouble is so we can\nlimit access to parts of our site.\n\nThe simple, raw way to limit access to pages is to check\n``request.user.is_authenticated()`` and redirect to a login page::\n\n    from django.http import HttpResponseRedirect\n\n    def my_view(request):\n        if not request.user.is_authenticated():\n            return HttpResponseRedirect('/accounts/login/?next=%s' % request.path)\n        # ...\n\nor perhaps display an error message::\n\n    def my_view(request):\n        if not request.user.is_authenticated():\n            return render(request, 'myapp/login_error.html')\n        # ...\n\nAs a shortcut, you can use the convenient ``login_required`` decorator::\n\n    from django.contrib.auth.decorators import login_required\n\n    @login_required\n    def my_view(request):\n        # ...\n\n``login_required`` does the following:\n\n* If the user isn't logged in, redirect to ``/accounts/login/``, passing\n  the current URL path in the query string as ``next``, for example:\n  ``/accounts/login/?next=/polls/3/``.\n\n* If the user is logged in, execute the view normally. The view code\n  can then assume that the user is logged in.\n\nLimiting Access to Users Who Pass a Test\n----------------------------------------\n\nLimiting access based on certain permissions or some other test, or providing\na different location for the login view works essentially the same way.\n\nThe raw way is to run your test on ``request.user`` in the view directly. For\nexample, this view checks to make sure the user is logged in and has the\npermission ``polls.can_vote`` (more about how permissions\nworks follows)::\n\n    def vote(request):\n        if request.user.is_authenticated() and request.user.has_perm('polls.can_vote')):\n            # vote here\n        else:\n            return HttpResponse(\"You can't vote in this poll.\")\n\nAgain, Django provides a shortcut called ``user_passes_test``. It\ntakes arguments and generates a specialized decorator for your particular\nsituation::\n\n    def user_can_vote(user):\n        return user.is_authenticated() and user.has_perm(\"polls.can_vote\")\n\n    @user_passes_test(user_can_vote, login_url=\"/login/\")\n    def vote(request):\n        # Code here can assume a logged-in user with the correct permission.\n        ...\n\n``user_passes_test`` takes one required argument: a callable that takes a\n``User`` object and returns ``True`` if the user is allowed to view the page.\nNote that ``user_passes_test`` does not automatically check that the ``User``\nis authenticated; you should do that yourself.\n\nIn this example we're also showing the second (optional) argument,\n``login_url``, which lets you specify the URL for your login page\n(``/accounts/login/`` by default). If the user doesn't pass the test, then\nthe ``user_passes_test`` decorator will redirect the user to the ``login_url``.\n\nBecause it's a relatively common task to check whether a user has a particular\npermission, Django provides a shortcut for that case: the\n``permission_required()`` decorator. Using this decorator, the earlier example\ncan be written as follows::\n\n    from django.contrib.auth.decorators import permission_required\n\n    @permission_required('polls.can_vote', login_url=\"/login/\")\n    def vote(request):\n        # ...\n\nNote that ``permission_required()`` also takes an optional ``login_url``\nparameter, which also defaults to ``'/accounts/login/'``.\n\n.. admonition:: Limiting Access to Generic Views\n\n    One of the most frequently asked questions on the Django users list deals\n    with limiting access to a generic view. To pull this off, you'll need to\n    write a thin wrapper around the view and point your URLconf to your wrapper\n    instead of the generic view itself::\n\n        from django.contrib.auth.decorators import login_required\n        from django.views.generic.date_based import object_detail\n\n        @login_required\n        def limited_object_detail(*args, **kwargs):\n            return object_detail(*args, **kwargs)\n\n    You can, of course, replace ``login_required`` with any of the other\n    limiting decorators.\n\nManaging Users, Permissions, and Groups\n---------------------------------------\n\nThe easiest way by far to manage the auth system is through the admin interface.\nChapter 6 discusses how to use Django's admin site to edit users and\ncontrol their permissions and access, and most of the time you'll just use that\ninterface.\n\nHowever, there are low-level APIs you can dive into when you need absolute\ncontrol, and we discuss these in the sections that follow.\n\nCreating Users\n``````````````\n\nCreate users with the ``create_user`` helper function::\n\n    >>> from django.contrib.auth.models import User\n    >>> user = User.objects.create_user(username='john',\n    ...                                 email='jlennon@beatles.com',\n    ...                                 password='glass onion')\n\nAt this point, ``user`` is a ``User`` instance ready to be saved to the database\n(``create_user()`` doesn't actually call ``save()`` itself). You can continue to\nchange its attributes before saving, too::\n\n    >>> user.is_staff = True\n    >>> user.save()\n\n.. SL Tested ok\n\nChanging Passwords\n``````````````````\n\nYou can change a password with ``set_password()``::\n\n    >>> user = User.objects.get(username='john')\n    >>> user.set_password('goo goo goo joob')\n    >>> user.save()\n\n.. SL Tested ok\n\nDon't set the ``password`` attribute directly unless you know what you're\ndoing. The password is actually stored as a *salted hash* and thus can't be\nedited directly.\n\nMore formally, the ``password`` attribute of a ``User`` object is a string in\nthis format::\n\n    hashtype$salt$hash\n\nThat's a hash type, the salt, and the hash itself, separated by the dollar sign\n($) character.\n\n``hashtype`` is either ``sha1`` (default) or ``md5``, the algorithm used to\nperform a one-way hash of the password. ``salt`` is a random string used to salt\nthe raw password to create the hash, for example::\n\n    sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4\n\nThe ``User.set_password()`` and ``User.check_password()`` functions handle the\nsetting and checking of these values behind the scenes.\n\n.. admonition:: Salted hashes\n\n    A *hash* is a one-way cryptographic function -- that is, you can easily\n    compute the hash of a given value, but it's nearly impossible to take a\n    hash and reconstruct the original value.\n\n    If we stored passwords as plain text, anyone who got their hands on the\n    password database would instantly know everyone's password. Storing\n    passwords as hashes reduces the value of a compromised database.\n\n    However, an attacker with the password database could still run a *brute-\n    force* attack, hashing millions of passwords and comparing those hashes\n    against the stored values. This takes some time, but less than you might\n    think.\n\n    Worse, there are publicly available *rainbow tables*, or databases of\n    pre-computed hashes of millions of passwords. With a rainbow table, an\n    experienced attacker could break most passwords in seconds.\n\n    Adding a *salt* -- basically an initial random value -- to the stored hash\n    adds another layer of difficulty to breaking passwords. Because salts\n    differ from password to password, they also prevent the use of a rainbow\n    table, thus forcing attackers to fall back on a brute-force attack, itself\n    made more difficult by the extra entropy added to the hash by the salt.\n\n    While salted hashes aren't absolutely the most secure way of storing\n    passwords, they're a good middle ground between security and convenience.\n\nHandling Registration\n`````````````````````\n\nWe can use these low-level tools to create views that allow users to sign up\nfor new accounts. Different developers implement registration differently, so\nDjango leaves writing a registration view up to you. Luckily, it's pretty easy.\n\nAt its simplest, we could provide a small view that prompts for the required\nuser information and creates those users. Django provides a built-in form you\ncan use for this purpose, which we'll use in this example::\n\n    from django import forms\n    from django.contrib.auth.forms import UserCreationForm\n    from django.http import HttpResponseRedirect\n    from django.shortcuts import render\n\n    def register(request):\n        if request.method == 'POST':\n            form = UserCreationForm(request.POST)\n            if form.is_valid():\n                new_user = form.save()\n                return HttpResponseRedirect(\"/books/\")\n        else:\n            form = UserCreationForm()\n        return render(request, \"registration/register.html\", {\n            'form': form,\n        })\n\nThis form assumes a template named ``registration/register.html``. Here's an\nexample of what that template might look like::\n\n  {% extends \"base.html\" %}\n\n  {% block title %}Create an account{% endblock %}\n\n  {% block content %}\n    <h1>Create an account</h1>\n\n    <form action=\"\" method=\"post\">\n        {{ form.as_p }}\n        <input type=\"submit\" value=\"Create the account\">\n    </form>\n  {% endblock %}\n\n.. SL Tested ok\n\nUsing Authentication Data in Templates\n--------------------------------------\n\nThe current logged-in user and his or her permissions are made available in the\ntemplate context when you use the ``render()`` shortcut or explicitly use a\n``RequestContext`` (see Chapter 9).\n\n.. note::\n\n   Technically, these variables are only made available in the template\n   context if you use ``RequestContext`` *and* your\n   ``TEMPLATE_CONTEXT_PROCESSORS`` setting contains\n   ``\"django.core.context_processors.auth\"``, which is the default. Again, see\n   Chapter 9 for more information.\n\nWhen using ``RequestContext``, the current user (either a ``User`` instance\nor an ``AnonymousUser`` instance) is stored in the template variable\n``{{ user }}``::\n\n    {% if user.is_authenticated %}\n      <p>Welcome, {{ user.username }}. Thanks for logging in.</p>\n    {% else %}\n      <p>Welcome, new user. Please log in.</p>\n    {% endif %}\n\nThis user's permissions are stored in the template variable ``{{ perms }}``.\nThis is a template-friendly proxy to a couple of permission methods described\nshortly.\n\nThere are two ways you can use this ``perms`` object. You can use something like\n``{% if perms.polls %}`` to check if the user has *any* permissions for some given\napplication, or you can use something like ``{% if perms.polls.can_vote %}`` to\ncheck if the user has a specific permission.\n\nThus, you can check permissions in template ``{% if %}`` statements::\n\n    {% if perms.polls %}\n      <p>You have permission to do something in the polls app.</p>\n      {% if perms.polls.can_vote %}\n        <p>You can vote!</p>\n      {% endif %}\n    {% else %}\n      <p>You don't have permission to do anything in the polls app.</p>\n    {% endif %}\n\nPermissions, Groups and Messages\n================================\n\nThere are a few other bits of the authentication framework that we've only dealt\nwith in passing. We'll take a closer look at them in the following sections.\n\nPermissions\n-----------\n\nPermissions are a simple way to \"mark\" users and groups as being able to\nperform some action. They are usually used by the Django admin site, but you can\neasily use them in your own code.\n\nThe Django admin site uses permissions as follows:\n\n* Access to view the \"add\" form, and add an object is limited to users with\n  the *add* permission for that type of object.\n\n* Access to view the change list, view the \"change\" form, and change an\n  object is limited to users with the *change* permission for that type of\n  object.\n\n* Access to delete an object is limited to users with the *delete*\n  permission for that type of object.\n\nPermissions are set globally per type of object, not per specific object\ninstance. For example, it's possible to say \"Mary may change news stories,\"\nbut permissions don't let you say \"Mary may change news stories, but only\nthe ones she created herself\" or \"Mary may only change news stories that have\na certain status, publication date, or ID.\"\n\nThese three basic permissions -- add, change, and delete -- are automatically\ncreated for each Django model. Behind the scenes, these permissions are added\nto the ``auth_permission`` database table when you run ``manage.py syncdb``.\n\nThese permissions will be of the form ``\"<app>.<action>_<object_name>\"``. That\nis, if you have a ``polls`` application with a ``Choice`` model, you'll get\npermissions named ``\"polls.add_choice\"``, ``\"polls.change_choice\"``, and\n``\"polls.delete_choice\"``.\n\nJust like users, permissions are implemented in a Django model that lives in\n``django.contrib.auth.models``. This means that you can use Django's database\nAPI to interact directly with permissions if you like.\n\nGroups\n------\n\nGroups are a generic way of categorizing users so you can apply permissions,\nor some other label, to those users. A user can belong to any number of\ngroups.\n\nA user in a group automatically has the permissions granted to that group. For\nexample, if the group ``Site editors`` has the permission\n``can_edit_home_page``, any user in that group will have that permission.\n\nGroups are also a convenient way to categorize users to give them some label, or\nextended functionality. For example, you could create a group ``'Special\nusers'``, and you could write code that could, say, give those users access to a\nmembers-only portion of your site, or send them members-only e-mail messages.\n\nLike users, the easiest way to manage groups is through the admin interface.\nHowever, groups are also just Django models that live in\n``django.contrib.auth.models``, so once again you can always use Django's\ndatabase APIs to deal with groups at a low level.\n\nMessages\n--------\n\nThe message system is a lightweight way to queue messages for given users. A\nmessage is associated with a ``User``. There's no concept of expiration or\ntimestamps.\n\nMessages are used by the Django admin interface after successful actions. For\nexample, when you create an object, you'll notice a \"The object was created\nsuccessfully\" message at the top of the admin page.\n\nYou can use the same API to queue and display messages in your own application.\nThe API is simple:\n\n* To create a new message, use\n  ``user.message_set.create(message='message_text')``.\n\n* To retrieve/delete messages, use ``user.get_and_delete_messages()``,\n  which returns a list of ``Message`` objects in the user's queue (if any)\n  and deletes the messages from the queue.\n\nIn this example view, the system saves a message for the user after creating a\nplaylist::\n\n    def create_playlist(request, songs):\n        # Create the playlist with the given songs.\n        # ...\n        request.user.message_set.create(\n            message=\"Your playlist was added successfully.\"\n        )\n        return render(request, \"playlists/create.html\")\n\nWhen you use the ``render()`` shortcut or render a template with a\n``RequestContext``, the current logged-in user and his or her messages are made\navailable in the template context as the template variable ``{{ messages }}``.\nHere's an example of template code that displays messages::\n\n    {% if messages %}\n    <ul>\n        {% for message in messages %}\n        <li>{{ message }}</li>\n        {% endfor %}\n    </ul>\n    {% endif %}\n\nNote that ``RequestContext`` calls ``get_and_delete_messages`` behind the\nscenes, so any messages will be deleted even if you don't display them.\n\nFinally, note that this messages framework only works with users in the user\ndatabase. To send messages to anonymous users, use the session framework\ndirectly.\n\nWhat's Next\n===========\n\nThe session and authorization system is a lot to absorb. Most of the time,\nyou won't need all the features described in this chapter, but when you need to\nallow complex interactions between users, it's good to have all that power\navailable.\n\nIn the `next chapter`_, we'll take a look at Django's caching infrastructure,\nwhich is a convenient way to improve the performance of your application.\n\n.. _next chapter: ../chapter15/\n"
  },
  {
    "path": "Python/DjangoBook/chapter15.rst",
    "content": "===================\nChapter 15: Caching\n===================\n\nA fundamental trade-off in dynamic Web sites is, well, they're dynamic. Each\ntime a user requests a page, the Web server makes all sorts of calculations --\nfrom database queries to template rendering to business logic -- to create the\npage that your site's visitor sees. This is a lot more expensive, from a\nprocessing-overhead perspective, than your standard\nread-a-file-off-the-filesystem server arrangement.\n\nFor most Web applications, this overhead isn't a big deal. Most Web\napplications aren't washingtonpost.com or slashdot.org; they're simply small-\nto medium-sized sites with so-so traffic. But for medium- to high-traffic\nsites, it's essential to cut as much overhead as possible.\n\nThat's where caching comes in.\n\nTo cache something is to save the result of an expensive calculation so that\nyou don't have to perform the calculation next time. Here's some pseudocode\nexplaining how this would work for a dynamically generated Web page::\n\n    given a URL, try finding that page in the cache\n    if the page is in the cache:\n        return the cached page\n    else:\n        generate the page\n        save the generated page in the cache (for next time)\n        return the generated page\n\nDjango comes with a robust cache system that lets you save dynamic pages so\nthey don't have to be calculated for each request. For convenience, Django\noffers different levels of cache granularity: You can cache the output of\nspecific views, you can cache only the pieces that are difficult to produce, or\nyou can cache your entire site.\n\nDjango also works well with \"upstream\" caches, such as Squid\n(http://www.squid-cache.org/) and browser-based caches. These are the types of\ncaches that you don't directly control but to which you can provide hints (via\nHTTP headers) about which parts of your site should be cached, and how.\n\nSetting Up the Cache\n====================\n\nThe cache system requires a small amount of setup. Namely, you have to tell it\nwhere your cached data should live -- whether in a database, on the filesystem\nor directly in memory. This is an important decision that affects your cache's\nperformance; yes, some cache types are faster than others.\n\nYour cache preference goes in the ``CACHE_BACKEND`` setting in your settings\nfile. Here's an explanation of all available values for ``CACHE_BACKEND``.\n\nMemcached\n---------\n\nBy far the fastest, most efficient type of cache available to Django, Memcached\nis an entirely memory-based cache framework originally developed to handle high\nloads at LiveJournal.com and subsequently open-sourced by Danga Interactive.\nIt's used by sites such as Facebook and Wikipedia to reduce database access and\ndramatically increase site performance.\n\nMemcached is available for free at http://danga.com/memcached/ . It runs as a\ndaemon and is allotted a specified amount of RAM. All it does is provide an\nfast interface for adding, retrieving and deleting arbitrary data in the cache.\nAll data is stored directly in memory, so there's no overhead of database or\nfilesystem usage.\n\nAfter installing Memcached itself, you'll need to install the Memcached Python\nbindings, which are not bundled with Django directly. Two versions of this are\navailable. Choose and install *one* of the following modules:\n\n* The fastest available option is a module called ``cmemcache``, available\n  at http://gijsbert.org/cmemcache/ .\n\n* If you can't install ``cmemcache``, you can install ``python-memcached``,\n  available at ftp://ftp.tummy.com/pub/python-memcached/ . If that URL is\n  no longer valid, just go to the Memcached Web site\n  (http://www.danga.com/memcached/) and get the Python bindings from the\n  \"Client APIs\" section.\n\nTo use Memcached with Django, set ``CACHE_BACKEND`` to\n``memcached://ip:port/``, where ``ip`` is the IP address of the Memcached\ndaemon and ``port`` is the port on which Memcached is running.\n\nIn this example, Memcached is running on localhost (127.0.0.1) port 11211::\n\n    CACHE_BACKEND = 'memcached://127.0.0.1:11211/'\n\nOne excellent feature of Memcached is its ability to share cache over multiple\nservers. This means you can run Memcached daemons on multiple machines, and the\nprogram will treat the group of machines as a *single* cache, without the need\nto duplicate cache values on each machine. To take advantage of this feature,\ninclude all server addresses in ``CACHE_BACKEND``, separated by semicolons.\n\nIn this example, the cache is shared over Memcached instances running on IP\naddress 172.19.26.240 and 172.19.26.242, both on port 11211::\n\n    CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'\n\nIn the following example, the cache is shared over Memcached instances running\non the IP addresses 172.19.26.240 (port 11211), 172.19.26.242 (port 11212), and\n172.19.26.244 (port 11213)::\n\n    CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11212;172.19.26.244:11213/'\n\nA final point about Memcached is that memory-based caching has one\ndisadvantage: Because the cached data is stored in memory, the data will be\nlost if your server crashes. Clearly, memory isn't intended for permanent data\nstorage, so don't rely on memory-based caching as your only data storage.\nWithout a doubt, *none* of the Django caching backends should be used for\npermanent storage -- they're all intended to be solutions for caching, not\nstorage -- but we point this out here because memory-based caching is\nparticularly temporary.\n\nDatabase Caching\n----------------\n\nTo use a database table as your cache backend, first create a cache table in\nyour database by running this command::\n\n    python manage.py createcachetable [cache_table_name]\n\n...where ``[cache_table_name]`` is the name of the database table to create.\n(This name can be whatever you want, as long as it's a valid table name that's\nnot already being used in your database.) This command creates a single table\nin your database that is in the proper format that Django's database-cache\nsystem expects.\n\nOnce you've created that database table, set your ``CACHE_BACKEND`` setting to\n``\"db://tablename\"``, where ``tablename`` is the name of the database table.\nIn this example, the cache table's name is ``my_cache_table``::\n\n    CACHE_BACKEND = 'db://my_cache_table'\n\nThe database caching backend uses the same database as specified in your\nsettings file. You can't use a different database backend for your cache table.\n\nDatabase caching works best if you've got a fast, well-indexed database server.\n\nFilesystem Caching\n------------------\n\nTo store cached items on a filesystem, use the ``\"file://\"`` cache type for\n``CACHE_BACKEND``. For example, to store cached data in ``/var/tmp/django_cache``,\nuse this setting::\n\n    CACHE_BACKEND = 'file:///var/tmp/django_cache'\n\nNote that there are three forward slashes toward the beginning of that example.\nThe first two are for ``file://``, and the third is the first character of the\ndirectory path, ``/var/tmp/django_cache``. If you're on Windows, put the\ndrive letter after the ``file://``, like this::\n\n    file://c:/foo/bar\n\nThe directory path should be absolute -- that is, it should start at the root\nof your filesystem. It doesn't matter whether you put a slash at the end of the\nsetting.\n\nMake sure the directory pointed-to by this setting exists and is readable and\nwritable by the system user under which your Web server runs. Continuing the\nabove example, if your server runs as the user ``apache``, make sure the\ndirectory ``/var/tmp/django_cache`` exists and is readable and writable by the\nuser ``apache``.\n\nEach cache value will be stored as a separate file whose contents are the\ncache data saved in a serialized (\"pickled\") format, using Python's ``pickle``\nmodule. Each file's name is the cache key, escaped for safe filesystem use.\n\nLocal-Memory Caching\n--------------------\n\nIf you want the speed advantages of in-memory caching but don't have the\ncapability of running Memcached, consider the local-memory cache backend. This\ncache is multi-process and thread-safe. To use it, set ``CACHE_BACKEND`` to\n``\"locmem:///\"``. For example::\n\n    CACHE_BACKEND = 'locmem:///'\n\nNote that each process will have its own private cache instance, which means no\ncross-process caching is possible. This obviously also means the local memory\ncache isn't particularly memory-efficient, so it's probably not a good choice\nfor production environments. It's nice for development.\n\nDummy Caching (For Development)\n-------------------------------\n\nFinally, Django comes with a \"dummy\" cache that doesn't actually cache -- it\njust implements the cache interface without doing anything.\n\nThis is useful if you have a production site that uses heavy-duty caching in\nvarious places but a development/test environment where you don't want to cache\nand don't want to have to change your code to special-case the latter. To\nactivate dummy caching, set ``CACHE_BACKEND`` like so::\n\n    CACHE_BACKEND = 'dummy:///'\n\nUsing a Custom Cache Backend\n----------------------------\n\nWhile Django includes support for a number of cache backends out-of-the-box,\nsometimes you might want to use a customized cache backend. To use an external\ncache backend with Django, use a Python import path as the scheme portion (the\npart before the initial colon) of the ``CACHE_BACKEND`` URI, like so::\n\n    CACHE_BACKEND = 'path.to.backend://'\n\nIf you're building your own backend, you can use the standard cache backends\nas reference implementations. You'll find the code in the\n``django/core/cache/backends/`` directory of the Django source.\n\nNote: Without a really compelling reason, such as a host that doesn't support\nthem, you should stick to the cache backends included with Django. They've\nbeen well-tested and are easy to use.\n\nCACHE_BACKEND Arguments\n-----------------------\n\nEach cache backend may take arguments. They're given in query-string style on\nthe ``CACHE_BACKEND`` setting. Valid arguments are as follows:\n\n* ``timeout``: The default timeout, in seconds, to use for the cache.\n  This argument defaults to 300 seconds (5 minutes).\n\n* ``max_entries``: For the ``locmem``, ``filesystem`` and ``database``\n  backends, the maximum number of entries allowed in the cache before old\n  values are deleted. This argument defaults to 300.\n\n* ``cull_percentage``: The percentage of entries that are culled when\n  ``max_entries`` is reached. The actual ratio is ``1/cull_percentage``, so\n  set ``cull_percentage=2`` to cull half of the entries when ``max_entries``\n  is reached.\n\n  A value of ``0`` for ``cull_percentage`` means that the entire cache will\n  be dumped when ``max_entries`` is reached. This makes culling *much*\n  faster at the expense of more cache misses.\n\nIn this example, ``timeout`` is set to ``60``::\n\n    CACHE_BACKEND = \"memcached://127.0.0.1:11211/?timeout=60\"\n\nIn this example, ``timeout`` is ``30`` and ``max_entries`` is ``400``::\n\n    CACHE_BACKEND = \"locmem:///?timeout=30&max_entries=400\"\n\nInvalid arguments are silently ignored, as are invalid values of known\narguments.\n\nThe Per-Site Cache\n==================\n\nOnce the cache is set up, the simplest way to use caching is to cache your\nentire site. You'll need to add\n``'django.middleware.cache.UpdateCacheMiddleware'`` and\n``'django.middleware.cache.FetchFromCacheMiddleware'`` to your\n``MIDDLEWARE_CLASSES`` setting, as in this example::\n\n    MIDDLEWARE_CLASSES = (\n        'django.middleware.cache.UpdateCacheMiddleware',\n        'django.middleware.common.CommonMiddleware',\n        'django.middleware.cache.FetchFromCacheMiddleware',\n    )\n\n.. note::\n\n    No, that's not a typo: the \"update\" middleware must be first in the list,\n    and the \"fetch\" middleware must be last. The details are a bit obscure, but\n    see `Order of MIDDLEWARE_CLASSES`_ below if you'd like the full story.\n\nThen, add the following required settings to your Django settings file:\n\n* ``CACHE_MIDDLEWARE_SECONDS`` -- The number of seconds each page should be\n  cached.\n* ``CACHE_MIDDLEWARE_KEY_PREFIX`` -- If the cache is shared across multiple\n  sites using the same Django installation, set this to the name of the site,\n  or some other string that is unique to this Django instance, to prevent key\n  collisions. Use an empty string if you don't care.\n\nThe cache middleware caches every page that doesn't have GET or POST\nparameters. Optionally, if the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting is\n``True``, only anonymous requests (i.e., not those made by a logged-in user)\nwill be cached. This is a simple and effective way of disabling caching for any\nuser-specific pages (include Django's admin interface). Note that if you use\n``CACHE_MIDDLEWARE_ANONYMOUS_ONLY``, you should make sure you've activated\n``AuthenticationMiddleware``.\n\nAdditionally, the cache middleware automatically sets a few headers in each\n``HttpResponse``:\n\n* Sets the ``Last-Modified`` header to the current date/time when a fresh\n  (uncached) version of the page is requested.\n\n* Sets the ``Expires`` header to the current date/time plus the defined\n  ``CACHE_MIDDLEWARE_SECONDS``.\n\n* Sets the ``Cache-Control`` header to give a max age for the page --\n  again, from the ``CACHE_MIDDLEWARE_SECONDS`` setting.\n\nSee Chapter 17 for more on middleware.\n\nIf a view sets its own cache expiry time (i.e. it has a ``max-age`` section in\nits ``Cache-Control`` header) then the page will be cached until the expiry\ntime, rather than ``CACHE_MIDDLEWARE_SECONDS``. Using the decorators in\n``django.views.decorators.cache`` you can easily set a view's expiry time\n(using the ``cache_control`` decorator) or disable caching for a view (using\nthe ``never_cache`` decorator). See the \"Using other headers\" section below for\nmore on these decorators.\n\nThe Per-View Cache\n==================\n\nA more granular way to use the caching framework is by caching the output of\nindividual views. ``django.views.decorators.cache`` defines a ``cache_page``\ndecorator that will automatically cache the view's response for you. It's easy\nto use::\n\n    from django.views.decorators.cache import cache_page\n\n    def my_view(request):\n        # ...\n\n    my_view = cache_page(my_view, 60 * 15)\n\nOr, using Python 2.4's decorator syntax::\n\n    @cache_page(60 * 15)\n    def my_view(request):\n        # ...\n\n``cache_page`` takes a single argument: the cache timeout, in seconds. In the\nabove example, the result of the ``my_view()`` view will be cached for 15\nminutes. (Note that we've written it as ``60 * 15`` for the purpose of\nreadability. ``60 * 15`` will be evaluated to ``900`` -- that is, 15 minutes\nmultiplied by 60 seconds per minute.)\n\nThe per-view cache, like the per-site cache, is keyed off of the URL. If\nmultiple URLs point at the same view, each URL will be cached separately.\nContinuing the ``my_view`` example, if your URLconf looks like this::\n\n    urlpatterns = ('',\n        (r'^foo/(\\d{1,2})/$', my_view),\n    )\n\nthen requests to ``/foo/1/`` and ``/foo/23/`` will be cached separately, as\nyou may expect. But once a particular URL (e.g., ``/foo/23/``) has been\nrequested, subsequent requests to that URL will use the cache.\n\nSpecifying Per-View Cache in the URLconf\n----------------------------------------\n\nThe examples in the previous section have hard-coded the fact that the view is\ncached, because ``cache_page`` alters the ``my_view`` function in place. This\napproach couples your view to the cache system, which is not ideal for several\nreasons. For instance, you might want to reuse the view functions on another,\ncache-less site, or you might want to distribute the views to people who might\nwant to use them without being cached. The solution to these problems is to\nspecify the per-view cache in the URLconf rather than next to the view functions\nthemselves.\n\nDoing so is easy: simply wrap the view function with ``cache_page`` when you\nrefer to it in the URLconf. Here's the old URLconf from earlier::\n\n    urlpatterns = ('',\n        (r'^foo/(\\d{1,2})/$', my_view),\n    )\n\nHere's the same thing, with ``my_view`` wrapped in ``cache_page``::\n\n    from django.views.decorators.cache import cache_page\n\n    urlpatterns = ('',\n        (r'^foo/(\\d{1,2})/$', cache_page(my_view, 60 * 15)),\n    )\n\nIf you take this approach, don't forget to import ``cache_page`` within your\nURLconf.\n\nTemplate Fragment Caching\n=========================\n\nIf you're after even more control, you can also cache template fragments using\nthe ``cache`` template tag. To give your template access to this tag, put\n``{% load cache %}`` near the top of your template.\n\nThe ``{% cache %}`` template tag caches the contents of the block for a given\namount of time. It takes at least two arguments: the cache timeout, in seconds,\nand the name to give the cache fragment. For example::\n\n    {% load cache %}\n    {% cache 500 sidebar %}\n        .. sidebar ..\n    {% endcache %}\n\nSometimes you might want to cache multiple copies of a fragment depending on\nsome dynamic data that appears inside the fragment. For example, you might want a\nseparate cached copy of the sidebar used in the previous example for every user\nof your site. Do this by passing additional arguments to the ``{% cache %}``\ntemplate tag to uniquely identify the cache fragment::\n\n    {% load cache %}\n    {% cache 500 sidebar request.user.username %}\n        .. sidebar for logged in user ..\n    {% endcache %}\n\nIt's perfectly fine to specify more than one argument to identify the fragment.\nSimply pass as many arguments to ``{% cache %}`` as you need.\n\nThe cache timeout can be a template variable, as long as the template variable\nresolves to an integer value. For example, if the template variable\n``my_timeout`` is set to the value ``600``, then the following two examples are\nequivalent::\n\n    {% cache 600 sidebar %} ... {% endcache %}\n    {% cache my_timeout sidebar %} ... {% endcache %}\n\nThis feature is useful in avoiding repetition in templates. You can set the\ntimeout in a variable, in one place, and just reuse that value.\n\nThe Low-Level Cache API\n=======================\n\nSometimes, caching an entire rendered page doesn't gain you very much and is,\nin fact, inconvenient overkill.\n\nPerhaps, for instance, your site includes a view whose results depend on\nseveral expensive queries, the results of which change at different intervals.\nIn this case, it would not be ideal to use the full-page caching that the\nper-site or per-view cache strategies offer, because you wouldn't want to\ncache the entire result (since some of the data changes often), but you'd still\nwant to cache the results that rarely change.\n\nFor cases like this, Django exposes a simple, low-level cache API. You can use\nthis API to store objects in the cache with any level of granularity you like.\nYou can cache any Python object that can be pickled safely: strings,\ndictionaries, lists of model objects, and so forth. (Most common Python objects\ncan be pickled; refer to the Python documentation for more information about\npickling.)\n\nThe cache module, ``django.core.cache``, has a ``cache`` object that's\nautomatically created from the ``CACHE_BACKEND`` setting::\n\n    >>> from django.core.cache import cache\n\nThe basic interface is ``set(key, value, timeout_seconds)`` and ``get(key)``::\n\n    >>> cache.set('my_key', 'hello, world!', 30)\n    >>> cache.get('my_key')\n    'hello, world!'\n\nThe ``timeout_seconds`` argument is optional and defaults to the ``timeout``\nargument in the ``CACHE_BACKEND`` setting (explained above).\n\nIf the object doesn't exist in the cache, ``cache.get()`` returns ``None``::\n\n    # Wait 30 seconds for 'my_key' to expire...\n\n    >>> cache.get('my_key')\n    None\n\nWe advise against storing the literal value ``None`` in the cache, because you\nwon't be able to distinguish between your stored ``None`` value and a cache\nmiss signified by a return value of ``None``.\n\n``cache.get()`` can take a ``default`` argument. This specifies which value to\nreturn if the object doesn't exist in the cache::\n\n    >>> cache.get('my_key', 'has expired')\n    'has expired'\n\nTo add a key only if it doesn't already exist, use the ``add()`` method.\nIt takes the same parameters as ``set()``, but it will not attempt to\nupdate the cache if the key specified is already present::\n\n    >>> cache.set('add_key', 'Initial value')\n    >>> cache.add('add_key', 'New value')\n    >>> cache.get('add_key')\n    'Initial value'\n\nIf you need to know whether ``add()`` stored a value in the cache, you can\ncheck the return value. It will return ``True`` if the value was stored,\n``False`` otherwise.\n\nThere's also a ``get_many()`` interface that only hits the cache once.\n``get_many()`` returns a dictionary with all the keys you asked for that\nactually exist in the cache (and haven't expired)::\n\n    >>> cache.set('a', 1)\n    >>> cache.set('b', 2)\n    >>> cache.set('c', 3)\n    >>> cache.get_many(['a', 'b', 'c'])\n    {'a': 1, 'b': 2, 'c': 3}\n\nFinally, you can delete keys explicitly with ``delete()``. This is an easy way\nof clearing the cache for a particular object::\n\n    >>> cache.delete('a')\n\nYou can also increment or decrement a key that already exists using the\n``incr()`` or ``decr()`` methods, respectively. By default, the existing cache\nvalue will incremented or decremented by 1. Other increment/decrement values\ncan be specified by providing an argument to the increment/decrement call. A\nValueError will be raised if you attempt to increment or decrement a\nnonexistent cache key.::\n\n    >>> cache.set('num', 1)\n    >>> cache.incr('num')\n    2\n    >>> cache.incr('num', 10)\n    12\n    >>> cache.decr('num')\n    11\n    >>> cache.decr('num', 5)\n    6\n\n.. note::\n\n    ``incr()``/``decr()`` methods are not guaranteed to be atomic. On those\n    backends that support atomic increment/decrement (most notably, the\n    memcached backend), increment and decrement operations will be atomic.\n    However, if the backend doesn't natively provide an increment/decrement\n    operation, it will be implemented using a two-step retrieve/update.\n\nUpstream Caches\n===============\n\nSo far, this chapter has focused on caching your *own* data. But another type\nof caching is relevant to Web development, too: caching performed by \"upstream\"\ncaches. These are systems that cache pages for users even before the request\nreaches your Web site.\n\nHere are a few examples of upstream caches:\n\n* Your ISP may cache certain pages, so if you requested a page from\n  http://example.com/, your ISP would send you the page without having to\n  access example.com directly. The maintainers of example.com have no\n  knowledge of this caching; the ISP sits between example.com and your Web\n  browser, handling all of the caching transparently.\n\n* Your Django Web site may sit behind a *proxy cache*, such as Squid Web\n  Proxy Cache (http://www.squid-cache.org/), that caches pages for\n  performance. In this case, each request first would be handled by the\n  proxy, and it would be passed to your application only if needed.\n\n* Your Web browser caches pages, too. If a Web page sends out the\n  appropriate headers, your browser will use the local cached copy for\n  subsequent requests to that page, without even contacting the Web page\n  again to see whether it has changed.\n\nUpstream caching is a nice efficiency boost, but there's a danger to it:\nMany Web pages' contents differ based on authentication and a host of other\nvariables, and cache systems that blindly save pages based purely on URLs could\nexpose incorrect or sensitive data to subsequent visitors to those pages.\n\nFor example, say you operate a Web e-mail system, and the contents of the\n\"inbox\" page obviously depend on which user is logged in. If an ISP blindly\ncached your site, then the first user who logged in through that ISP would have\nhis user-specific inbox page cached for subsequent visitors to the site. That's\nnot cool.\n\nFortunately, HTTP provides a solution to this problem. A number of HTTP headers\nexist to instruct upstream caches to differ their cache contents depending on\ndesignated variables, and to tell caching mechanisms not to cache particular\npages. We'll look at some of these headers in the sections that follow.\n\nUsing Vary Headers\n==================\n\nThe ``Vary`` header defines which request headers a cache\nmechanism should take into account when building its cache key. For example, if\nthe contents of a Web page depend on a user's language preference, the page is\nsaid to \"vary on language.\"\n\nBy default, Django's cache system creates its cache keys using the requested\npath (e.g., ``\"/stories/2005/jun/23/bank_robbed/\"``). This means every request\nto that URL will use the same cached version, regardless of user-agent\ndifferences such as cookies or language preferences. However, if this page\nproduces different content based on some difference in request headers -- such\nas a cookie, or a language, or a user-agent -- you'll need to use the ``Vary``\nheader to tell caching mechanisms that the page output depends on those things.\n\nTo do this in Django, use the convenient ``vary_on_headers`` view decorator,\nlike so::\n\n    from django.views.decorators.vary import vary_on_headers\n\n    # Python 2.3 syntax.\n    def my_view(request):\n        # ...\n    my_view = vary_on_headers(my_view, 'User-Agent')\n\n    # Python 2.4+ decorator syntax.\n    @vary_on_headers('User-Agent')\n    def my_view(request):\n        # ...\n\nIn this case, a caching mechanism (such as Django's own cache middleware) will\ncache a separate version of the page for each unique user-agent.\n\nThe advantage to using the ``vary_on_headers`` decorator rather than manually\nsetting the ``Vary`` header (using something like\n``response['Vary'] = 'user-agent'``) is that the decorator *adds* to the\n``Vary`` header (which may already exist), rather than setting it from scratch\nand potentially overriding anything that was already in there.\n\nYou can pass multiple headers to ``vary_on_headers()``::\n\n    @vary_on_headers('User-Agent', 'Cookie')\n    def my_view(request):\n        # ...\n\nThis tells upstream caches to vary on *both*, which means each combination of\nuser-agent and cookie will get its own cache value. For example, a request with\nthe user-agent ``Mozilla`` and the cookie value ``foo=bar`` will be considered\ndifferent from a request with the user-agent ``Mozilla`` and the cookie value\n``foo=ham``.\n\nBecause varying on cookie is so common, there's a ``vary_on_cookie``\ndecorator. These two views are equivalent::\n\n    @vary_on_cookie\n    def my_view(request):\n        # ...\n\n    @vary_on_headers('Cookie')\n    def my_view(request):\n        # ...\n\nThe headers you pass to ``vary_on_headers`` are not case sensitive;\n``\"User-Agent\"`` is the same thing as ``\"user-agent\"``.\n\nYou can also use a helper function, ``django.utils.cache.patch_vary_headers``,\ndirectly. This function sets, or adds to, the ``Vary header``. For example::\n\n    from django.utils.cache import patch_vary_headers\n\n    def my_view(request):\n        # ...\n        response = render(request, 'template_name', context)\n        patch_vary_headers(response, ['Cookie'])\n        return response\n\n``patch_vary_headers`` takes an ``HttpResponse`` instance as its first argument\nand a list/tuple of case-insensitive header names as its second argument.\n\nControlling Cache: Using Other Headers\n======================================\n\nOther problems with caching are the privacy of data and the question of where\ndata should be stored in a cascade of caches.\n\nA user usually faces two kinds of caches: his or her own browser cache (a\nprivate cache) and his or her provider's cache (a public cache). A public cache\nis used by multiple users and controlled by someone else. This poses problems\nwith sensitive data--you don't want, say, your bank account number stored in a\npublic cache. So Web applications need a way to tell caches which data is\nprivate and which is public.\n\nThe solution is to indicate a page's cache should be \"private.\" To do this in\nDjango, use the ``cache_control`` view decorator. Example::\n\n    from django.views.decorators.cache import cache_control\n\n    @cache_control(private=True)\n    def my_view(request):\n        # ...\n\nThis decorator takes care of sending out the appropriate HTTP header behind the\nscenes.\n\nThere are a few other ways to control cache parameters. For example, HTTP\nallows applications to do the following:\n\n* Define the maximum time a page should be cached.\n\n* Specify whether a cache should always check for newer versions, only\n  delivering the cached content when there are no changes. (Some caches\n  might deliver cached content even if the server page changed, simply\n  because the cache copy isn't yet expired.)\n\nIn Django, use the ``cache_control`` view decorator to specify these cache\nparameters. In this example, ``cache_control`` tells caches to revalidate the\ncache on every access and to store cached versions for, at most, 3,600 seconds::\n\n    from django.views.decorators.cache import cache_control\n\n    @cache_control(must_revalidate=True, max_age=3600)\n    def my_view(request):\n        # ...\n\nAny valid ``Cache-Control`` HTTP directive is valid in ``cache_control()``.\nHere's a full list:\n\n* ``public=True``\n* ``private=True``\n* ``no_cache=True``\n* ``no_transform=True``\n* ``must_revalidate=True``\n* ``proxy_revalidate=True``\n* ``max_age=num_seconds``\n* ``s_maxage=num_seconds``\n\n(Note that the caching middleware already sets the cache header's max-age with\nthe value of the ``CACHE_MIDDLEWARE_SETTINGS`` setting. If you use a custom\n``max_age`` in a ``cache_control`` decorator, the decorator will take\nprecedence, and the header values will be merged correctly.)\n\nIf you want to use headers to disable caching altogether,\n``django.views.decorators.cache.never_cache`` is a view decorator that adds\nheaders to ensure the response won't be cached by browsers or other caches.\nExample::\n\n    from django.views.decorators.cache import never_cache\n\n    @never_cache\n    def myview(request):\n        # ...\n\nOther Optimizations\n===================\n\nDjango comes with a few other pieces of middleware that can help optimize your\napps' performance:\n\n* ``django.middleware.http.ConditionalGetMiddleware`` adds support for\n  modern browsers to conditionally GET responses based on the ``ETag``\n  and ``Last-Modified`` headers.\n\n* ``django.middleware.gzip.GZipMiddleware`` compresses responses for all\n  moderns browsers, saving bandwidth and transfer time.\n\nOrder of MIDDLEWARE_CLASSES\n===========================\n\nIf you use caching middleware, it's important to put each half in the right\nplace within the ``MIDDLEWARE_CLASSES`` setting. That's because the cache\nmiddleware needs to know which headers by which to vary the cache storage.\nMiddleware always adds something to the ``Vary`` response header when it can.\n\n``UpdateCacheMiddleware`` runs during the response phase, where middleware is\nrun in reverse order, so an item at the top of the list runs *last* during the\nresponse phase. Thus, you need to make sure that ``UpdateCacheMiddleware``\nappears *before* any other middleware that might add something to the ``Vary``\nheader. The following middleware modules do so:\n\n* ``SessionMiddleware`` adds ``Cookie``\n* ``GZipMiddleware`` adds ``Accept-Encoding``\n* ``LocaleMiddleware`` adds ``Accept-Language``\n\n``FetchFromCacheMiddleware``, on the other hand, runs during the request phase,\nwhere middleware is applied first-to-last, so an item at the top of the list\nruns *first* during the request phase. The ``FetchFromCacheMiddleware`` also\nneeds to run after other middleware updates the ``Vary`` header, so\n``FetchFromCacheMiddleware`` must be *after* any item that does so.\n\nWhat's Next?\n============\n\nDjango ships with a number of \"contrib\" packages -- optional features that can\nmake your life easier. We've already covered a few of these: the admin site\n(Chapter 6) and the session/user framework (Chapter 14). The next chapter\ncovers more of the \"contributed\" subframeworks.\n"
  },
  {
    "path": "Python/DjangoBook/chapter16.rst",
    "content": "==========================\nChapter 16: django.contrib\n==========================\n\nOne of the many strengths of Python is its \"batteries included\" philosophy: when\nyou install Python, it comes with a large standard library of packages that you\ncan start using immediately, without having to download anything else. Django\naims to follow this philosophy, and it includes its own standard library of\nadd-ons useful for common Web development tasks. This chapter covers that\ncollection of add-ons.\n\nThe Django Standard Library\n===========================\n\nDjango's standard library lives in the package ``django.contrib``. Within each\nsubpackage is a separate piece of add-on functionality. These pieces are not\nnecessarily related, but some ``django.contrib`` subpackages may require other\nones.\n\nThere's no hard requirement for the types of functionality in\n``django.contrib``. Some of the packages include models (and hence require you\nto install their database tables into your database), but others consist solely\nof middleware or template tags.\n\nThe single characteristic the ``django.contrib`` packages have in common is\nthis: if you were to remove the ``django.contrib`` package entirely, you could\nstill use Django's fundamental features with no problems. When the Django\ndevelopers add new functionality to the framework, they use this rule of thumb\nin deciding whether the new functionality should live in ``django.contrib`` or\nelsewhere.\n\n``django.contrib`` consists of these packages:\n\n* ``admin``: The Django admin site. See Chapter 6.\n\n* ``admindocs``: Auto-documentation for the Django admin site. This book\n  doesn't cover this feature; check the official Django documentation.\n\n* ``auth``: Django's authentication framework. See Chapter 14.\n\n* ``comments``: A comments application. This book doesn't cover this\n  feature; check the official Django documentation.\n\n* ``contenttypes``: A framework for hooking into \"types\" of content, where\n  each installed Django model is a separate content type. This framework is\n  used internally by other \"contrib\" applications and is mostly intended for very\n  advanced Django developers. Those developers should find out more about\n  this application by reading the source code in ``django/contrib/contenttypes``.\n\n* ``csrf``: Protection against Cross-Site Request Forgery (CSRF). See\n  the later section titled \"CSRF Protection.\"\n\n* ``databrowse``: A Django application that lets you browse your data. This\n  book doesn't cover this feature; check the official Django documentation.\n\n* ``flatpages``: A framework for managing simple \"flat\" HTML content in a\n  database. See the later section titled \"Flatpages.\"\n\n* ``formtools``: A number of useful higher-level libraries for dealing with\n  common patterns in forms. This book doesn't cover this feature; check the\n  official Django documentation.\n\n* ``gis``: Extensions to Django that provide for GIS (Geographic\n  Information Systems) support. These, for example, allow your Django\n  models to store geographic data and perform geographic queries. This is\n  a large, complex library and isn't covered in this book. See\n  http://geodjango.org/ for documentation.\n\n* ``humanize``: A set of Django template filters useful for adding a\n  \"human touch\" to data. See the later section titled \"Humanizing Data.\"\n\n* ``localflavor``: Assorted pieces of code that are useful for particular\n  countries or cultures. For example, this includes ways to validate U.S.\n  ZIP codes or Icelandic identification numbers.\n\n* ``markup``: A set of Django template filters that implement a number of\n  common markup languages. See the later section titled \"Markup Filters.\"\n\n* ``redirects``: A framework for managing redirects. See the later section titled\n  \"Redirects.\"\n\n* ``sessions``: Django's session framework. See Chapter 14.\n\n* ``sitemaps``: A framework for generating sitemap XML files. See Chapter 13.\n\n* ``sites``: A framework that lets you operate multiple Web sites from the\n  same database and Django installation. See the next section, \"Sites.\"\n\n* ``syndication``: A framework for generating syndication feeds in RSS and\n  Atom. See Chapter 13.\n\n* ``webdesign``: Django add-ons that are particularly useful to Web\n  *designers* (as opposed to developers). As of this writing, this included\n  only a single template tag, ``{% lorem %}``. Check the Django\n  documentation for information.\n\nThe rest of this chapter goes into detail a number of ``django.contrib``\npackages that we haven't yet covered in this book.\n\nSites\n=====\n\nDjango's sites system is a generic framework that lets you operate multiple\nWeb sites from the same database and Django project. This is an abstract\nconcept, and it can be tricky to understand, so we'll start with a couple of\nscenarios where it would be useful.\n\nScenario 1: Reusing Data on Multiple Sites\n------------------------------------------\n\nAs we explained in Chapter 1, the Django-powered sites LJWorld.com and\nLawrence.com are operated by the same news organization: the *Lawrence\nJournal-World* newspaper in Lawrence, Kansas. LJWorld.com focuses on news, while\nLawrence.com focuses on local entertainment. But sometimes editors want to\npublish an article on *both* sites.\n\nThe brain-dead way of solving the problem would be to use a separate database\nfor each site and to require site producers to publish the same story twice:\nonce for LJWorld.com and again for Lawrence.com. But that's inefficient for\nsite producers, and it's redundant to store multiple copies of the same story\nin the database.\n\nThe better solution? Both sites use the same article database, and an article\nis associated with one or more sites via a many-to-many relationship. The\nDjango sites framework provides the database table to which articles can be\nrelated. It's a hook for associating data with one or more \"sites.\"\n\nScenario 2: Storing Your Site Name/Domain in One Place\n------------------------------------------------------\n\nLJWorld.com and Lawrence.com both have e-mail alert functionality, which lets\nreaders sign up to get notifications when news happens. It's pretty basic: a\nreader signs up on a Web form, and he immediately gets an e-mail saying,\n\"Thanks for your subscription.\"\n\nIt would be inefficient and redundant to implement this signup-processing code\ntwice, so the sites use the same code behind the scenes. But the \"Thank you for\nyour subscription\" notice needs to be different for each site. By using ``Site``\nobjects, we can abstract the thank-you notice to use the values of the\ncurrent site's ``name`` (e.g., ``'LJWorld.com'``) and ``domain`` (e.g.,\n``'www.ljworld.com'``).\n\nThe Django sites framework provides a place for you to store the ``name`` and\n``domain`` for each site in your Django project, which means you can reuse\nthose values in a generic way.\n\nHow to Use the Sites Framework\n------------------------------\n\nThe sites framework is more a series of conventions than a framework. The\nwhole thing is based on two simple concepts:\n\n* The ``Site`` model, found in ``django.contrib.sites``, has ``domain`` and\n  ``name`` fields.\n\n* The ``SITE_ID`` setting specifies the database ID of the ``Site`` object\n  associated with that particular settings file.\n\nHow you use these two concepts is up to you, but Django uses them in a couple\nof ways automatically via simple conventions.\n\nTo install the sites application, follow these steps:\n\n1. Add ``'django.contrib.sites'`` to your ``INSTALLED_APPS``.\n\n2. Run the command ``manage.py syncdb`` to install the ``django_site``\n   table into your database. This will also create a default site object,\n   with the domain ``example.com``.\n\n3. Change the ``example.com`` site to your own domain, and add any other\n   ``Site`` objects, either through the Django admin site or via the Python\n   API. Create a ``Site`` object for each site/domain that this Django\n   project powers.\n\n4. Define the ``SITE_ID`` setting in each of your settings files. This\n   value should be the database ID of the ``Site`` object for the site\n   powered by that settings file.\n\nThe Sites Framework's Capabilities\n----------------------------------\n\nThe sections that follow describe the various things you can do with the sites\nframework.\n\nReusing Data on Multiple Sites\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo reuse data on multiple sites, as explained in the first scenario, just create\na ``ManyToManyField`` to ``Site`` in your models, for example::\n\n    from django.db import models\n    from django.contrib.sites.models import Site\n\n    class Article(models.Model):\n        headline = models.CharField(max_length=200)\n        # ...\n        sites = models.ManyToManyField(Site)\n\nThat's the infrastructure you need to associate articles with multiple sites in\nyour database. With that in place, you can reuse the same Django view code for\nmultiple sites. Continuing the ``Article`` model example, here's what an\n``article_detail`` view might look like::\n\n    from django.conf import settings\n    from django.shortcuts import get_object_or_404\n    from mysite.articles.models import Article\n\n    def article_detail(request, article_id):\n        a = get_object_or_404(Article, id=article_id, sites__id=settings.SITE_ID)\n        # ...\n\nThis view function is reusable because it checks the article's site\ndynamically, according to the value of the ``SITE_ID`` setting.\n\nFor example, say LJWorld.com's settings file has a ``SITE_ID`` set to ``1``, and\nLawrence.com's settings file has a ``SITE_ID`` set to ``2``. If this view is\ncalled when LJWorld.com's settings file is active, then it will limit the\narticle lookup to articles in which the list of sites includes LJWorld.com.\n\nAssociating Content with a Single Site\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSimilarly, you can associate a model to the ``Site`` model in a many-to-one\nrelationship using ``ForeignKey``.\n\nFor example, if each article is associated with only a single site, you could\nuse a model like this::\n\n    from django.db import models\n    from django.contrib.sites.models import Site\n\n    class Article(models.Model):\n        headline = models.CharField(max_length=200)\n        # ...\n        site = models.ForeignKey(Site)\n\nThis has the same benefits as described in the last section.\n\nHooking Into the Current Site from Views\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOn a lower level, you can use the sites framework in your Django views to do\nparticular things based on the site in which the view is being called,\nfor example::\n\n    from django.conf import settings\n\n    def my_view(request):\n        if settings.SITE_ID == 3:\n            # Do something.\n        else:\n            # Do something else.\n\nOf course, it's ugly to hard-code the site IDs like that. A slightly cleaner way\nof accomplishing the same thing is to check the current site's domain::\n\n    from django.conf import settings\n    from django.contrib.sites.models import Site\n\n    def my_view(request):\n        current_site = Site.objects.get(id=settings.SITE_ID)\n        if current_site.domain == 'foo.com':\n            # Do something\n        else:\n            # Do something else.\n\nThe idiom of retrieving the ``Site`` object for the value of\n``settings.SITE_ID`` is quite common, so the ``Site`` model's manager\n(``Site.objects``) has a ``get_current()`` method. This example is equivalent to\nthe previous one::\n\n    from django.contrib.sites.models import Site\n\n    def my_view(request):\n        current_site = Site.objects.get_current()\n        if current_site.domain == 'foo.com':\n            # Do something\n        else:\n            # Do something else.\n\n.. note::\n\n    In this final example, you don't have to import ``django.conf.settings``.\n\nGetting the Current Domain for Display\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nFor a DRY (Don't Repeat Yourself) approach to storing your site's name and\ndomain name, as explained in\n\"Scenario 2: Storing Your Site Name/Domain in One Place,\" just reference the\n``name`` and ``domain`` of the current ``Site`` object. For example::\n\n    from django.contrib.sites.models import Site\n    from django.core.mail import send_mail\n\n    def register_for_newsletter(request):\n        # Check form values, etc., and subscribe the user.\n        # ...\n        current_site = Site.objects.get_current()\n        send_mail('Thanks for subscribing to %s alerts' % current_site.name,\n            'Thanks for your subscription. We appreciate it.\\n\\n-The %s team.' % current_site.name,\n            'editor@%s' % current_site.domain,\n            [user_email])\n        # ...\n\nContinuing our ongoing example of LJWorld.com and Lawrence.com, on Lawrence.com\nthis e-mail has the subject line \"Thanks for subscribing to lawrence.com\nalerts.\" On LJWorld.com, the e-mail has the subject line \"Thanks for subscribing to\nLJWorld.com alerts.\" This same site-specific behavior is applied to the e-mails'\nmessage body.\n\nAn even more flexible (but more heavyweight) way of doing this would be to use\nDjango's template system. Assuming Lawrence.com and LJWorld.com have different\ntemplate directories (``TEMPLATE_DIRS``), you could simply delegate to the\ntemplate system like so::\n\n    from django.core.mail import send_mail\n    from django.template import loader, Context\n\n    def register_for_newsletter(request):\n        # Check form values, etc., and subscribe the user.\n        # ...\n        subject = loader.get_template('alerts/subject.txt').render(Context({}))\n        message = loader.get_template('alerts/message.txt').render(Context({}))\n        send_mail(subject, message, 'do-not-reply@example.com', [user_email])\n        # ...\n\nIn this case, you have to create ``subject.txt`` and ``message.txt``\ntemplates in both the LJWorld.com and Lawrence.com template directories.\nAs mentioned previously, that gives you more flexibility, but it's also\nmore complex.\n\nIt's a good idea to exploit the ``Site`` objects as much as possible to remove\nunneeded complexity and redundancy.\n\nCurrentSiteManager\n------------------\n\nIf ``Site`` objects play a key role in your application, consider using the\n``CurrentSiteManager`` in your model(s). It's a model manager (see Chapter 10)\nthat automatically filters its queries to include only objects associated with\nthe current ``Site``.\n\nUse ``CurrentSiteManager`` by adding it to your model explicitly. For example::\n\n    from django.db import models\n    from django.contrib.sites.models import Site\n    from django.contrib.sites.managers import CurrentSiteManager\n\n    class Photo(models.Model):\n        photo = models.FileField(upload_to='/home/photos')\n        photographer_name = models.CharField(max_length=100)\n        pub_date = models.DateField()\n        site = models.ForeignKey(Site)\n        objects = models.Manager()\n        on_site = CurrentSiteManager()\n\nWith this model, ``Photo.objects.all()`` will return all ``Photo`` objects in\nthe database, but ``Photo.on_site.all()`` will return only the ``Photo``\nobjects associated with the current site, according to the ``SITE_ID`` setting.\n\nIn other words, these two statements are equivalent::\n\n    Photo.objects.filter(site=settings.SITE_ID)\n    Photo.on_site.all()\n\nHow did ``CurrentSiteManager`` know which field of ``Photo`` was the ``Site``?\nIt defaults to looking for a field called ``site``. If your model has a\n``ForeignKey`` or ``ManyToManyField`` called something *other* than ``site``,\nyou need to explicitly pass that as the parameter to ``CurrentSiteManager``.\nThe following model, which has a field called ``publish_on``, demonstrates\nthis::\n\n    from django.db import models\n    from django.contrib.sites.models import Site\n    from django.contrib.sites.managers import CurrentSiteManager\n\n    class Photo(models.Model):\n        photo = models.FileField(upload_to='/home/photos')\n        photographer_name = models.CharField(max_length=100)\n        pub_date = models.DateField()\n        publish_on = models.ForeignKey(Site)\n        objects = models.Manager()\n        on_site = CurrentSiteManager('publish_on')\n\nIf you attempt to use ``CurrentSiteManager`` and pass a field name that doesn't\nexist, Django will raise a ``ValueError``.\n\n.. note::\n\n    You'll probably want to keep a normal (non-site-specific) ``Manager`` on\n    your model, even if you use ``CurrentSiteManager``. As explained in Appendix\n    B, if you define a manager manually, then Django won't create the automatic\n    ``objects = models.Manager()`` manager for you.\n\n    Also, certain parts of Django -- namely, the Django admin site and generic\n    views -- use whichever manager is defined *first* in the model, so if you\n    want your admin site to have access to all objects (not just site-specific\n    ones), put ``objects = models.Manager()`` in your model, before you define\n    ``CurrentSiteManager``.\n\nHow Django Uses the Sites Framework\n-----------------------------------\n\nAlthough it's not required that you use the sites framework, it's encouraged,\nbecause Django takes advantage of it in a few places. Even if your\nDjango installation is powering only a single site, you should take a few\nseconds to create the site object with your ``domain`` and ``name``, and point\nto its ID in your ``SITE_ID`` setting.\n\nHere's how Django uses the sites framework:\n\n* In the redirects framework (see the later section \"Redirects\"), each\n  redirect object is associated with a particular site. When Django searches\n  for a redirect, it takes into account the current ``SITE_ID``.\n\n* In the comments framework, each comment is associated with a particular\n  site. When a comment is posted, its ``site`` is set to the current\n  ``SITE_ID``, and when comments are listed via the appropriate template\n  tag, only the comments for the current site are displayed.\n\n* In the flatpages framework (see the later section \"Flatpages\"), each\n  flatpage is associated with a particular site. When a flatpage is created,\n  you specify its ``site``, and the flatpage middleware checks the current\n  ``SITE_ID`` in retrieving flatpages to display.\n\n* In the syndication framework (see Chapter 13), the templates for\n  ``title`` and ``description`` automatically have access to a variable\n  ``{{ site }}``, which is the ``Site`` object representing the current\n  site. Also, the hook for providing item URLs will use the\n  ``domain`` from the current ``Site`` object if you don't specify a\n  fully qualified domain.\n\n* In the authentication framework (see Chapter 14), the\n  ``django.contrib.auth.views.login`` view passes the current ``Site`` name\n  to the template as ``{{ site_name }}`` and the current ``Site`` object as\n  ``{{ site }}``.\n\nFlatpages\n=========\n\nOften you'll have a database-driven Web application up and running, but you'll\nneed to add a couple of one-off static pages, such as an About page or a\nPrivacy Policy page. It would be possible to use a standard Web server such as\nApache to serve these files as flat HTML files, but that introduces an extra\nlevel of complexity into your application, because then you have to worry about\nconfiguring Apache, you have to set up access for your team to edit those\nfiles, and you can't take advantage of Django's template system to style the\npages.\n\nThe solution to this problem is Django's flatpages application, which lives in the\npackage ``django.contrib.flatpages``. This application lets you manage such one-off\npages via Django's admin site, and it lets you specify templates for them using\nDjango's template system. It uses Django models behind the scenes, which means\nit stores the pages in a database, just like the rest of your data, and you can\naccess flatpages with the standard Django database API.\n\nFlatpages are keyed by their URL and site. When you create a flatpage, you\nspecify which URL it's associated with, along with which site(s) it's on. (For\nmore on sites, see the \"Sites\" section.)\n\nUsing Flatpages\n---------------\n\nTo install the flatpages application, follow these steps:\n\n1. Add ``'django.contrib.flatpages'`` to your ``INSTALLED_APPS``.\n   ``django.contrib.flatpages`` depends on ``django.contrib.sites``, so make\n   sure the both packages are in ``INSTALLED_APPS``.\n\n2. Add ``'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'``\n   to your ``MIDDLEWARE_CLASSES`` setting.\n\n3. Run the command ``manage.py syncdb`` to install the two required tables\n   into your database.\n\nThe flatpages application creates two tables in your database: ``django_flatpage``\nand ``django_flatpage_sites``. ``django_flatpage`` simply maps a URL to a title\nand bunch of text content. ``django_flatpage_sites`` is a many-to-many table\nthat associates a flatpage with one or more sites.\n\nThe application comes with a single ``FlatPage`` model, defined in\n``django/contrib/flatpages/models.py``. It looks something like this::\n\n    from django.db import models\n    from django.contrib.sites.models import Site\n\n    class FlatPage(models.Model):\n        url = models.CharField(max_length=100, db_index=True)\n        title = models.CharField(max_length=200)\n        content = models.TextField(blank=True)\n        enable_comments = models.BooleanField()\n        template_name = models.CharField(max_length=70, blank=True)\n        registration_required = models.BooleanField()\n        sites = models.ManyToManyField(Site)\n\nLet's examine these fields one at a time:\n\n* ``url``: The URL at which this flatpage lives, excluding the domain\n  name but including the leading slash (e.g., ``/about/contact/``).\n\n* ``title``: The title of the flatpage. The framework doesn't do anything\n  special with this. It's your responsibility to display it in your\n  template.\n\n* ``content``: The content of the flatpage (i.e., the HTML of the page).\n  The framework doesn't do anything special with this. It's your\n  responsibility to display it in the template.\n\n* ``enable_comments``: Whether to enable comments on this flatpage. The\n  framework doesn't do anything special with this. You can check this value\n  in your template and display a comment form if needed.\n\n* ``template_name``: The name of the template to use for rendering this\n  flatpage. This is optional; if it's not given or if this template doesn't\n  exist, the framework will fall back to the template\n  ``flatpages/default.html``.\n\n* ``registration_required``: Whether registration is required for viewing\n  this flatpage. This integrates with Django's authentication/user\n  framework, which is explained further in Chapter 14.\n\n* ``sites``: The sites that this flatpage lives on. This integrates with\n  Django's sites framework, which is explained in the \"Sites\" section of\n  this chapter.\n\nYou can create flatpages through either the Django admin interface or the\nDjango database API. For more information on this, see the section\n\"Adding, Changing, and Deleting Flatpages.\"\n\nOnce you've created flatpages, ``FlatpageFallbackMiddleware`` does all of\nthe work. Each time any Django application raises a 404 error, this middleware\nchecks the flatpages database for the requested URL as a last resort.\nSpecifically, it checks for a flatpage with the given URL with a site ID that\ncorresponds to the ``SITE_ID`` setting.\n\nIf it finds a match, it loads the flatpage's template or\n``flatpages/default.html`` if the flatpage has not specified a custom template.\nIt passes that template a single context variable, ``flatpage``, which is the\n``FlatPage`` object. It uses ``RequestContext`` in rendering the template.\n\nIf ``FlatpageFallbackMiddleware`` doesn't find a match, the request continues\nto be processed as usual.\n\n.. note::\n\n    This middleware only gets activated for 404 (page not found) errors -- not\n    for 500 (server error) or other error responses. Also note that the order of\n    ``MIDDLEWARE_CLASSES`` matters. Generally, you can put\n    ``FlatpageFallbackMiddleware`` at or near the end of the list, because it's\n    a last resort.\n\nAdding, Changing, and Deleting Flatpages\n----------------------------------------\n\nYou can add, change and delete flatpages in two ways:\n\nVia the Admin Interface\n~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you've activated the automatic Django admin interface, you should see a\n\"Flatpages\" section on the admin index page. Edit flatpages as you would edit any\nother object in the system.\n\nVia the Python API\n~~~~~~~~~~~~~~~~~~\n\nAs described previously, flatpages are represented by a standard Django model that\nlives in ``django/contrib/flatpages/models.py``. Hence, you can access flatpage\nobjects via the Django database API, for example::\n\n    >>> from django.contrib.flatpages.models import FlatPage\n    >>> from django.contrib.sites.models import Site\n    >>> fp = FlatPage.objects.create(\n    ...     url='/about/',\n    ...     title='About',\n    ...     content='<p>About this site...</p>',\n    ...     enable_comments=False,\n    ...     template_name='',\n    ...     registration_required=False,\n    ... )\n    >>> fp.sites.add(Site.objects.get(id=1))\n    >>> FlatPage.objects.get(url='/about/')\n    <FlatPage: /about/ -- About>\n\nUsing Flatpage Templates\n------------------------\n\nBy default, flatpages are rendered via the template ``flatpages/default.html``,\nbut you can override that for a particular flatpage with the ``template_name``\nfield on the ``FlatPage`` object.\n\nCreating the ``flatpages/default.html`` template is your responsibility. In\nyour template directory, just create a ``flatpages`` directory containing a\n``default.html`` file.\n\nFlatpage templates are passed a single context variable, ``flatpage``, which is\nthe flatpage object.\n\nHere's a sample ``flatpages/default.html`` template::\n\n    <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n        \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n    <html>\n    <head>\n    <title>{{ flatpage.title }}</title>\n    </head>\n    <body>\n    {{ flatpage.content|safe }}\n    </body>\n    </html>\n\nNote that we've used the ``safe`` template filter to allow ``flatpage.content``\nto include raw HTML and bypass auto-escaping.\n\nRedirects\n=========\n\nDjango's redirects framework lets you manage redirects easily by storing them in\na database and treating them as any other Django model object. For example, you\ncan use the redirects framework to tell Django, \"Redirect any request to\n``/music/`` to ``/sections/arts/music/``.\" This comes in handy when you need to\nmove things around on your site; Web developers should do whatever is necessary\nto avoid broken links.\n\nUsing the Redirects Framework\n-----------------------------\n\nTo install the redirects application, follow these steps:\n\n1. Add ``'django.contrib.redirects'`` to your ``INSTALLED_APPS``.\n\n2. Add ``'django.contrib.redirects.middleware.RedirectFallbackMiddleware'``\n   to your ``MIDDLEWARE_CLASSES`` setting.\n\n3. Run the command ``manage.py syncdb`` to install the single required\n   table into your database.\n\n``manage.py syncdb`` creates a ``django_redirect`` table in your database. This\nis a simple lookup table with ``site_id``, ``old_path``, and ``new_path`` fields.\n\nYou can create redirects through either the Django admin interface or the Django\ndatabase API. For more, see the section \"Adding, Changing, and Deleting\nRedirects.\"\n\nOnce you've created redirects, the ``RedirectFallbackMiddleware`` class does all\nof the work. Each time any Django application raises a 404 error, this\nmiddleware checks the redirects database for the requested URL as a last resort.\nSpecifically, it checks for a redirect with the given ``old_path`` with a site\nID that corresponds to the ``SITE_ID`` setting. (See the earlier section \"Sites\"\nfor more information on ``SITE_ID`` and the sites framework.) Then it follows these steps:\n\n* If it finds a match, and ``new_path`` is not empty, it redirects to\n  ``new_path``.\n\n* If it finds a match, and ``new_path`` is empty, it sends a 410 (\"Gone\")\n  HTTP header and an empty (contentless) response.\n\n* If it doesn't find a match, the request continues to be processed as\n  usual.\n\nThe middleware only gets activated for 404 errors -- not for 500 errors or responses of any\nother status code.\n\nNote that the order of ``MIDDLEWARE_CLASSES`` matters. Generally, you can put\n``RedirectFallbackMiddleware`` toward the end of the list, because it's a last\nresort.\n\n.. note::\n\n    If you're using both the redirect and flatpage fallback middleware, consider\n    which one (redirect or flatpage) you'd like checked first. We\n    suggest flatpages before redirects (thus putting\n    the flatpage middleware before the redirect middleware), but you might feel\n    differently.\n\nAdding, Changing, and Deleting Redirects\n----------------------------------------\n\nYou can add, change and delete redirects in two ways:\n\nVia the Admin Interface\n~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you've activated the automatic Django admin interface, you should see a\n\"Redirects\" section on the admin index page. Edit redirects as you would edit any\nother object in the system.\n\nVia the Python API\n~~~~~~~~~~~~~~~~~~\n\nRedirects are represented by a standard Django model that lives in\n``django/contrib/redirects/models.py``. Hence, you can access redirect objects\nvia the Django database API, for example::\n\n    >>> from django.contrib.redirects.models import Redirect\n    >>> from django.contrib.sites.models import Site\n    >>> red = Redirect.objects.create(\n    ...     site=Site.objects.get(id=1),\n    ...     old_path='/music/',\n    ...     new_path='/sections/arts/music/',\n    ... )\n    >>> Redirect.objects.get(old_path='/music/')\n    <Redirect: /music/ ---> /sections/arts/music/>\n\nCSRF Protection\n===============\n\nThe ``django.contrib.csrf`` package protects against\nCross-Site Request Forgery (CSRF).\n\nCSRF, also known as \"session riding,\" is a Web site security exploit. It\nhappens when a malicious Web site tricks a user into unknowingly loading a URL\nfrom a site at which that user is already authenticated, hence taking advantage\nof the user's authenticated status. This can be a bit tricky to understand at first,\nso we walk through two examples in this section.\n\nA Simple CSRF Example\n---------------------\n\nSuppose you're logged in to a webmail account at ``example.com``. This webmail\nsite has a Log Out button that points to the URL ``example.com/logout`` --\nthat is, the only action you need to take in order to log out is to visit the\npage ``example.com/logout``.\n\nA malicious site can coerce you to visit the URL ``example.com/logout`` by\nincluding that URL as a hidden ``<iframe>`` on its own (malicious) page. Thus,\nif you're logged in to the ``example.com`` webmail account and visit the\nmalicious page that has an ``<iframe>`` to ``example.com/logout``, the act of\nvisiting the malicious page will log you out from ``example.com``.\n\nClearly, being logged out of a webmail site against your will is not a\nterrifying breach of security, but this same type of exploit can happen to\n*any* site that trusts users, such as an online banking site or an e-commerce\nsite, where the exploit could be used to initiate an order or payment without\nthe user's knowledge.\n\nA More Complex CSRF Example\n---------------------------\n\nIn the previous example, ``example.com`` was partially at fault because it allowed\na state change (i.e., logging the user out) to be requested via the HTTP\n``GET`` method. It's much better practice to require an HTTP ``POST`` for any\nrequest that changes state on the server. But even Web sites that require\n``POST`` for state-changing actions are vulnerable to CSRF.\n\nSuppose ``example.com`` has upgraded its Log Out functionality so that it's a\n``<form>`` button that is requested via ``POST`` to the URL\n``example.com/logout``. Furthermore, the logout ``<form>`` includes this\nhidden field::\n\n    <input type=\"hidden\" name=\"confirm\" value=\"true\">\n\nThis ensures that a simple ``POST`` to the URL ``example.com/logout`` won't\nlog a user out; in order for a user to log out, the user must request\n``example.com/logout`` via ``POST`` *and* send the ``confirm`` ``POST``\nvariable with a value of ``'true'``.\n\nWell, despite the extra security, this arrangement can still be exploited by\nCSRF -- the malicious page just needs to do a little more work. Attackers can\ncreate an entire form targeting your site, hide it in an invisible ``<iframe>``,\nand then use JavaScript to submit that form automatically.\n\nPreventing CSRF\n---------------\n\nHow, then, can your site protect itself from this exploit? The first step is\nto make sure all ``GET`` requests are free of side effects. That way,\nif a malicious site includes one of your pages as an ``<iframe>``,\nit won't have a negative effect.\n\nThat leaves ``POST`` requests. The second step is to give each ``POST``\n``<form>`` a hidden field whose value is secret and is generated from the\nuser's session ID. Then, when processing the form on the server side, check for\nthat secret field and raise an error if it doesn't validate.\n\nThis is exactly what Django's CSRF prevention layer does, as explained in the\nsections that follow.\n\nUsing the CSRF Middleware\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe ``django.contrib.csrf`` package contains only one module: ``middleware.py``. This\nmodule contains a Django middleware class, ``CsrfMiddleware``, which implements\nthe CSRF protection.\n\nTo activate this CSRF protection, add ``'django.contrib.csrf.middleware.CsrfMiddleware'``\nto the ``MIDDLEWARE_CLASSES`` setting in your settings file. This middleware\nneeds to process the response *after* ``SessionMiddleware``, so\n``CsrfMiddleware`` must appear *before* ``SessionMiddleware`` in the list\n(because the response middleware is processed last-to-first). Also, it must\nprocess the response before the response gets compressed or otherwise mangled,\nso ``CsrfMiddleware`` must come after ``GZipMiddleware``. Once you've added\nthat to your ``MIDDLEWARE_CLASSES`` setting, you're done.  See the section\n\"Order of MIDDLEWARE_CLASSES\" in Chapter 15 for more explanation.\n\nIn case you're interested, here's how ``CsrfMiddleware`` works. It does these\ntwo things:\n\n1. It modifies outgoing requests by adding a hidden form field to all\n   ``POST`` forms, with the name ``csrfmiddlewaretoken`` and a value that\n   is a hash of the session ID plus a secret key. The middleware does *not*\n   modify the response if there's no session ID set, so the performance\n   penalty is negligible for requests that don't use sessions.\n\n2. On all incoming ``POST`` requests that have the session cookie set, it\n   checks that ``csrfmiddlewaretoken`` is present and correct. If it\n   isn't, the user will get a 403 ``HTTP`` error. The content of the 403\n   error page is the message \"Cross Site Request Forgery detected. Request\n   aborted.\"\n\nThis ensures that only forms originating from your Web site can be used to POST\ndata back.\n\nThis middleware deliberately targets only HTTP ``POST`` requests (and the\ncorresponding POST forms). As we explained, ``GET`` requests ought never\nto have side effects; it's your own responsibility to ensure this.\n\n``POST`` requests not accompanied by a session cookie are not\nprotected, but they don't *need* to be protected, because a malicious Web site\ncould make these kind of requests anyway.\n\nTo avoid altering non-HTML requests, the middleware checks the response's\n``Content-Type`` header before modifying it. Only pages that are served as\n``text/html`` or ``application/xml+xhtml`` are modified.\n\nLimitations of the CSRF Middleware\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n``CsrfMiddleware`` requires Django's session framework to work. (See Chapter 14\nfor more on sessions.) If you're using a custom session or authentication\nframework that manually manages session cookies, this middleware will not help\nyou.\n\nIf your application creates HTML pages and forms in some unusual way (e.g., if it\nsends fragments of HTML in JavaScript ``document.write`` statements), you\nmight bypass the filter that adds the hidden field to the form. In this case,\nthe form submission will always fail. (This happens because\n``CsrfMiddleware`` uses a regular expression to add the ``csrfmiddlewaretoken``\nfield to your HTML before the page is sent to the client, and the regular\nexpression sometimes cannot handle wacky HTML.) If you suspect this might be\nhappening, just view the source in your Web browser to see whether\n``csrfmiddlewaretoken`` was inserted into your ``<form>``.\n\nFor more CSRF information and examples, visit http://en.wikipedia.org/wiki/CSRF\n\nHumanizing Data\n===============\n\nThe package ``django.contrib.humanize`` holds a set of Django template filters\nuseful for adding a \"human touch\" to data. To activate these filters, add\n``'django.contrib.humanize'`` to your ``INSTALLED_APPS``. Once you've done\nthat, use ``{% load humanize %}`` in a template, and you'll have access to the\nfilters described in the following sections.\n\napnumber\n--------\n\nFor numbers 1 through 9, this filter returns the number spelled out. Otherwise,\nit returns the numeral. This follows Associated Press style.\n\nExamples:\n\n* 1 becomes \"one\".\n* 2 becomes \"two\".\n* 10 becomes \"10\".\n\nYou can pass in either an integer or a string representation of an integer.\n\nintcomma\n--------\n\nThis filter converts an integer to a string containing commas every three digits.\n\nExamples:\n\n* 4500 becomes \"4,500\".\n* 45000 becomes \"45,000\".\n* 450000 becomes \"450,000\".\n* 4500000 becomes \"4,500,000\".\n\nYou can pass in either an integer or a string representation of an integer.\n\nintword\n-------\n\nThis filter converts a large integer to a friendly text representation. It works best for\nnumbers over 1 million.\n\nExamples:\n\n* 1000000 becomes \"1.0 million\".\n* 1200000 becomes \"1.2 million\".\n* 1200000000 becomes \"1.2 billion\".\n\nValues up to 1 quadrillion (1,000,000,000,000,000) are supported.\n\nYou can pass in either an integer or a string representation of an integer.\n\nordinal\n-------\n\nThis filter converts an integer to its ordinal as a string.\n\nExamples:\n\n* 1 becomes \"1st\".\n* 2 becomes \"2nd\".\n* 3 becomes \"3rd\".\n* 254 becomes \"254th\".\n\nYou can pass in either an integer or a string representation of an integer.\n\nMarkup Filters\n==============\n\nThe package ``django.contrib.markup`` includes a handful of Django template\nfilters, each of which implements a common markup languages:\n\n* ``textile``: Implements Textile\n  (http://en.wikipedia.org/wiki/Textile_%28markup_language%29)\n\n* ``markdown``: Implements Markdown (http://en.wikipedia.org/wiki/Markdown)\n\n* ``restructuredtext``: Implements ReStructured Text\n  (http://en.wikipedia.org/wiki/ReStructuredText)\n\nIn each case, the filter expects formatted markup as a string and returns a\nstring representing the marked-up text. For example, the ``textile`` filter converts\ntext that is marked up in Textile format to HTML::\n\n    {% load markup %}\n    {{ object.content|textile }}\n\nTo activate these filters, add ``'django.contrib.markup'`` to your\n``INSTALLED_APPS`` setting. Once you've done that, use ``{% load markup %}`` in\na template, and you'll have access to these filters. For more documentation,\nread the source code in ``django/contrib/markup/templatetags/markup.py.``\n\nWhat's Next?\n============\n\nMany of these contributed frameworks (CSRF, the auth system, etc.) do their\nmagic by providing a piece of *middleware*. Middleware is code that runs before\nand/or after every request and can modify requests and responses at will, to\nextend the framework. In the `next chapter`_, we'll discuss Django's built-in\nmiddleware and explain how you can write your own.\n\n.. _next chapter: ../chapter17/\n"
  },
  {
    "path": "Python/DjangoBook/chapter17.rst",
    "content": "======================\nChapter 17: Middleware\n======================\n\nOn occasion, you'll need to run a piece of code on each and every request that\nDjango handles. This code might need to modify the request before the view\nhandles it, it might need to log information about the request for debugging\npurposes, and so forth.\n\nYou can do this with Django's *middleware* framework, which is a set of hooks\ninto Django's request/response processing. It's a light, low-level \"plug-in\"\nsystem capable of globally altering both Django's input and output.\n\nEach middleware component is responsible for doing some specific function. If\nyou're reading this book straight through, you've seen middleware a number of\ntimes already:\n\n* All of the session and user tools that we looked at in Chapter 14\n  are made possible by a few small pieces of middleware (more\n  specifically, the middleware makes ``request.session`` and\n  ``request.user`` available to you in views).\n\n* The sitewide cache discussed in Chapter 15 is actually just a piece\n  of middleware that bypasses the call to your view function if the\n  response for that view has already been cached.\n\n* The ``flatpages``, ``redirects``, and ``csrf`` applications from\n  Chapter 16 all do their magic through middleware components.\n\nThis chapter dives deeper into exactly what middleware is and how it works,\nand explains how you can write your own middleware.\n\nWhat's Middleware?\n==================\n\nLet's start with a very simple example.\n\nHigh-traffic sites often need to deploy Django behind a load-balancing proxy\n(see Chapter 12). This can cause a few small complications, one of which is\nthat every request's remote IP (``request.META[\"REMOTE_IP\"]``) will be that of\nthe load balancer, not the actual IP making the request. Load balancers deal\nwith this by setting a special header, ``X-Forwarded-For``, to the actual\nrequesting IP address.\n\nSo here's a small bit of middleware that lets sites running behind a proxy\nstill see the correct IP address in ``request.META[\"REMOTE_ADDR\"]``::\n\n    class SetRemoteAddrFromForwardedFor(object):\n        def process_request(self, request):\n            try:\n                real_ip = request.META['HTTP_X_FORWARDED_FOR']\n            except KeyError:\n                pass\n            else:\n                # HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs.\n                # Take just the first one.\n                real_ip = real_ip.split(\",\")[0]\n                request.META['REMOTE_ADDR'] = real_ip\n\n(Note: Although the HTTP header is called ``X-Forwarded-For``, Django makes\nit available as ``request.META['HTTP_X_FORWARDED_FOR']``. With the exception\nof ``content-length`` and ``content-type``, any HTTP headers in the request are\nconverted to ``request.META`` keys by converting all characters to uppercase,\nreplacing any hyphens with underscores and adding an ``HTTP_`` prefix to the\nname.)\n\nIf this middleware is installed (see the next section), every request's\n``X-Forwarded-For`` value will be automatically inserted into\n``request.META['REMOTE_ADDR']``. This means your Django applications don't need\nto be concerned with whether they're behind a load-balancing proxy or not; they\ncan simply access ``request.META['REMOTE_ADDR']``, and that will work whether\nor not a proxy is being used.\n\nIn fact, this is a common enough need that this piece of middleware is a\nbuilt-in part of Django. It lives in ``django.middleware.http``, and you can\nread a bit more about it later in this chapter.\n\nMiddleware Installation\n=======================\n\nIf you've read this book straight through, you've already seen a number of\nexamples of middleware installation; many of the examples in previous chapters\nhave required certain middleware. For completeness, here's how to install\nmiddleware.\n\nTo activate a middleware component, add it to the ``MIDDLEWARE_CLASSES`` tuple\nin your settings module. In ``MIDDLEWARE_CLASSES``, each middleware component\nis represented by a string: the full Python path to the middleware's class\nname. For example, here's the default ``MIDDLEWARE_CLASSES`` created by\n``django-admin.py startproject``::\n\n    MIDDLEWARE_CLASSES = (\n        'django.middleware.common.CommonMiddleware',\n        'django.contrib.sessions.middleware.SessionMiddleware',\n        'django.contrib.auth.middleware.AuthenticationMiddleware',\n    )\n\nA Django installation doesn't require any middleware -- ``MIDDLEWARE_CLASSES``\ncan be empty, if you'd like -- but we recommend that you activate\n``CommonMiddleware``, which we explain shortly.\n\nThe order is significant. On the request and view phases, Django applies\nmiddleware in the order given in ``MIDDLEWARE_CLASSES``, and on the response\nand exception phases, Django applies middleware in reverse order. That is,\nDjango treats ``MIDDLEWARE_CLASSES`` as a sort of \"wrapper\" around the view\nfunction: on the request it walks down the list to the view, and on the\nresponse it walks back up.\n\nMiddleware Methods\n==================\n\nNow that you know what middleware is and how to install it, let's take a look at\nall the available methods that middleware classes can define.\n\nInitializer: __init__(self)\n---------------------------\n\nUse ``__init__()`` to perform systemwide setup for a given middleware class.\n\nFor performance reasons, each activated middleware class is instantiated only\n*once* per server process. This means that ``__init__()`` is called only once\n-- at server startup -- not for individual requests.\n\nA common reason to implement an ``__init__()`` method is to check whether the\nmiddleware is indeed needed. If ``__init__()`` raises\n``django.core.exceptions.MiddlewareNotUsed``, then Django will remove the\nmiddleware from the middleware stack. You might use this feature to check for\nsome piece of software that the middleware class requires, or check whether\nthe server is running debug mode, or any other such environment situation.\n\nIf a middleware class defines an ``__init__()`` method, the method should take no\narguments beyond the standard ``self``.\n\nRequest Preprocessor: process_request(self, request)\n----------------------------------------------------\n\nThis method gets called as soon as the request has been received -- before\nDjango has parsed the URL to determine which view to execute. It gets passed\nthe ``HttpRequest`` object, which you may modify at will.\n\n``process_request()`` should return either ``None`` or an ``HttpResponse``\nobject.\n\n* If it returns ``None``, Django will continue processing this request,\n  executing any other middleware and then the appropriate view.\n\n* If it returns an ``HttpResponse`` object, Django won't bother calling\n  *any* other middleware (of any type) or the appropriate view. Django\n  will immediately return that ``HttpResponse``.\n\nView Preprocessor: process_view(self, request, view, args, kwargs)\n------------------------------------------------------------------\n\nThis method gets called after the request preprocessor is called and Django\nhas determined which view to execute, but before that view has actually been\nexecuted.\n\nThe arguments passed to this view are shown in Table 17-1.\n\n.. table:: Table 17-1. Arguments Passed to process_view()\n\n    ==============  ==========================================================\n    Argument        Explanation\n    ==============  ==========================================================\n    ``request``     The ``HttpRequest`` object.\n\n    ``view``        The Python function that Django will call to handle this\n                    request. This is the actual function object itself,\n                    not the name of the function as a string.\n\n    ``args``        The list of positional arguments that will be passed to\n                    the view, not including the ``request`` argument (which\n                    is always the first argument to a view).\n\n    ``kwargs``      The dictionary of keyword arguments that will be passed\n                    to the view.\n    ==============  ==========================================================\n\nJust like ``process_request()``, ``process_view()`` should return either\n``None`` or an ``HttpResponse`` object.\n\n* If it returns ``None``, Django will continue processing this request,\n  executing any other middleware and then the appropriate view.\n\n* If it returns an ``HttpResponse`` object, Django won't bother calling\n  *any* other middleware (of any type) or the appropriate view. Django\n  will immediately return that ``HttpResponse``.\n\nResponse Postprocessor: process_response(self, request, response)\n-----------------------------------------------------------------\n\nThis method gets called after the view function is called and the response is\ngenerated. Here, the processor can modify the content of a response. One\nobvious use case is content compression, such as gzipping of the request's\nHTML.\n\nThe parameters should be pretty self-explanatory: ``request`` is the request\nobject, and ``response`` is the response object returned from the view.\n\nUnlike the request and view preprocessors, which may return ``None``,\n``process_response()`` *must* return an ``HttpResponse`` object. That response\ncould be the original one passed into the function (possibly modified) or a\nbrand-new one.\n\nException Postprocessor: process_exception(self, request, exception)\n--------------------------------------------------------------------\n\nThis method gets called only if something goes wrong and a view raises an\nuncaught exception. You can use this hook to send error notifications, dump\npostmortem information to a log, or even try to recover from the error\nautomatically.\n\nThe parameters to this function are the same ``request`` object we've been\ndealing with all along, and ``exception``, which is the actual ``Exception``\nobject raised by the view function.\n\n``process_exception()`` should return a either ``None`` or an ``HttpResponse``\nobject.\n\n* If it returns ``None``, Django will continue processing this request\n  with the framework's built-in exception handling.\n\n* If it returns an ``HttpResponse`` object, Django will use that response\n  instead of the framework's built-in exception handling.\n\n.. note::\n\n    Django ships with a number of middleware classes (discussed in the following\n    section) that make good examples. Reading the code for them should give you\n    a good feel for the power of middleware.\n\n    You can also find a number of community-contributed examples on Django's\n    wiki: http://code.djangoproject.com/wiki/ContributedMiddleware\n\nBuilt-in Middleware\n===================\n\nDjango comes with some built-in middleware to deal with common problems, which we discuss\nin the sections that follow.\n\nAuthentication Support Middleware\n---------------------------------\n\nMiddleware class: ``django.contrib.auth.middleware.AuthenticationMiddleware``.\n\nThis middleware enables authentication support. It adds the ``request.user``\nattribute, representing the currently logged-in user, to every incoming\n``HttpRequest`` object.\n\nSee Chapter 14 for complete details.\n\n\"Common\" Middleware\n-------------------\n\nMiddleware class: ``django.middleware.common.CommonMiddleware``.\n\nThis middleware adds a few conveniences for perfectionists:\n\n* *Forbids access to user agents in the ``DISALLOWED_USER_AGENTS`` setting*:\n  If provided, this setting should be a list of compiled regular expression\n  objects that are matched against the user-agent header for each incoming\n  request. Here's an example snippet from a settings file::\n\n      import re\n\n      DISALLOWED_USER_AGENTS = (\n          re.compile(r'^OmniExplorer_Bot'),\n          re.compile(r'^Googlebot')\n      )\n\n  Note the ``import re``, because ``DISALLOWED_USER_AGENTS`` requires its\n  values to be compiled regexes (i.e., the output of ``re.compile()``).\n  The settings file is regular Python, so it's perfectly OK to include\n  Python ``import`` statements in it.\n\n* *Performs URL rewriting based on the ``APPEND_SLASH`` and ``PREPEND_WWW``\n  settings*: If ``APPEND_SLASH`` is ``True``, URLs that lack a trailing\n  slash will be redirected to the same URL with a trailing slash, unless\n  the last component in the path contains a period. So ``foo.com/bar`` is\n  redirected to ``foo.com/bar/``, but ``foo.com/bar/file.txt`` is passed\n  through unchanged.\n\n  If ``PREPEND_WWW`` is ``True``, URLs that lack a leading \"www.\" will be\n  redirected to the same URL with a leading \"www.\".\n\n  Both of these options are meant to normalize URLs. The philosophy is\n  that each URL should exist in one -- and only one -- place. Technically the\n  URL ``example.com/bar`` is distinct from ``example.com/bar/``, which in\n  turn is distinct from ``www.example.com/bar/``. A search-engine indexer\n  would treat these as separate URLs, which is detrimental to your site's\n  search-engine rankings, so it's a best practice to normalize URLs.\n\n* *Handles ETags based on the ``USE_ETAGS`` setting*: *ETags* are an HTTP-level\n  optimization for caching pages conditionally. If ``USE_ETAGS`` is\n  set to ``True``, Django will calculate an ETag for each request by\n  MD5-hashing the page content, and it will take care of sending ``Not\n  Modified`` responses, if appropriate.\n\n  Note there is also a conditional ``GET`` middleware, covered shortly, which\n  handles ETags and does a bit more.\n\nCompression Middleware\n----------------------\n\nMiddleware class: ``django.middleware.gzip.GZipMiddleware``.\n\nThis middleware automatically compresses content for browsers that understand gzip\ncompression (all modern browsers). This can greatly reduce the amount of bandwidth\na Web server consumes. The tradeoff is that it takes a bit of processing time to\ncompress pages.\n\nWe usually prefer speed over bandwidth, but if you prefer the reverse, just\nenable this middleware.\n\nConditional GET Middleware\n--------------------------\n\nMiddleware class: ``django.middleware.http.ConditionalGetMiddleware``.\n\nThis middleware provides support for conditional ``GET`` operations. If the response\nhas an ``Last-Modified`` or ``ETag`` or header, and the request has ``If-None-Match``\nor ``If-Modified-Since``, the response is replaced by an 304 (\"Not modified\")\nresponse. ``ETag`` support depends on on the ``USE_ETAGS`` setting and expects\nthe ``ETag`` response header to already be set. As discussed above, the ``ETag``\nheader is set by the Common middleware.\n\nIt also removes the content from any response to a ``HEAD`` request and sets the\n``Date`` and ``Content-Length`` response headers for all requests.\n\nReverse Proxy Support (X-Forwarded-For Middleware)\n--------------------------------------------------\n\nMiddleware class: ``django.middleware.http.SetRemoteAddrFromForwardedFor``.\n\nThis is the example we examined in the \"What's Middleware?\" section earlier. It\nsets ``request.META['REMOTE_ADDR']`` based on\n``request.META['HTTP_X_FORWARDED_FOR']``, if the latter is set. This is useful\nif you're sitting behind a reverse proxy that causes each request's\n``REMOTE_ADDR`` to be set to ``127.0.0.1``.\n\n.. admonition:: Danger!\n\n    This middleware does *not* validate ``HTTP_X_FORWARDED_FOR``.\n\n    If you're not behind a reverse proxy that sets ``HTTP_X_FORWARDED_FOR``\n    automatically, do not use this middleware. Anybody can spoof the value of\n    ``HTTP_X_FORWARDED_FOR``, and because this sets ``REMOTE_ADDR`` based on\n    ``HTTP_X_FORWARDED_FOR``, that means anybody can fake his IP address.\n\n    Only use this middleware when you can absolutely trust the value of\n    ``HTTP_X_FORWARDED_FOR``.\n\nSession Support Middleware\n--------------------------\n\nMiddleware class: ``django.contrib.sessions.middleware.SessionMiddleware``.\n\nThis middleware enables session support. See Chapter 14 for details.\n\nSitewide Cache Middleware\n-------------------------\n\nMiddleware classes: ``django.middleware.cache.UpdateCacheMiddleware`` and\n``django.middleware.cache.FetchFromCacheMiddleware``.\n\nThese middlewares work together to cache each Django-powered page. This was\ndiscussed in detail in Chapter 15.\n\nTransaction Middleware\n----------------------\n\nMiddleware class: ``django.middleware.transaction.TransactionMiddleware``.\n\nThis middleware binds a database ``COMMIT`` or ``ROLLBACK`` to the request/response\nphase. If a view function runs successfully, a ``COMMIT`` is issued. If the view\nraises an exception, a ``ROLLBACK`` is issued.\n\nThe order of this middleware in the stack is important. Middleware modules\nrunning outside of it run with commit-on-save -- the default Django behavior.\nMiddleware modules running inside it (coming later in the stack) will be under\nthe same transaction control as the view functions.\n\nSee Appendix B for more about information about database transactions.\n\nWhat's Next?\n============\n\nWeb developers and database-schema designers don't always have the luxury of\nstarting from scratch. In the `next chapter`_, we'll cover how to integrate with\nlegacy systems, such as database schemas you've inherited from the 1980s.\n\n.. _next chapter: ../chapter18/\n"
  },
  {
    "path": "Python/DjangoBook/chapter18.rst",
    "content": "==============================================================\nChapter 18: Integrating with Legacy Databases and Applications\n==============================================================\n\nDjango is best suited for so-called green-field development -- that is, starting\nprojects from scratch, as if you were constructing a building on a fresh field\nof green grass. But despite the fact that Django favors from-scratch projects,\nit's possible to integrate the framework into legacy databases and\napplications. This chapter explains a few integration strategies.\n\nIntegrating with a Legacy Database\n==================================\n\nDjango's database layer generates SQL schemas from Python code -- but with\na legacy database, you already have the SQL schemas. In such a case,\nyou'll need to create models for your existing database tables. For this\npurpose, Django comes with a tool that can generate model code by reading your\ndatabase table layouts. This tool is called ``inspectdb``, and you can call it\nby executing the command ``manage.py inspectdb``.\n\nUsing ``inspectdb``\n-------------------\n\nThe ``inspectdb`` utility introspects the database pointed to by your settings\nfile, determines a Django model representation for each of your tables, and\nprints the Python model code to standard output.\n\nHere's a walk-through of a typical legacy database integration process from\nscratch. The only assumptions are that Django is installed and that you have a\nlegacy database.\n\n1. Create a Django project by running\n   ``django-admin.py startproject mysite`` (where ``mysite`` is your\n   project's name). We'll use ``mysite`` as the project name in this\n   example.\n\n2. Edit the settings file in that project, ``mysite/settings.py``,\n   to tell Django what your database connection parameters are and what\n   the name of the database is. Specifically, provide the\n   ``DATABASE_NAME``, ``DATABASE_ENGINE``, ``DATABASE_USER``,\n   ``DATABASE_PASSWORD``, ``DATABASE_HOST``, and ``DATABASE_PORT`` settings.\n   (Note that some of these settings are optional. Refer to Chapter 5 for\n   more information.)\n\n3. Create a Django application within your project by running\n   ``python mysite/manage.py startapp myapp`` (where ``myapp`` is your\n   application's name). We'll use ``myapp`` as the application name here.\n\n4. Run the command ``python mysite/manage.py inspectdb``. This will\n   examine the tables in the ``DATABASE_NAME`` database and print the\n   generated model class for each table. Take a look at the output to get\n   an idea of what ``inspectdb`` can do.\n\n5. Save the output to the ``models.py`` file within your application by using\n   standard shell output redirection::\n\n       python mysite/manage.py inspectdb > mysite/myapp/models.py\n\n6. Edit the ``mysite/myapp/models.py`` file to clean up the generated\n   models and make any necessary customizations. We'll give\n   some hints for this in the next section.\n\nCleaning Up Generated Models\n----------------------------\n\nAs you might expect, the database introspection isn't perfect, and you'll need\nto do some light cleanup of the resulting model code. Here are a few pointers\nfor dealing with the generated models:\n\n1. Each database table is converted to a model class (i.e., there is a\n   one-to-one mapping between database tables and model classes). This means\n   that you'll need to refactor the models for any many-to-many join tables\n   into ``ManyToManyField`` objects.\n\n2. Each generated model has an attribute for every field, including\n   ``id`` primary key fields. However, recall that Django automatically\n   adds an ``id`` primary key field if a model doesn't have a primary key.\n   Thus, you'll want to remove any lines that look like this::\n\n       id = models.IntegerField(primary_key=True)\n\n   Not only are these lines redundant, but also they can cause problems if your\n   application will be adding *new* records to these tables.\n\n3. Each field's type (e.g., ``CharField``, ``DateField``) is determined by\n   looking at the database column type (e.g., ``VARCHAR``, ``DATE``). If\n   ``inspectdb`` cannot map a column's type to a model field type, it will\n   use ``TextField`` and will insert the Python comment\n   ``'This field type is a guess.'`` next to the field in the generated\n   model. Keep an eye out for that, and change the field type accordingly\n   if needed.\n\n   If a field in your database has no good Django equivalent, you can\n   safely leave it off. The Django model layer is not required to include\n   every field in your table(s).\n\n4. If a database column name is a Python reserved word (such as ``pass``,\n   ``class``, or ``for``), ``inspectdb`` will append ``'_field'`` to the\n   attribute name and set the ``db_column`` attribute to the real field\n   name (e.g., ``pass``, ``class``, or ``for``).\n\n   For example, if a table has an ``INT`` column called ``for``, the generated\n   model will have a field like this::\n\n       for_field = models.IntegerField(db_column='for')\n\n   ``inspectdb`` will insert the Python comment\n   ``'Field renamed because it was a Python reserved word.'`` next to the\n   field.\n\n5. If your database contains tables that refer to other tables (as most\n   databases do), you might need to rearrange the order of the generated\n   models so that models that refer to other models are ordered properly.\n   For example, if model ``Book`` has a ``ForeignKey`` to model ``Author``,\n   model ``Author`` should be defined before model ``Book``.  If you need\n   to create a relationship on a model that has not yet been defined, you\n   can use a string containing the name of the model, rather than the model\n   object itself.\n\n6. ``inspectdb`` detects primary keys for PostgreSQL, MySQL, and SQLite.\n   That is, it inserts ``primary_key=True`` where appropriate. For other\n   databases, you'll need to insert ``primary_key=True`` for at least one\n   field in each model, because Django models are required to have a\n   ``primary_key=True`` field.\n\n7. Foreign-key detection only works with PostgreSQL and with certain types\n   of MySQL tables. In other cases, foreign-key fields will be generated as\n   ``IntegerField``s, assuming the foreign-key column was an ``INT``\n   column.\n\nIntegrating with an Authentication System\n=========================================\n\nIt's possible to integrate Django with an existing authentication system --\nanother source of usernames and passwords or authentication methods.\n\nFor example, your company may already have an LDAP setup that stores a username\nand password for every employee. It would be a hassle for both the network\nadministrator and the users themselves if users had separate accounts in LDAP\nand the Django-based applications.\n\nTo handle situations like this, the Django authentication system lets you\nplug in other authentication sources. You can override Django's default\ndatabase-based scheme, or you can use the default system in tandem with other\nsystems.\n\nSpecifying Authentication Backends\n----------------------------------\n\nBehind the scenes, Django maintains a list of \"authentication backends\" that it\nchecks for authentication. When somebody calls\n``django.contrib.auth.authenticate()`` (as described in Chapter 14), Django\ntries authenticating across all of its authentication backends. If the first\nauthentication method fails, Django tries the second one, and so on, until all\nbackends have been attempted.\n\nThe list of authentication backends to use is specified in the\n``AUTHENTICATION_BACKENDS`` setting. This should be a tuple of Python path\nnames that point to Python classes that know how to authenticate. These classes\ncan be anywhere on your Python path.\n\nBy default, ``AUTHENTICATION_BACKENDS`` is set to the following::\n\n    ('django.contrib.auth.backends.ModelBackend',)\n\nThat's the basic authentication scheme that checks the Django users database.\n\nThe order of ``AUTHENTICATION_BACKENDS`` matters, so if the same username and\npassword are valid in multiple backends, Django will stop processing at the\nfirst positive match.\n\nWriting an Authentication Backend\n---------------------------------\n\nAn authentication backend is a class that implements two methods:\n``get_user(id)`` and ``authenticate(**credentials)``.\n\nThe ``get_user`` method takes an ``id`` -- which could be a username, database\nID, or whatever -- and returns a ``User`` object.\n\nThe  ``authenticate`` method takes credentials as keyword arguments. Most of\nthe time it looks like this::\n\n    class MyBackend(object):\n        def authenticate(self, username=None, password=None):\n            # Check the username/password and return a User.\n\nBut it could also authenticate a token, like so::\n\n    class MyBackend(object):\n        def authenticate(self, token=None):\n            # Check the token and return a User.\n\nEither way, ``authenticate`` should check the credentials it gets, and it\nshould return a ``User`` object that matches those credentials, if the\ncredentials are valid. If they're not valid, it should return ``None``.\n\nThe Django admin system is tightly coupled to Django's own database-backed\n``User`` object described in Chapter 14. The best way to deal with this is to\ncreate a Django ``User`` object for each user that exists for your backend\n(e.g., in your LDAP directory, your external SQL database, etc.). Either you can\nwrite a script to do this in advance or your ``authenticate`` method can do it\nthe first time a user logs in.\n\nHere's an example backend that authenticates against a username and password\nvariable defined in your ``settings.py`` file and creates a Django ``User``\nobject the first time a user authenticates::\n\n    from django.conf import settings\n    from django.contrib.auth.models import User, check_password\n\n    class SettingsBackend(object):\n        \"\"\"\n        Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.\n\n        Use the login name, and a hash of the password. For example:\n\n        ADMIN_LOGIN = 'admin'\n        ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'\n        \"\"\"\n        def authenticate(self, username=None, password=None):\n            login_valid = (settings.ADMIN_LOGIN == username)\n            pwd_valid = check_password(password, settings.ADMIN_PASSWORD)\n            if login_valid and pwd_valid:\n                try:\n                    user = User.objects.get(username=username)\n                except User.DoesNotExist:\n                    # Create a new user. Note that we can set password\n                    # to anything, because it won't be checked; the password\n                    # from settings.py will.\n                    user = User(username=username, password='get from settings.py')\n                    user.is_staff = True\n                    user.is_superuser = True\n                    user.save()\n                return user\n            return None\n\n        def get_user(self, user_id):\n            try:\n                return User.objects.get(pk=user_id)\n            except User.DoesNotExist:\n                return None\n\nFor more on authentication backends, see the official Django documentation.\n\nIntegrating with Legacy Web Applications\n========================================\n\nIt's possible to run a Django application on the same Web server as an\napplication powered by another technology. The most straightforward way of\ndoing this is to use Apache's configuration file, ``httpd.conf``, to delegate\ndifferent URL patterns to different technologies. (Note that Chapter 12 covers\nDjango deployment on Apache/mod_python, so it might be worth reading that\nchapter first before attempting this integration.)\n\nThe key is that Django will be activated for a particular URL pattern only if\nyour ``httpd.conf`` file says so. The default deployment explained in Chapter\n12 assumes you want Django to power every page on a particular domain::\n\n    <Location \"/\">\n        SetHandler python-program\n        PythonHandler django.core.handlers.modpython\n        SetEnv DJANGO_SETTINGS_MODULE mysite.settings\n        PythonDebug On\n    </Location>\n\nHere, the ``<Location \"/\">`` line means \"handle every URL, starting at the\nroot,\" with Django.\n\nIt's perfectly fine to limit this ``<Location>`` directive to a certain\ndirectory tree. For example, say you have a legacy PHP application that powers\nmost pages on a domain and you want to install a Django admin site at\n``/admin/`` without disrupting the PHP code. To do this, just set the\n``<Location>`` directive to ``/admin/``::\n\n    <Location \"/admin/\">\n        SetHandler python-program\n        PythonHandler django.core.handlers.modpython\n        SetEnv DJANGO_SETTINGS_MODULE mysite.settings\n        PythonDebug On\n    </Location>\n\nWith this in place, only the URLs that start with ``/admin/`` will activate\nDjango. Any other page will use whatever infrastructure already existed.\n\nNote that attaching Django to a qualified URL (such as ``/admin/`` in this\nsection's example) does not affect the Django URL parsing. Django works with the\nabsolute URL (e.g., ``/admin/people/person/add/``), not a \"stripped\" version of\nthe URL (e.g., ``/people/person/add/``). This means that your root URLconf\nshould include the leading ``/admin/``.\n\nWhat's Next?\n============\n\nIf you're a native English speaker, you might not have noticed one of the\ncoolest features of Django's admin site: it's available in more than 50\ndifferent languages! This is made possible by Django's internationalization\nframework (and the hard work of Django's volunteer translators). The\n`next chapter`_ explains how to use this framework to provide localized Django\nsites.\n\n.. _next chapter: ../chapter19/\n"
  },
  {
    "path": "Python/DjangoBook/chapter19.rst",
    "content": "================================\nChapter 19: Internationalization\n================================\n\nDjango was originally developed right in the middle of the United States --\nquite literally, as Lawrence, Kansas, is less than 40 miles from the\ngeographic center of the continental United States. Like most open source\nprojects, though, Django's community grew to include people from all over the\nglobe. As Django's community became increasingly diverse,\n*internationalization* and *localization* became increasingly important.\nBecause many developers have at best a fuzzy understanding of these terms,\nwe'll define them briefly.\n\n*Internationalization* refers to the process of designing programs for the\npotential use of any locale. This includes marking text (such as UI elements and\nerror messages) for future translation, abstracting the display of dates and\ntimes so that different local standards may be observed, providing support for\ndiffering time zones, and generally making sure that the code contains no\nassumptions about the location of its users. You'll often see\n\"internationalization\" abbreviated *I18N*. (The \"18\" refers to the number\nof letters omitted between the initial \"I\" and the terminal \"N.\")\n\n*Localization* refers to the process of actually translating an\ninternationalized program for use in a particular locale. You'll sometimes see\n\"localization\" abbreviated as *L10N*.\n\nDjango itself is fully internationalized; all strings are marked for\ntranslation, and settings control the display of locale-dependent values like\ndates and times. Django also ships with more than 50 different localization\nfiles. If you're not a native English speaker, there's a good chance that\nDjango is already translated into your primary language.\n\nThe same internationalization framework used for these localizations is\navailable for you to use in your own code and templates.\n\nTo use this framework, you'll need to add a minimal number of hooks to your\nPython code and templates. These hooks are called *translation strings*. They\ntell Django, \"This text should be translated into the end user's language, if a\ntranslation for this text is available in that language.\"\n\nDjango takes care of using these hooks to translate Web applications, on the\nfly, according to users' language preferences.\n\nEssentially, Django does two things:\n\n* It lets developers and template authors specify which parts of their\n  applications should be translatable.\n\n* It uses that information to translate Web applications for particular\n  users according to their language preferences.\n\n.. note::\n\n    Django's translation machinery uses GNU ``gettext``\n    (http://www.gnu.org/software/gettext/) via the standard ``gettext`` module\n    that comes with Python.\n\n.. admonition:: If You Don't Need Internationalization:\n\n    Django's internationalization hooks are enabled by default, which incurs a\n    small bit of overhead. If you don't use internationalization, you should\n    set ``USE_I18N = False`` in your settings file. If ``USE_I18N`` is set to\n    ``False``, then Django will make some optimizations so as not to load the\n    internationalization machinery.\n\n    You'll probably also want to remove\n    ``'django.core.context_processors.i18n'`` from your\n    ``TEMPLATE_CONTEXT_PROCESSORS`` setting.\n\nThe three steps for internationalizing your Django application are:\n\n1. Embed translation strings in your Python code and templates.\n\n2. Get translations for those strings, in whichever languages you want to\n   support.\n\n3. Activate the locale middleware in your Django settings.\n\nWe'll cover each one of these steps in detail.\n\n1. How to Specify Translation Strings\n=====================================\n\nTranslation strings specify \"This text should be translated.\" These strings can\nappear in your Python code and templates. It's your responsibility to mark\ntranslatable strings; the system can only translate strings it knows about.\n\nIn Python Code\n--------------\n\nStandard Translation\n~~~~~~~~~~~~~~~~~~~~\n\nSpecify a translation string by using the function ``ugettext()``. It's\nconvention to import this as a shorter alias, ``_``, to save typing.\n\nIn this example, the text ``\"Welcome to my site.\"`` is marked as a translation\nstring::\n\n    from django.utils.translation import ugettext as _\n\n    def my_view(request):\n        output = _(\"Welcome to my site.\")\n        return HttpResponse(output)\n\nObviously, you could code this without using the alias. This example is\nidentical to the previous one::\n\n    from django.utils.translation import ugettext\n\n    def my_view(request):\n        output = ugettext(\"Welcome to my site.\")\n        return HttpResponse(output)\n\nTranslation works on computed values. This example is identical to the previous\ntwo::\n\n    def my_view(request):\n        words = ['Welcome', 'to', 'my', 'site.']\n        output = _(' '.join(words))\n        return HttpResponse(output)\n\nTranslation works on variables. Again, here's an identical example::\n\n    def my_view(request):\n        sentence = 'Welcome to my site.'\n        output = _(sentence)\n        return HttpResponse(output)\n\n(The caveat with using variables or computed values, as in the previous two\nexamples, is that Django's translation-string-detecting utility,\n``django-admin.py makemessages``, won't be able to find these strings. More on\n``makemessages`` later.)\n\nThe strings you pass to ``_()`` or ``ugettext()`` can take placeholders,\nspecified with Python's standard named-string interpolation syntax. Example::\n\n    def my_view(request, m, d):\n        output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d}\n        return HttpResponse(output)\n\nThis technique lets language-specific translations reorder the placeholder\ntext. For example, an English translation may be ``\"Today is November 26.\"``,\nwhile a Spanish translation may be ``\"Hoy es 26 de Noviembre.\"`` -- with the\nplaceholders (the month and the day) with their positions swapped.\n\nFor this reason, you should use named-string interpolation (e.g., ``%(day)s``)\ninstead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you\nhave more than a single parameter. If you used positional interpolation,\ntranslations wouldn't be able to reorder placeholder text.\n\nMarking Strings as No-Op\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nUse the function ``django.utils.translation.ugettext_noop()`` to mark a string\nas a translation string without translating it. The string is later translated\nfrom a variable.\n\nUse this if you have constant strings that should be stored in the source\nlanguage because they are exchanged over systems or users -- such as strings in\na database -- but should be translated at the last possible point in time, such\nas when the string is presented to the user.\n\nLazy Translation\n~~~~~~~~~~~~~~~~\n\nUse the function ``django.utils.translation.ugettext_lazy()`` to translate\nstrings lazily -- when the value is accessed rather than when the\n``ugettext_lazy()`` function is called.\n\nFor example, to translate a model's ``help_text``, do the following::\n\n    from django.utils.translation import ugettext_lazy\n\n    class MyThing(models.Model):\n        name = models.CharField(help_text=ugettext_lazy('This is the help text'))\n\nIn this example, ``ugettext_lazy()`` stores a lazy reference to the string --\nnot the actual translation. The translation itself will be done when the string\nis used in a string context, such as template rendering on the Django admin\nsite.\n\nThe result of a ``ugettext_lazy()`` call can be used wherever you would use a\nunicode string (an object with type ``unicode``) in Python. If you try to use\nit where a bytestring (a ``str`` object) is expected, things will not work as\nexpected, since a ``ugettext_lazy()`` object doesn't know how to convert\nitself to a bytestring.  You can't use a unicode string inside a bytestring,\neither, so this is consistent with normal Python behavior. For example::\n\n    # This is fine: putting a unicode proxy into a unicode string.\n    u\"Hello %s\" % ugettext_lazy(\"people\")\n\n    # This will not work, since you cannot insert a unicode object\n    # into a bytestring (nor can you insert our unicode proxy there)\n    \"Hello %s\" % ugettext_lazy(\"people\")\n\nIf you ever see output that looks like ``\"hello\n<django.utils.functional...>\"``, you have tried to insert the result of\n``ugettext_lazy()`` into a bytestring. That's a bug in your code.\n\nIf you don't like the verbose name ``ugettext_lazy``, you can just alias it as\n``_`` (underscore), like so::\n\n    from django.utils.translation import ugettext_lazy as _\n\n    class MyThing(models.Model):\n        name = models.CharField(help_text=_('This is the help text'))\n\nAlways use lazy translations in Django models. Field names and table names\nshould be marked for translation (otherwise, they won't be translated in the\nadmin interface). This means writing explicit ``verbose_name`` and\n``verbose_name_plural`` options in the ``Meta`` class, though, rather than\nrelying on Django's default determination of ``verbose_name`` and\n``verbose_name_plural`` by looking at the model's class name::\n\n    from django.utils.translation import ugettext_lazy as _\n\n    class MyThing(models.Model):\n        name = models.CharField(_('name'), help_text=_('This is the help text'))\n        class Meta:\n            verbose_name = _('my thing')\n            verbose_name_plural = _('mythings')\n\nPluralization\n~~~~~~~~~~~~~\n\nUse the function ``django.utils.translation.ungettext()`` to specify pluralized\nmessages. Example::\n\n    from django.utils.translation import ungettext\n\n    def hello_world(request, count):\n        page = ungettext('there is %(count)d object',\n            'there are %(count)d objects', count) % {\n                'count': count,\n            }\n        return HttpResponse(page)\n\n``ungettext`` takes three arguments: the singular translation string, the plural\ntranslation string and the number of objects (which is passed to the\ntranslation languages as the ``count`` variable).\n\nIn Template Code\n----------------\n\nTranslation in Django templates uses two template tags and a slightly different\nsyntax than in Python code. To give your template access to these tags, put\n``{% load i18n %}`` toward the top of your template.\n\nThe ``{% trans %}`` template tag translates either a constant string\n(enclosed in single or double quotes) or variable content::\n\n    <title>{% trans \"This is the title.\" %}</title>\n    <title>{% trans myvar %}</title>\n\nIf the ``noop`` option is present, variable lookup still takes place but the\ntranslation is skipped. This is useful when \"stubbing out\" content that will\nrequire translation in the future::\n\n    <title>{% trans \"myvar\" noop %}</title>\n\nIt's not possible to mix a template variable inside a string within ``{% trans\n%}``. If your translations require strings with variables (placeholders), use\n``{% blocktrans %}``::\n\n    {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}\n\nTo translate a template expression -- say, using template filters -- you need\nto bind the expression to a local variable for use within the translation\nblock::\n\n    {% blocktrans with value|filter as myvar %}\n    This will have {{ myvar }} inside.\n    {% endblocktrans %}\n\nIf you need to bind more than one expression inside a ``blocktrans`` tag,\nseparate the pieces with ``and``::\n\n    {% blocktrans with book|title as book_t and author|title as author_t %}\n    This is {{ book_t }} by {{ author_t }}\n    {% endblocktrans %}\n\nTo pluralize, specify both the singular and plural forms with the\n``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and\n``{% endblocktrans %}``. Example::\n\n    {% blocktrans count list|length as counter %}\n    There is only one {{ name }} object.\n    {% plural %}\n    There are {{ counter }} {{ name }} objects.\n    {% endblocktrans %}\n\nInternally, all block and inline translations use the appropriate\n``ugettext`` / ``ungettext`` call.\n\nEach ``RequestContext`` has access to three translation-specific variables:\n\n* ``LANGUAGES`` is a list of tuples in which the first element is the\n  language code and the second is the language name (translated into the\n  currently active locale).\n\n* ``LANGUAGE_CODE`` is the current user's preferred language, as a string.\n  Example: ``en-us``. (See \"How Django discovers language preference,\"\n  below.)\n\n* ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a\n  right-to-left language, e.g.: Hebrew, Arabic. If False it's a\n  left-to-right language, e.g.: English, French, German etc.\n\nIf you don't use the ``RequestContext`` extension, you can get those values with\nthree tags::\n\n    {% get_current_language as LANGUAGE_CODE %}\n    {% get_available_languages as LANGUAGES %}\n    {% get_current_language_bidi as LANGUAGE_BIDI %}\n\nThese tags also require a ``{% load i18n %}``.\n\nTranslation hooks are also available within any template block tag that accepts\nconstant strings. In those cases, just use ``_()`` syntax to specify a\ntranslation string::\n\n    {% some_special_tag _(\"Page not found\") value|yesno:_(\"yes,no\") %}\n\nIn this case, both the tag and the filter will see the already-translated\nstring, so they don't need to be aware of translations.\n\n.. note::\n    In this example, the translation infrastructure will be passed the string\n    ``\"yes,no\"``, not the individual strings ``\"yes\"`` and ``\"no\"``. The\n    translated string will need to contain the comma so that the filter\n    parsing code knows how to split up the arguments. For example, a German\n    translator might translate the string ``\"yes,no\"`` as ``\"ja,nein\"``\n    (keeping the comma intact).\n\nWorking With Lazy Translation Objects\n-------------------------------------\n\nUsing ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models\nand utility functions is a common operation. When you're working with these\nobjects elsewhere in your code, you should ensure that you don't accidentally\nconvert them to strings, because they should be converted as late as possible\n(so that the correct locale is in effect). This necessitates the use of a\ncouple of helper functions.\n\nJoining Strings: string_concat()\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nStandard Python string joins (``''.join([...])``) will not work on lists\ncontaining lazy translation objects. Instead, you can use\n``django.utils.translation.string_concat()``, which creates a lazy object that\nconcatenates its contents *and* converts them to strings only when the result\nis included in a string. For example::\n\n    from django.utils.translation import string_concat\n    # ...\n    name = ugettext_lazy(u'John Lennon')\n    instrument = ugettext_lazy(u'guitar')\n    result = string_concat([name, ': ', instrument])\n\nIn this case, the lazy translations in ``result`` will only be converted to\nstrings when ``result`` itself is used in a string (usually at template\nrendering time).\n\nThe allow_lazy() Decorator\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDjango offers many utility functions (particularly in ``django.utils``) that\ntake a string as their first argument and do something to that string. These\nfunctions are used by template filters as well as directly in other code.\n\nIf you write your own similar functions and deal with translations, you'll\nface the problem of what to do when the first argument is a lazy translation\nobject. You don't want to convert it to a string immediately, because you might\nbe using this function outside of a view (and hence the current thread's locale\nsetting will not be correct).\n\nFor cases like this, use the ``django.utils.functional.allow_lazy()``\ndecorator. It modifies the function so that *if* it's called with a lazy\ntranslation as the first argument, the function evaluation is delayed until it\nneeds to be converted to a string.\n\nFor example::\n\n    from django.utils.functional import allow_lazy\n\n    def fancy_utility_function(s, ...):\n        # Do some conversion on string 's'\n        # ...\n    fancy_utility_function = allow_lazy(fancy_utility_function, unicode)\n\nThe ``allow_lazy()`` decorator takes, in addition to the function to decorate,\na number of extra arguments (``*args``) specifying the type(s) that the\noriginal function can return. Usually, it's enough to include ``unicode`` here\nand ensure that your function returns only Unicode strings.\n\nUsing this decorator means you can write your function and assume that the\ninput is a proper string, then add support for lazy translation objects at the\nend.\n\n2. How to Create Language Files\n===============================\n\nOnce you've tagged your strings for later translation, you need to write (or\nobtain) the language translations themselves. Here's how that works.\n\n.. admonition:: Locale restrictions\n\n    Django does not support localizing your application into a locale for\n    which Django itself has not been translated. In this case, it will ignore\n    your translation files. If you were to try this and Django supported it,\n    you would inevitably see a mixture of translated strings (from your\n    application) and English strings (from Django itself). If you want to\n    support a locale for your application that is not already part of\n    Django, you'll need to make at least a minimal translation of the Django\n    core.\n\nMessage Files\n-------------\n\nThe first step is to create a *message file* for a new language. A message\nfile is a plain-text file, representing a single language, that contains all\navailable translation strings and how they should be represented in the given\nlanguage. Message files have a ``.po`` file extension.\n\nDjango comes with a tool, ``django-admin.py makemessages``, that automates the\ncreation and upkeep of these files. To create or update a message file, run\nthis command::\n\n    django-admin.py makemessages -l de\n\n...where ``de`` is the language code for the message file you want to create.\nThe language code, in this case, is in locale format. For example, it's\n``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian German.\n\nThe script should be run from one of three places:\n\n* The root directory of your Django project.\n* The root directory of your Django app.\n* The root ``django`` directory (not a Subversion checkout, but the one\n  that is linked-to via ``$PYTHONPATH`` or is located somewhere on that\n  path). This is only relevant when you are creating a translation for\n  Django itself.\n\nThis script runs over your project source tree or your application source tree and\npulls out all strings marked for translation. It creates (or updates) a message\nfile in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` example, the\nfile will be ``locale/de/LC_MESSAGES/django.po``.\n\nBy default ``django-admin.py makemessages`` examines every file that has the\n``.html`` file extension. In case you want to override that default, use the\n``--extension`` or ``-e`` option to specify the file extensions to examine::\n\n    django-admin.py makemessages -l de -e txt\n\nSeparate multiple extensions with commas and/or use ``-e`` or ``--extension``\nmultiple times::\n\n    django-admin.py makemessages -l de -e html,txt -e xml\n\nWhen creating JavaScript translation catalogs (which we'll cover later in this\nchapter,) you need to use the special 'djangojs' domain, **not** ``-e js``.\n\n.. admonition:: No gettext?\n\n    If you don't have the ``gettext`` utilities installed, ``django-admin.py\n    makemessages`` will create empty files. If that's the case, either install\n    the ``gettext`` utilities or just copy the English message file\n    (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting\n    point; it's just an empty translation file.\n\n.. admonition:: Working on Windows?\n\n   If you're using Windows and need to install the GNU gettext utilities so\n   ``django-admin makemessages`` works, see the \"gettext on Windows\" section\n   below for more information.\n\nThe format of ``.po`` files is straightforward. Each ``.po`` file contains a\nsmall bit of metadata, such as the translation maintainer's contact\ninformation, but the bulk of the file is a list of *messages* -- simple\nmappings between translation strings and the actual translated text for the\nparticular language.\n\nFor example, if your Django app contained a translation string for the text\n``\"Welcome to my site.\"``, like so::\n\n    _(\"Welcome to my site.\")\n\n...then ``django-admin.py makemessages`` will have created a ``.po`` file\ncontaining the following snippet -- a message::\n\n    #: path/to/python/module.py:23\n    msgid \"Welcome to my site.\"\n    msgstr \"\"\n\nA quick explanation:\n\n* ``msgid`` is the translation string, which appears in the source. Don't\n  change it.\n* ``msgstr`` is where you put the language-specific translation. It starts\n  out empty, so it's your responsibility to change it. Make sure you keep\n  the quotes around your translation.\n* As a convenience, each message includes, in the form of a comment line\n  prefixed with ``#`` and located above the ``msgid`` line, the filename and\n  line number from which the translation string was gleaned.\n\nLong messages are a special case. There, the first string directly after the\n``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be\nwritten over the next few lines as one string per line. Those strings are\ndirectly concatenated. Don't forget trailing spaces within the strings;\notherwise, they'll be tacked together without whitespace!\n\nTo reexamine all source code and templates for new translation strings and\nupdate all message files for *all* languages, run this::\n\n    django-admin.py makemessages -a\n\nCompiling Message Files\n-----------------------\n\nAfter you create your message file -- and each time you make changes to it --\nyou'll need to compile it into a more efficient form, for use by ``gettext``.\nDo this with the ``django-admin.py compilemessages`` utility.\n\nThis tool runs over all available ``.po`` files and creates ``.mo`` files, which\nare binary files optimized for use by ``gettext``. In the same directory from\nwhich you ran ``django-admin.py makemessages``, run ``django-admin.py\ncompilemessages`` like this::\n\n   django-admin.py compilemessages\n\nThat's it. Your translations are ready for use.\n\n3. How Django Discovers Language Preference\n===========================================\n\nOnce you've prepared your translations -- or, if you just want to use the\ntranslations that come with Django -- you'll just need to activate translation\nfor your app.\n\nBehind the scenes, Django has a very flexible model of deciding which language\nshould be used -- installation-wide, for a particular user, or both.\n\nTo set an installation-wide language preference, set ``LANGUAGE_CODE``.\nDjango uses this language as the default translation -- the final attempt if no\nother translator finds a translation.\n\nIf all you want to do is run Django with your native language, and a language\nfile is available for your language, all you need to do is set\n``LANGUAGE_CODE``.\n\nIf you want to let each individual user specify which language he or she\nprefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language\nselection based on data from the request. It customizes content for each user.\n\nTo use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'``\nto your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you\nshould follow these guidelines:\n\n* Make sure it's one of the first middlewares installed.\n* It should come after ``SessionMiddleware``, because ``LocaleMiddleware``\n  makes use of session data.\n* If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it.\n\nFor example, your ``MIDDLEWARE_CLASSES`` might look like this::\n\n    MIDDLEWARE_CLASSES = (\n       'django.contrib.sessions.middleware.SessionMiddleware',\n       'django.middleware.locale.LocaleMiddleware',\n       'django.middleware.common.CommonMiddleware',\n    )\n\n(For more on middleware, see Chapter 17.)\n\n``LocaleMiddleware`` tries to determine the user's language preference by\nfollowing this algorithm:\n\n* First, it looks for a ``django_language`` key in the current user's\n  session.\n\n* Failing that, it looks for a cookie.\n\n* Failing that, it looks at the ``Accept-Language`` HTTP header. This\n  header is sent by your browser and tells the server which language(s) you\n  prefer, in order by priority. Django tries each language in the header\n  until it finds one with available translations.\n\n* Failing that, it uses the global ``LANGUAGE_CODE`` setting.\n\nNotes:\n\n* In each of these places, the language preference is expected to be in the\n  standard language format, as a string. For example, Brazilian Portuguese\n  is ``pt-br``.\n\n* If a base language is available but the sublanguage specified is not,\n  Django uses the base language. For example, if a user specifies ``de-at``\n  (Austrian German) but Django only has ``de`` available, Django uses\n  ``de``.\n\n* Only languages listed in the ``LANGUAGES`` setting can be selected.\n  If you want to restrict the language selection to a subset of provided\n  languages (because your application doesn't provide all those languages),\n  set ``LANGUAGES`` to a list of languages. For example::\n\n      LANGUAGES = (\n        ('de', _('German')),\n        ('en', _('English')),\n      )\n\n  This example restricts languages that are available for automatic\n  selection to German and English (and any sublanguage, like ``de-ch`` or\n  ``en-us``).\n\n* If you define a custom ``LANGUAGES`` setting, as explained in the\n  previous bullet, it's OK to mark the languages as translation strings\n  -- but use a \"dummy\" ``ugettext()`` function, not the one in\n  ``django.utils.translation``. You should *never* import\n  ``django.utils.translation`` from within your settings file, because that\n  module in itself depends on the settings, and that would cause a circular\n  import.\n\n  The solution is to use a \"dummy\" ``ugettext()`` function. Here's a sample\n  settings file::\n\n      ugettext = lambda s: s\n\n      LANGUAGES = (\n          ('de', ugettext('German')),\n          ('en', ugettext('English')),\n      )\n\n  With this arrangement, ``django-admin.py makemessages`` will still find\n  and mark these strings for translation, but the translation won't happen\n  at runtime -- so you'll have to remember to wrap the languages in the\n  *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime.\n\n* The ``LocaleMiddleware`` can only select languages for which there is a\n  Django-provided base translation. If you want to provide translations\n  for your application that aren't already in the set of translations\n  in Django's source tree, you'll want to provide at least basic\n  translations for that language. For example, Django uses technical\n  message IDs to translate date formats and time formats -- so you will\n  need at least those translations for the system to work correctly.\n\n  A good starting point is to copy the English ``.po`` file and to\n  translate at least the technical messages -- maybe the validation\n  messages, too.\n\n  Technical message IDs are easily recognized; they're all upper case. You\n  don't translate the message ID as with other messages, you provide the\n  correct local variant on the provided English value. For example, with\n  ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), this would\n  be the format string that you want to use in your language. The format\n  is identical to the format strings used by the ``now`` template tag.\n\nOnce ``LocaleMiddleware`` determines the user's preference, it makes this\npreference available as ``request.LANGUAGE_CODE`` for each\n``HttpRequest``. Feel free to read this value in your view\ncode. Here's a simple example::\n\n    def hello_world(request):\n        if request.LANGUAGE_CODE == 'de-at':\n            return HttpResponse(\"You prefer to read Austrian German.\")\n        else:\n            return HttpResponse(\"You prefer to read another language.\")\n\nNote that, with static (middleware-less) translation, the language is in\n``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's\nin ``request.LANGUAGE_CODE``.\n\nUsing Translations in Your Own Projects\n=======================================\n\nDjango looks for translations by following this algorithm:\n\n* First, it looks for a ``locale`` directory in the application directory\n  of the view that's being called. If it finds a translation for the\n  selected language, the translation will be installed.\n* Next, it looks for a ``locale`` directory in the project directory. If it\n  finds a translation, the translation will be installed.\n* Finally, it checks the Django-provided base translation in\n  ``django/conf/locale``.\n\nThis way, you can write applications that include their own translations, and\nyou can override base translations in your project path. Or, you can just build\na big project out of several apps and put all translations into one big project\nmessage file. The choice is yours.\n\nAll message file repositories are structured the same way. They are:\n\n* ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``\n* ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``\n* All paths listed in ``LOCALE_PATHS`` in your settings file are\n  searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``\n* ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``\n\nTo create message files, you use the same ``django-admin.py makemessages``\ntool as with the Django message files. You only need to be in the right place\n-- in the directory where either the ``conf/locale`` (in case of the source\ntree) or the ``locale/`` (in case of app messages or project messages)\ndirectory are located. And you use the same ``django-admin.py compilemessages``\nto produce the binary ``django.mo`` files that are used by ``gettext``.\n\nYou can also run ``django-admin.py compilemessages --settings=path.to.settings``\nto make the compiler process all the directories in your ``LOCALE_PATHS``\nsetting.\n\nApplication message files are a bit complicated to discover -- they need the\n``LocaleMiddleware``. If you don't use the middleware, only the Django message\nfiles and project message files will be processed.\n\nFinally, you should give some thought to the structure of your translation\nfiles. If your applications need to be delivered to other users and will\nbe used in other projects, you might want to use app-specific translations.\nBut using app-specific translations and project translations could produce\nweird problems with ``makemessages``: ``makemessages`` will traverse all\ndirectories below the current path and so might put message IDs into the\nproject message file that are already in application message files.\n\nThe easiest way out is to store applications that are not part of the project\n(and so carry their own translations) outside the project tree. That way,\n``django-admin.py makemessages`` on the project level will only translate\nstrings that are connected to your explicit project and not strings that are\ndistributed independently.\n\nThe ``set_language`` Redirect View\n==================================\n\nAs a convenience, Django comes with a view, ``django.views.i18n.set_language``,\nthat sets a user's language preference and redirects back to the previous page.\n\nActivate this view by adding the following line to your URLconf::\n\n    (r'^i18n/', include('django.conf.urls.i18n')),\n\n(Note that this example makes the view available at ``/i18n/setlang/``.)\n\nThe view expects to be called via the ``POST`` method, with a ``language``\nparameter set in request. If session support is enabled, the view\nsaves the language choice in the user's session. Otherwise, it saves the\nlanguage choice in a cookie that is by default named ``django_language``.\n(The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.)\n\nAfter setting the language choice, Django redirects the user, following this\nalgorithm:\n\n* Django looks for a ``next`` parameter in the ``POST`` data.\n* If that doesn't exist, or is empty, Django tries the URL in the\n  ``Referrer`` header.\n* If that's empty -- say, if a user's browser suppresses that header --\n  then the user will be redirected to ``/`` (the site root) as a fallback.\n\nHere's example HTML template code::\n\n    <form action=\"/i18n/setlang/\" method=\"post\">\n    <input name=\"next\" type=\"hidden\" value=\"/next/page/\" />\n    <select name=\"language\">\n        {% for lang in LANGUAGES %}\n        <option value=\"{{ lang.0 }}\">{{ lang.1 }}</option>\n        {% endfor %}\n    </select>\n    <input type=\"submit\" value=\"Go\" />\n    </form>\n\nTranslations and JavaScript\n===========================\n\nAdding translations to JavaScript poses some problems:\n\n* JavaScript code doesn't have access to a ``gettext`` implementation.\n\n* JavaScript code doesn't have access to .po or .mo files; they need to be\n  delivered by the server.\n\n* The translation catalogs for JavaScript should be kept as small as\n  possible.\n\nDjango provides an integrated solution for these problems: It passes the\ntranslations into JavaScript, so you can call ``gettext``, etc., from within\nJavaScript.\n\nThe ``javascript_catalog`` View\n-------------------------------\n\nThe main solution to these problems is the ``javascript_catalog`` view, which\nsends out a JavaScript code library with functions that mimic the ``gettext``\ninterface, plus an array of translation strings. Those translation strings are\ntaken from the application, project or Django core, according to what you\nspecify in either the info_dict or the URL.\n\nYou hook it up like this::\n\n    js_info_dict = {\n        'packages': ('your.app.package',),\n    }\n\n    urlpatterns = patterns('',\n        (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),\n    )\n\nEach string in ``packages`` should be in Python dotted-package syntax (the\nsame format as the strings in ``INSTALLED_APPS``) and should refer to a package\nthat contains a ``locale`` directory. If you specify multiple packages, all\nthose catalogs are merged into one catalog. This is useful if you have\nJavaScript that uses strings from different applications.\n\nYou can make the view dynamic by putting the packages into the URL pattern::\n\n    urlpatterns = patterns('',\n        (r'^jsi18n/(?P<packages>\\S+)/$', 'django.views.i18n.javascript_catalog'),\n    )\n\nWith this, you specify the packages as a list of package names delimited by '+'\nsigns in the URL. This is especially useful if your pages use code from\ndifferent apps and this changes often and you don't want to pull in one big\ncatalog file. As a security measure, these values can only be either\n``django.conf`` or any package from the ``INSTALLED_APPS`` setting.\n\nUsing the JavaScript Translation Catalog\n----------------------------------------\n\nTo use the catalog, just pull in the dynamically generated script like this::\n\n    <script type=\"text/javascript\" src=\"/path/to/jsi18n/\"></script>\n\nThis is how the admin fetches the translation catalog from the server. When the\ncatalog is loaded, your JavaScript code can use the standard ``gettext``\ninterface to access it::\n\n    document.write(gettext('this is to be translated'));\n\nThere is also an ``ngettext`` interface::\n\n    var object_cnt = 1 // or 0, or 2, or 3, ...\n    s = ngettext('literal for the singular case',\n            'literal for the plural case', object_cnt);\n\nand even a string interpolation function::\n\n    function interpolate(fmt, obj, named);\n\nThe interpolation syntax is borrowed from Python, so the ``interpolate``\nfunction supports both positional and named interpolation:\n\n* Positional interpolation: ``obj`` contains a JavaScript Array object\n  whose elements values are then sequentially interpolated in their\n  corresponding ``fmt`` placeholders in the same order they appear.\n  For example::\n\n    fmts = ngettext('There is %s object. Remaining: %s',\n            'There are %s objects. Remaining: %s', 11);\n    s = interpolate(fmts, [11, 20]);\n    // s is 'There are 11 objects. Remaining: 20'\n\n* Named interpolation: This mode is selected by passing the optional\n  boolean ``named`` parameter as true. ``obj`` contains a JavaScript\n  object or associative array. For example::\n\n    d = {\n        count: 10\n        total: 50\n    };\n\n    fmts = ngettext('Total: %(total)s, there is %(count)s object',\n    'there are %(count)s of a total of %(total)s objects', d.count);\n    s = interpolate(fmts, d, true);\n\nYou shouldn't go over the top with string interpolation, though: this is still\nJavaScript, so the code has to make repeated regular-expression substitutions.\nThis isn't as fast as string interpolation in Python, so keep it to those\ncases where you really need it (for example, in conjunction with ``ngettext``\nto produce proper pluralizations).\n\nCreating JavaScript Translation Catalogs\n----------------------------------------\n\nYou create and update the translation catalogs the same way as the other\n\nDjango translation catalogs -- with the django-admin.py makemessages tool. The\nonly difference is you need to provide a ``-d djangojs`` parameter, like this::\n\n    django-admin.py makemessages -d djangojs -l de\n\nThis would create or update the translation catalog for JavaScript for German.\nAfter updating translation catalogs, just run ``django-admin.py compilemessages``\nthe same way as you do with normal Django translation catalogs.\n\nNotes for Users Familiar with ``gettext``\n=========================================\n\nIf you know ``gettext``, you might note these specialties in the way Django\ndoes translation:\n\n* The string domain is ``django`` or ``djangojs``. This string domain is\n  used to differentiate between different programs that store their data\n  in a common message-file library (usually ``/usr/share/locale/``). The\n  ``django`` domain is used for python and template translation strings\n  and is loaded into the global translation catalogs. The ``djangojs``\n  domain is only used for JavaScript translation catalogs to make sure\n  that those are as small as possible.\n* Django doesn't use ``xgettext`` alone. It uses Python wrappers around\n  ``xgettext`` and ``msgfmt``. This is mostly for convenience.\n\n``gettext`` on Windows\n======================\n\nThis is only needed for people who either want to extract message IDs or compile\nmessage files (``.po``). Translation work itself just involves editing existing\nfiles of this type, but if you want to create your own message files, or want to\ntest or compile a changed message file, you will need the ``gettext`` utilities:\n\n* Download the following zip files from\n  http://sourceforge.net/projects/gettext\n\n  * ``gettext-runtime-X.bin.woe32.zip``\n  * ``gettext-tools-X.bin.woe32.zip``\n  * ``libiconv-X.bin.woe32.zip``\n\n* Extract the 3 files in the same folder (i.e. ``C:\\Program\n  Files\\gettext-utils``)\n\n* Update the system PATH:\n\n  * ``Control Panel > System > Advanced > Environment Variables``\n  * In the ``System variables`` list, click ``Path``, click ``Edit``\n  * Add ``;C:\\Program Files\\gettext-utils\\bin`` at the end of the\n    ``Variable value`` field\n\nYou may also use ``gettext`` binaries you have obtained elsewhere, so long as\nthe ``xgettext --version`` command works properly. Some version 0.14.4 binaries\nhave been found to not support this command. Do not attempt to use Django\ntranslation utilities with a ``gettext`` package if the command ``xgettext\n--version`` entered at a Windows command prompt causes a popup window saying\n\"xgettext.exe has generated errors and will be closed by Windows\".\n\nWhat's Next?\n============\n\nThe `final chapter`_ focuses on security -- how you can help secure your sites and\nyour users from malicious attackers.\n\n.. _final chapter: ../chapter20/\n"
  },
  {
    "path": "Python/DjangoBook/chapter20.rst",
    "content": "====================\nChapter 20: Security\n====================\n\nThe Internet can be a scary place.\n\nThese days, high-profile security gaffes seem to crop up on a daily basis. We've\nseen viruses spread with amazing speed, swarms of compromised computers wielded as\nweapons, a never-ending arms race against spammers, and many, many reports of\nidentify theft from hacked Web sites.\n\nAs Web developers, we have a duty to do what we can to combat these forces\nof darkness. Every Web developer needs to treat security as a fundamental\naspect of Web programming. Unfortunately, it turns out that implementing security is *hard*\n-- attackers need to find only a single vulnerability, but defenders have to\nprotect every single one.\n\nDjango attempts to mitigate this difficulty. It's designed to automatically\nprotect you from many of the common security mistakes that new (and even\nexperienced) Web developers make. Still, it's important to understand what\nthese problems are, how Django protects you, and -- most important -- the\nsteps you can take to make your code even more secure.\n\nFirst, though, an important disclaimer: We do not intend to present a\ndefinitive guide to every known Web security exploit, and so we won't try to\nexplain each vulnerability in a comprehensive manner. Instead, we'll give a\nshort synopsis of security problems as they apply to Django.\n\nThe Theme of Web Security\n=========================\n\nIf you learn only one thing from this chapter, let it be this:\n\n    Never -- under any circumstances -- trust data from the browser.\n\nYou *never* know who's on the other side of that HTTP connection. It might be\none of your users, but it just as easily could be a nefarious cracker looking\nfor an opening.\n\nAny data of any nature that comes from the browser needs to be treated with a\nhealthy dose of paranoia. This includes data that's both \"in band\" (i.e.,\nsubmitted from Web forms) and \"out of band\" (i.e., HTTP headers, cookies,\nand other request information). It's trivial to spoof the request metadata that\nbrowsers usually add automatically.\n\nEvery one of the vulnerabilities discussed in this chapter stems directly from\ntrusting data that comes over the wire and then failing to sanitize that data\nbefore using it. You should make it a general practice to continuously ask,\n\"Where does this data come from?\"\n\nSQL Injection\n=============\n\n*SQL injection* is a common exploit in which an attacker alters Web page\nparameters (such as ``GET``/``POST`` data or URLs) to insert arbitrary SQL\nsnippets that a naive Web application executes in its database directly. It's\nprobably the most dangerous -- and, unfortunately, one of the most common --\nvulnerabilities out there.\n\nThis vulnerability most commonly crops up when constructing SQL \"by hand\" from\nuser input. For example, imagine writing a function to gather a list of\ncontact information from a contact search page. To prevent spammers from reading\nevery single e-mail in our system, we'll force the user to type in someone's\nusername before providing her e-mail address::\n\n    def user_contacts(request):\n        user = request.GET['username']\n        sql = \"SELECT * FROM user_contacts WHERE username = '%s';\" % username\n        # execute the SQL here...\n\n.. note::\n\n    In this example, and all similar \"don't do this\" examples that follow,\n    we've deliberately left out most of the code needed to make the functions\n    actually work. We don't want this code to work if someone accidentally\n    takes it out of context.\n\nThough at first this doesn't look dangerous, it really is.\n\nFirst, our attempt at protecting our entire e-mail list will fail with a\ncleverly constructed query. Think about what happens if an attacker types\n``\"' OR 'a'='a\"`` into the query box. In that case, the query that the string\ninterpolation will construct will be::\n\n    SELECT * FROM user_contacts WHERE username = '' OR 'a' = 'a';\n\nBecause we allowed unsecured SQL into the string, the attacker's added ``OR``\nclause ensures that every single row is returned.\n\nHowever, that's the *least* scary attack. Imagine what will happen if the\nattacker submits ``\"'; DELETE FROM user_contacts WHERE 'a' = 'a\"``. We'll end\nup with this complete query::\n\n    SELECT * FROM user_contacts WHERE username = ''; DELETE FROM user_contacts WHERE 'a' = 'a';\n\nYikes! Our entire contact list would be deleted instantly.\n\nThe Solution\n------------\n\nAlthough this problem is insidious and sometimes hard to spot, the solution is\nsimple: *never* trust user-submitted data, and *always* escape it when passing\nit into SQL.\n\nThe Django database API does this for you. It automatically escapes all\nspecial SQL parameters, according to the quoting conventions of the database\nserver you're using (e.g., PostgreSQL or MySQL).\n\nFor example, in this API call::\n\n    foo.get_list(bar__exact=\"' OR 1=1\")\n\nDjango will escape the input accordingly, resulting in a statement like this::\n\n    SELECT * FROM foos WHERE bar = '\\' OR 1=1'\n\nCompletely harmless.\n\nThis applies to the entire Django database API, with a couple of exceptions:\n\n* The ``where`` argument to the ``extra()`` method. (See Appendix C.)\n  That parameter accepts raw SQL by design.\n\n* Queries done \"by hand\" using the lower-level database API. (See Chapter 10.)\n\nIn each of these cases, it's easy to keep yourself protected. In each case,\navoid string interpolation in favor of passing in *bind parameters*. That is,\nthe example we started this section with should be written as follows::\n\n    from django.db import connection\n\n    def user_contacts(request):\n        user = request.GET['username']\n        sql = \"SELECT * FROM user_contacts WHERE username = %s\"\n        cursor = connection.cursor()\n        cursor.execute(sql, [user])\n        # ... do something with the results\n\nThe low-level ``execute`` method takes a SQL string with ``%s`` placeholders\nand automatically escapes and inserts parameters from the list passed as the\nsecond argument. You should *always* construct custom SQL this way.\n\nUnfortunately, you can't use bind parameters everywhere in SQL; they're not\nallowed as identifiers (i.e., table or column names). Thus, if you need to,\nsay, dynamically construct a list of tables from a ``POST`` variable, you'll\nneed to escape that name in your code. Django provides a function,\n``django.db.connection.ops.quote_name``, which will escape the identifier\naccording to the current database's quoting scheme.\n\nCross-Site Scripting (XSS)\n==========================\n\n*Cross-site scripting* (XSS), is found in Web applications that fail to\nescape user-submitted content properly before rendering it into HTML. This\nallows an attacker to insert arbitrary HTML into your Web page, usually in the\nform of ``<script>`` tags.\n\nAttackers often use XSS attacks to steal cookie and session information, or to trick\nusers into giving private information to the wrong person (aka *phishing*).\n\nThis type of attack can take a number of different forms and has almost\ninfinite permutations, so we'll just look at a typical example. Consider this\nextremely simple \"Hello, World\" view::\n\n    from django.http import HttpResponse\n\n    def say_hello(request):\n        name = request.GET.get('name', 'world')\n        return HttpResponse('<h1>Hello, %s!</h1>' % name)\n\nThis view simply reads a name from a ``GET`` parameter and passes that name\ninto the generated HTML. So, if we accessed\n``http://example.com/hello/?name=Jacob``, the page would contain this::\n\n    <h1>Hello, Jacob!</h1>\n\nBut wait -- what happens if we access\n``http://example.com/hello/?name=<i>Jacob</i>``? Then we get this::\n\n    <h1>Hello, <i>Jacob</i>!</h1>\n\nOf course, an attacker wouldn't use something as benign as ``<i>`` tags; he\ncould include a whole set of HTML that hijacked your page with arbitrary\ncontent. This type of attack has been used to trick users into entering data\ninto what looks like their bank's Web site, but in fact is an XSS-hijacked form\nthat submits their back account information to an attacker.\n\nThe problem gets worse if you store this data in the database and later display it\nit on your site. For example, MySpace was once found to be vulnerable to an XSS\nattack of this nature. A user inserted JavaScript into his profile that automatically\nadded him as your friend when you visited his profile page. Within a few days, he had\nmillions of friends.\n\nNow, this may sound relatively benign, but keep in mind that this attacker\nmanaged to get *his* code -- not MySpace's -- running on *your* computer. This\nviolates the assumed trust that all the code on MySpace is actually written\nby MySpace.\n\nMySpace was extremely lucky that this malicious code didn't automatically\ndelete viewers' accounts, change their passwords, flood the site with spam, or\nany of the other nightmare scenarios this vulnerability unleashes.\n\nThe Solution\n------------\n\nThe solution is simple: *always* escape *any* content that might have come\nfrom a user before inserting it into HTML.\n\nTo guard against this, Django's template system automatically escapes all\nvariable values. Let's see what happens if we rewrite our example using the\ntemplate system::\n\n    # views.py\n\n    from django.shortcuts import render\n\n    def say_hello(request):\n        name = request.GET.get('name', 'world')\n        return render(request, 'hello.html', {'name': name})\n\n    # hello.html\n\n    <h1>Hello, {{ name }}!</h1>\n\nWith this in place, a request to ``http://example.com/hello/name=<i>Jacob</i>``\nwill result in the following page::\n\n    <h1>Hello, &lt;i&gt;Jacob&lt;/i&gt;!</h1>\n\nWe covered Django's auto-escaping back in Chapter 4, along with ways to turn\nit off. But even if you're using this feature, you should *still* get in the\nhabit of asking yourself, at all times, \"Where does this data come from?\" No\nautomatic solution will ever protect your site from XSS attacks 100% of the\ntime.\n\nCross-Site Request Forgery\n==========================\n\nCross-site request forgery (CSRF) happens when a malicious Web site tricks users\ninto unknowingly loading a URL from a site at which they're already authenticated --\nhence taking advantage of their authenticated status.\n\nDjango has built-in tools to protect from this kind of attack. Both the attack\nitself and those tools are covered in great detail in `Chapter 16`_.\n\nSession Forging/Hijacking\n=========================\n\nThis isn't a specific attack, but rather a general class of attacks on a\nuser's session data. It can take a number of different forms:\n\n* A *man-in-the-middle* attack, where an attacker snoops on session data\n  as it travels over the wire (or wireless) network.\n\n* *Session forging*, where an attacker uses a session ID\n  (perhaps obtained through a man-in-the-middle attack) to pretend to be\n  another user.\n\n  An example of these first two would be an attacker in a coffee shop using\n  the shop's wireless network to capture a session cookie. She could then use that\n  cookie to impersonate the original user.\n\n* A *cookie-forging* attack, where an attacker overrides the supposedly\n  read-only data stored in a cookie. `Chapter 14`_ explains in detail how\n  cookies work, and one of the salient points is that it's trivial for\n  browsers and malicious users to change cookies without your knowledge.\n\n  There's a long history of Web sites that have stored a cookie like\n  ``IsLoggedIn=1`` or even ``LoggedInAsUser=jacob``. It's dead simple to\n  exploit these types of cookies.\n\n  On a more subtle level, though, it's never a good idea to trust anything\n  stored in cookies. You never know who's been poking at them.\n\n* *Session fixation*, where an attacker tricks a user into setting or\n  reseting the user's session ID.\n\n  For example, PHP allows session identifiers to be passed in the URL\n  (e.g.,\n  ``http://example.com/?PHPSESSID=fa90197ca25f6ab40bb1374c510d7a32``). An\n  attacker who tricks a user into clicking a link with a hard-coded\n  session ID will cause the user to pick up that session.\n\n  Session fixation has been used in phishing attacks to trick users into entering\n  personal information into an account the attacker owns. He can\n  later log into that account and retrieve the data.\n\n* *Session poisoning*, where an attacker injects potentially dangerous\n  data into a user's session -- usually through a Web form that the user\n  submits to set session data.\n\n  A canonical example is a site that stores a simple user preference (like\n  a page's background color) in a cookie. An attacker could trick a user\n  into clicking a link to submit a \"color\" that actually contains an\n  XSS attack. If that color isn't escaped, the user could again\n  inject malicious code into the user's environment.\n\nThe Solution\n------------\n\nThere are a number of general principles that can protect you from these attacks:\n\n* Never allow session information to be contained in the URL.\n\n  Django's session framework (see `Chapter 14`_) simply doesn't allow\n  sessions to be contained in the URL.\n\n* Don't store data in cookies directly. Instead, store a session ID\n  that maps to session data stored on the backend.\n\n  If you use Django's built-in session framework (i.e.,\n  ``request.session``), this is handled automatically for you. The only\n  cookie that the session framework uses is a single session ID; all the\n  session data is stored in the database.\n\n* Remember to escape session data if you display it in the template. See\n  the earlier XSS section, and remember that it applies to any user-created\n  content as well as any data from the browser. You should treat session\n  information as being user created.\n\n* Prevent attackers from spoofing session IDs whenever possible.\n\n  Although it's nearly impossible to detect someone who's hijacked a\n  session ID, Django does have built-in protection against a brute-force\n  session attack. Session IDs are stored as hashes (instead of sequential\n  numbers), which prevents a brute-force attack, and a user will always get\n  a new session ID if she tries a nonexistent one, which prevents session\n  fixation.\n\nNotice that none of those principles and tools prevents man-in-the-middle\nattacks. These types of attacks are nearly impossible to detect. If your site\nallows logged-in users to see any sort of sensitive data, you should *always*\nserve that site over HTTPS. Additionally, if you have an SSL-enabled site,\nyou should set the ``SESSION_COOKIE_SECURE`` setting to ``True``; this will\nmake Django only send session cookies over HTTPS.\n\nE-mail Header Injection\n=======================\n\nSQL injection's less well-known sibling, *e-mail header injection*, hijacks\nWeb forms that send e-mail. An attacker can use this technique to send spam via\nyour mail server. Any form that constructs e-mail headers from Web form data is\nvulnerable to this kind of attack.\n\nLet's look at the canonical contact form found on many sites. Usually this\nsends a message to a hard-coded e-mail address and, hence, doesn't appear\nvulnerable to spam abuse at first glance.\n\nHowever, most of these forms also allow the user to type in his own subject\nfor the e-mail (along with a \"from\" address, body, and sometimes a few other\nfields). This subject field is used to construct the \"subject\" header of the\ne-mail message.\n\nIf that header is unescaped when building the e-mail message, an attacker could\nsubmit something like ``\"hello\\ncc:spamvictim@example.com\"`` (where ``\"\\n``\" is\na newline character). That would make the constructed e-mail headers turn into::\n\n    To: hardcoded@example.com\n    Subject: hello\n    cc: spamvictim@example.com\n\nLike SQL injection, if we trust the subject line given by the user, we'll\nallow him to construct a malicious set of headers, and he can use our\ncontact form to send spam.\n\nThe Solution\n------------\n\nWe can prevent this attack in the same way we prevent SQL injection: always\nescape or validate user-submitted content.\n\nDjango's built-in mail functions (in ``django.core.mail``) simply do not allow\nnewlines in any fields used to construct headers (the from and to addresses,\nplus the subject). If you try to use ``django.core.mail.send_mail`` with a\nsubject that contains newlines, Django will raise a ``BadHeaderError``\nexception.\n\nIf you do not use Django's built-in mail functions to send e-mail, you'll need\nto make sure that newlines in headers either cause an error or are stripped.\nYou may want to examine the ``SafeMIMEText`` class in ``django.core.mail`` to\nsee how Django does this.\n\nDirectory Traversal\n===================\n\n*Directory traversal* is another injection-style attack, wherein a malicious\nuser tricks filesystem code into reading and/or writing files that the Web\nserver shouldn't have access to.\n\nAn example might be a view that reads files from the disk without carefully\nsanitizing the file name::\n\n    def dump_file(request):\n        filename = request.GET[\"filename\"]\n        filename = os.path.join(BASE_PATH, filename)\n        content = open(filename).read()\n\n        # ...\n\nThough it looks like that view restricts file access to files beneath\n``BASE_PATH`` (by using ``os.path.join``), if the attacker passes in a\n``filename`` containing ``..`` (that's two periods, a shorthand for\n\"the parent directory\"), she can access files \"above\" ``BASE_PATH``. It's only\na matter of time before she can discover the correct number of dots to\nsuccessfully access, say, ``../../../../../etc/passwd``.\n\nAnything that reads files without proper escaping is vulnerable to this\nproblem. Views that *write* files are just as vulnerable, but the consequences\nare doubly dire.\n\nAnother permutation of this problem lies in code that dynamically loads\nmodules based on the URL or other request information. A well-publicized\nexample came from the world of Ruby on Rails.  Prior to mid-2006,\nRails used URLs like ``http://example.com/person/poke/1`` directly to\nload modules and call methods. The result was that a\ncarefully constructed URL could automatically load arbitrary code,\nincluding a database reset script!\n\nThe Solution\n------------\n\nIf your code ever needs to read or write files based on user input, you need\nto sanitize the requested path very carefully to ensure that an attacker isn't\nable to escape from the base directory you're restricting access to.\n\n.. note::\n\n    Needless to say, you should *never* write code that can read from any\n    area of the disk!\n\nA good example of how to do this escaping lies in Django's built-in static\ncontent-serving view (in ``django.views.static``). Here's the relevant code::\n\n    import os\n    import posixpath\n\n    # ...\n\n    path = posixpath.normpath(urllib.unquote(path))\n    newpath = ''\n    for part in path.split('/'):\n        if not part:\n            # strip empty path components\n            continue\n\n        drive, part = os.path.splitdrive(part)\n        head, part = os.path.split(part)\n        if part in (os.curdir, os.pardir):\n            # strip '.' and '..' in path\n            continue\n\n        newpath = os.path.join(newpath, part).replace('\\\\', '/')\n\nDjango doesn't read files (unless you use the ``static.serve``\nfunction, but that's protected with the code just shown), so this\nvulnerability doesn't affect the core code much.\n\nIn addition, the use of the URLconf abstraction means that Django will *never*\nload code you've not explicitly told it to load. There's no way to create a\nURL that causes Django to load something not mentioned in a URLconf.\n\nExposed Error Messages\n======================\n\nDuring development, being able to see tracebacks and errors live in your\nbrowser is extremely useful. Django has \"pretty\" and informative debug\nmessages specifically to make debugging easier.\n\nHowever, if these errors get displayed once the site goes live, they can\nreveal aspects of your code or configuration that could aid an attacker.\n\nFurthermore, errors and tracebacks aren't at all useful to end users. Django's\nphilosophy is that site visitors should never see application-related error\nmessages. If your code raises an unhandled exception, a site visitor should\nnot see the full traceback -- or *any* hint of code snippets or Python\n(programmer-oriented) error messages. Instead, the visitor should see a\nfriendly \"This page is unavailable\" message.\n\nNaturally, of course, developers need to see tracebacks to debug problems in\ntheir code. So the framework should hide all error messages from the public,\nbut it should display them to the trusted site developers.\n\nThe Solution\n------------\n\nAs we covered in Chapter 12, Django's ``DEBUG`` setting controls the display of\nthese error messages. Make sure to set this to ``False`` when you're ready to\ndeploy.\n\nUsers deploying under Apache and mod_python (also see Chapter 12) should also\nmake sure they have ``PythonDebug Off`` in their Apache conf files; this will\nsuppress any errors that occur before Django has had a chance to load.\n\nA Final Word on Security\n========================\n\nWe hope all this talk of security problems isn't too intimidating. It's true\nthat the Web can be a wild world, but with a little bit of foresight,\nyou can have a secure Web site.\n\nKeep in mind that Web security is a constantly changing field; if you're\nreading the dead-tree version of this book, be sure to check more up to date\nsecurity resources for any new vulnerabilities that have been discovered. In\nfact, it's always a good idea to spend some time each week or month\nresearching and keeping current on the state of Web application security. It's\na small investment to make, but the protection you'll get for your site and\nyour users is priceless.\n\nWhat's Next?\n============\n\nYou've reached the end of our regularly scheduled program. The following\nappendixes all contain reference material that you might need as you work on\nyour Django projects.\n\nWe wish you the best of luck in running your Django site, whether it's a little\ntoy for you and a few friends, or the next Google.\n\n.. _Chapter 14: ../chapter14/\n.. _Chapter 16: ../chapter16/\n"
  },
  {
    "path": "Python/DjangoBook/conf.py",
    "content": "# Basic project info\nproject = u'The Django Book'\ncopyright = u'Adrian Holovaty, Jacob Kaplan-Moss, et al.'\nversion = '2.0'\nrelease = '2.0'\n\n# Build options\ntemplates_path = ['_templates']\nexclude_patterns = ['_build', 'README.rst']\nsource_suffix = '.rst'\nmaster_doc = 'index'\n\n# HTML options\nhtml_theme = 'djangobook'\nhtml_theme_path = ['themes']\nhtml_static_path = ['_static']\npygments_style = 'sphinx'\nhtml_use_index = False          # FIXME once proper index directives are added.\nhtml_show_sourcelink = False\nhtml_show_sphinx = False\nhtml_title = \"The Django Book\"\nhtml_add_permalinks = False     # FIXME once styles are fixed to get the hover back.\n\n# LATEX builder\nlatex_documents = [\n  ('index', 'TheDjangoBook.tex', u'The Django Book',\n   u'Adrian Holovaty, Jacob Kaplan-Moss, et al.', 'manual'),\n]\n\n# texinfo builder\ntexinfo_documents = [\n    ('index', 'TheDjangoBook.tex', u'The Django Book',\n     u'Adrian Holovaty, Jacob Kaplan-Moss, et al.', 'manual'),\n    ]\n\n# ePub builder\nepub_title = u'The Django Book'\nepub_author = u'Adrian Holovaty, Jacob Kaplan-Moss, et al.'\nepub_publisher = u'Adrian Holovaty, Jacob Kaplan-Moss, et al.'\nepub_copyright = u'Adrian Holovaty, Jacob Kaplan-Moss, et al.'\n"
  },
  {
    "path": "Python/DjangoBook/frontmatter.rst",
    "content": "===============\nAbout this book\n===============\n\nYou’re reading The Django Book, first published in December 2007 (and updated in 2009) by Apress as The Definitive Guide to Django: Web Development Done Right.\n\nWe’ve released this book freely for a couple of reasons. First, we love Django and we want it to be as accessible as possible. Many programmers learn their craft from well-written technical material, so we set out to create a top-notch guide and reference to Django.\n\nSecond, it turns out that writing books about technology is fundamentally difficult: your words are often outdated before the book even reaches the printer. On the web, however, “the ink is never dry” — we can (and will!) keep the book updated.\n\nAcknowledgements\n================\n\nThe most gratifying aspect of working on Django is the community. We've been\nespecially lucky that Django has attracted such a smart, motivated, and friendly\nbunch. A segment of that community followed us over to the online \"beta\" release\nof this book. Their reviews and comments were indispensable; this book wouldn't\nhave been possible without all that wonderful peer review. Almost a thousand\npeople left comments that helped us improve the clarity, quality, and flow of\nthe final book; we'd like to thank each and every one of them.\n\nWe're especially grateful to those who took the time to review the book in depth\nand left dozens (sometimes hundreds) of comments apiece: Marty Alchin, Max\nBattcher, Oliver Beat- tie, Rod Begbie, Paul Bissex, Matt Boersma, Robbin\nBonthond, Peter Bowyer, Nesta Campbell, Jon Colverson, Jeff Croft, Chris Dary,\nAlex Dong, Matt Drew, Robert Dzikowski, Nick Efford, Ludvig Ericson, Eric\nFloehr, Brad Fults, David Grant, Simon Greenhill, Robert Haveman, Kent Johnson,\nAndrew Kember, Marek Kubica, Eduard Kucera, Anand Kumria, Scott Lamb, Fredrik\nLundh, Vadim Macagon, Markus Majer, Orestis Markou, R. Mason, Yasushi Masuda,\nKevin Menard, Carlo Miron, James Mulholland, R.D. Nielsen, Michael O'Keefe,\nLawrence Oluyede, Andreas Pfrengle, Frankie Robertson, Mike Robinson, Armin\nRonacher, Daniel Roseman, Johan Samyn, Ross Shannon, Carolina F. Silva, Paul\nSmith, Björn Stabell, Bob Stepno, Graeme Stevenson, Justin Stockton, Kevin\nTeague, Daniel Tietze, Brooks Travis, Peter Tripp, Matthias Urlichs, Peter van\nKampen, Alexandre Vassalotti, Jay Wang, Brian Will, and Joshua Works.\n\nMany thanks to our technical editor, Jeremy Dunck. Without Jeremy this book\nwould be littered with errors, inaccuracies, and broken code. We feel very lucky\nthat someone as talented as Jeremy found the time to help us out.\n\nSpecials thanks go to Simon Willison for writing the chapter on form processing.\nWe really appreciate the help, and we're thrilled that Simon's excellent writing\ncan be part of this book.\n\nWe're grateful for all the hard work the folks at Apress put into this book.\nThey've been amazingly supportive and patient; this book wouldn't have come\ntogether without a lot of work on their part. We're especially happy that Apress\nsupported and even encouraged the free release of this book online; it's\nwonderful seeing a publisher so embracing the spirit of open source.\n\nFinally, of course, thanks to our friends, families, and coworkers who've\ngraciously tolerated our mental absence while we finished this work.\n\nAbout the Authors\n=================\n\n**Adrian Holovaty** is a Web developer with a background in journalism. He’s known in journalism circles as one of the pioneers of “journalism via computer programming”, and in technical circles as “the guy who invented Django.”\n\nHe was lead developer at World Online for 2.5 years, during which time Django was developed and implemented on World Online’s sites. He’s the founder of EveryBlock__, a “news feed for your block”.\n\nAdrian lives in Chicago, USA.\n\n__ http://everyblock.com/\n\n**Jacob Kaplan-Moss** is a partner at `Revolution Systems`__ which provides support services around Django and related open source technologies. Jacob previously worked at World Online, where Django was invented, where he was the lead developer of Ellington, a commercial Web publishing platform for media companies.\n\nJacob lives in Lawrence, Kansas, USA.\n\n__ http://revsys.com\n\nAbout the Technical Reviewer\n============================\n\n**Jeremy Dunck** was rescued from corporate IT drudgery by Free Software and, in part, Django. Many of Jeremy’s interests center around access to information.\n\nJeremy was the lead developer of Pegasus News, one of the first uses of Django outside World Online, and has since joined Votizen, a startup intent on reducing the influence of money in politics.\n\nHe serves as DSF Secretary, organizes and helps organize sprints, cares about the health and equity of the Django community. He has gone an embarrassingly long time without a working blog.\n\nJeremy lives in Mountain View, CA, USA.\n\n"
  },
  {
    "path": "Python/DjangoBook/graphics/chapter03.graffle",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>ActiveLayerIndex</key>\n\t<integer>0</integer>\n\t<key>AutoAdjust</key>\n\t<true/>\n\t<key>CanvasColor</key>\n\t<dict>\n\t\t<key>w</key>\n\t\t<string>1</string>\n\t</dict>\n\t<key>CanvasOrigin</key>\n\t<string>{0, 0}</string>\n\t<key>CanvasScale</key>\n\t<real>1</real>\n\t<key>ColumnAlign</key>\n\t<integer>1</integer>\n\t<key>ColumnSpacing</key>\n\t<real>36</real>\n\t<key>CreationDate</key>\n\t<string>2007-01-27 11:29:56 -0600</string>\n\t<key>Creator</key>\n\t<string>Jacob Kaplan-Moss</string>\n\t<key>DisplayScale</key>\n\t<string>1 in = 1 in</string>\n\t<key>GraphDocumentVersion</key>\n\t<integer>5</integer>\n\t<key>GraphicsList</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{317.555, 320.838}, {65, 14}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>Vertical</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>844</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>843</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.37213572859764099</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Align</key>\n\t\t\t\t<integer>2</integer>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qr\\pardirnatural\n\n\\f0\\fs24 \\cf0 Response}</string>\n\t\t\t</dict>\n\t\t\t<key>Wrap</key>\n\t\t\t<string>YES</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>833</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.77922910451889038</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>843</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{348.75, 345.781}</string>\n\t\t\t\t<string>{324, 324}</string>\n\t\t\t\t<string>{311.25, 308.5}</string>\n\t\t\t\t<string>{308.568, 291.097}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>766</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>1</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{204.894, 467.497}, {65, 14}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>YES</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>842</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>833</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.21303296089172363</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf0 Response}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{180.004, 385.051}, {71, 14}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>YES</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>841</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>834</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.26573890447616577</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf0 Response?}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{165.205, 237.508}, {71, 14}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>YES</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>840</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>839</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.28381043672561646</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf0 Response?}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>833</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.94963222742080688</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>839</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{171.448, 209.688}</string>\n\t\t\t\t<string>{198, 218.688}</string>\n\t\t\t\t<string>{203, 249.5}</string>\n\t\t\t\t<string>{235.5, 265.162}</string>\n\t\t\t\t<string>{281.594, 270.5}</string>\n\t\t\t\t<string>{302, 258.5}</string>\n\t\t\t\t<string>{309.375, 235.454}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>760</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>6</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>833</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.6352689266204834</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>834</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{171, 394.25}</string>\n\t\t\t\t<string>{272.5, 384.661}</string>\n\t\t\t\t<string>{297.492, 340.801}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>765</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>5</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{345.554, 237.162}, {65, 28}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>YES</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>829</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>828</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.48887303471565247</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf0 404/500\\\nResponse}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>767</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>6</integer>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>828</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{369, 284.13}</string>\n\t\t\t\t<string>{381.024, 262}</string>\n\t\t\t\t<string>{359.552, 209.688}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>769</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.86956596374511719</real>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>764</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>2</integer>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>822</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{121.5, 412.25}</string>\n\t\t\t\t<string>{121.5, 473.875}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>765</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>8</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{87.8429, 150.816}, {77, 14}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>YES</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>812</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>794</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.66534054279327393</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf0 HttpRequest}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{349, 408.519}, {81, 14}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>Vertical</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>811</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>809</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.49313709139823914</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf0 Exception}</string>\n\t\t\t</dict>\n\t\t\t<key>Wrap</key>\n\t\t\t<string>YES</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>766</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>7</integer>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>809</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{398, 443.502}</string>\n\t\t\t\t<string>{413, 420.625}</string>\n\t\t\t\t<string>{398.25, 381.781}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>772</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.93961387872695923</real>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{195, 66}, {42, 14}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>YES</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>799</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>792</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.4749925434589386</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf0 HTTP}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>760</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>2</integer>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>794</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{171, 133.5}</string>\n\t\t\t\t<string>{135, 144}</string>\n\t\t\t\t<string>{123.094, 169}</string>\n\t\t\t\t<string>{121.948, 182.688}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>750</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>9</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>750</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>2</integer>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>792</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{216, 50.834}</string>\n\t\t\t\t<string>{216, 97.5}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>692</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>765</integer>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>791</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{121.5, 348.625}</string>\n\t\t\t\t<string>{121.5, 376.25}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>755</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>8</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>750</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>7</integer>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>784</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{310.052, 182.688}</string>\n\t\t\t\t<string>{298.55, 153}</string>\n\t\t\t\t<string>{261, 133.5}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>767</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>2</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{141.25, 436.048}, {138, 14}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>YES</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>773</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>772</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.48611101508140564</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf0 View Exception Handler}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>ID</key>\n\t\t\t<integer>772</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{9, 442.562}</string>\n\t\t\t\t<string>{423, 443.562}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>Pattern</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t\t<key>Width</key>\n\t\t\t\t\t<real>3</real>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{123.094, 277.533}, {158.5, 14}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FitText</key>\n\t\t\t<string>Vertical</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>w</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Helvetica</string>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>770</integer>\n\t\t\t<key>Line</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>769</integer>\n\t\t\t\t<key>Position</key>\n\t\t\t\t<real>0.46701368689537048</real>\n\t\t\t\t<key>RotationType</key>\n\t\t\t\t<integer>0</integer>\n\t\t\t</dict>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fswiss\\fcharset77 Helvetica;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf0 Request Exception Handler}</string>\n\t\t\t</dict>\n\t\t\t<key>Wrap</key>\n\t\t\t<string>YES</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>ID</key>\n\t\t\t<integer>769</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{9, 285}</string>\n\t\t\t\t<string>{423, 284}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>Pattern</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t\t<key>Width</key>\n\t\t\t\t\t<real>3</real>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{260.552, 182.688}, {99, 36}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>b</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>g</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>r</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Courier</string>\n\t\t\t\t<key>NSKern</key>\n\t\t\t\t<real>0.0</real>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>767</integer>\n\t\t\t<key>Magnets</key>\n\t\t\t<array>\n\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t</array>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>fill</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t<real>80</real>\n\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t<real>5</real>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fmodern\\fcharset77 Courier;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf1 \\expnd0\\expndtw0\\kerning0\nResponse Middleware}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{324, 345.781}, {99, 36}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>b</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>g</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>r</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Courier</string>\n\t\t\t\t<key>NSKern</key>\n\t\t\t\t<real>0.0</real>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>766</integer>\n\t\t\t<key>Magnets</key>\n\t\t\t<array>\n\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t</array>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>fill</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t<real>80</real>\n\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t<real>5</real>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fmodern\\fcharset77 Courier;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf1 \\expnd0\\expndtw0\\kerning0\nException Middleware}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{72, 376.25}, {99, 36}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>b</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>g</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>r</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Courier</string>\n\t\t\t\t<key>NSKern</key>\n\t\t\t\t<real>0.0</real>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>765</integer>\n\t\t\t<key>Magnets</key>\n\t\t\t<array>\n\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t</array>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>fill</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t<real>80</real>\n\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t<real>5</real>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fmodern\\fcharset77 Courier;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf1 \\expnd0\\expndtw0\\kerning0\nView Middleware}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{72, 473.875}, {99, 36}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>b</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>g</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>r</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Courier</string>\n\t\t\t\t<key>NSKern</key>\n\t\t\t\t<real>0.0</real>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>764</integer>\n\t\t\t<key>Magnets</key>\n\t\t\t<array>\n\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t</array>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>fill</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t<real>80</real>\n\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t<real>5</real>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fmodern\\fcharset77 Courier;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf1 \\expnd0\\expndtw0\\kerning0\nView}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>755</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>2</integer>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>747</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{121.948, 218.688}</string>\n\t\t\t\t<string>{121.5, 312.625}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>760</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>8</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{72.4482, 182.688}, {99, 36}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>b</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>g</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>r</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Courier</string>\n\t\t\t\t<key>NSKern</key>\n\t\t\t\t<real>0.0</real>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>760</integer>\n\t\t\t<key>Magnets</key>\n\t\t\t<array>\n\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t</array>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>fill</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t<real>80</real>\n\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t<real>5</real>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fmodern\\fcharset77 Courier;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf1 \\expnd0\\expndtw0\\kerning0\nRequest Middleware}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{72, 312.625}, {99, 36}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>b</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>g</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>r</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Courier</string>\n\t\t\t\t<key>NSKern</key>\n\t\t\t\t<real>0.0</real>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>755</integer>\n\t\t\t<key>Magnets</key>\n\t\t\t<array>\n\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t</array>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>fill</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t<real>80</real>\n\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t<real>5</real>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fmodern\\fcharset77 Courier;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf1 \\expnd0\\expndtw0\\kerning0\nURLConf}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{126, 97.5}, {180, 36}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>b</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>g</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>r</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>Courier</string>\n\t\t\t\t<key>NSKern</key>\n\t\t\t\t<real>0.0</real>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>750</integer>\n\t\t\t<key>Magnets</key>\n\t\t\t<array>\n\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t</array>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Rectangle</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>fill</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t<real>80</real>\n\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t<real>5</real>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fmodern\\fcharset77 Courier;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf1 \\expnd0\\expndtw0\\kerning0\nModPythonHandler}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Bounds</key>\n\t\t\t<string>{{175.5, 7}, {81, 45}}</string>\n\t\t\t<key>Class</key>\n\t\t\t<string>ShapedGraphic</string>\n\t\t\t<key>FontInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>Color</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>b</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>g</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t\t<key>r</key>\n\t\t\t\t\t<string>1</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>Font</key>\n\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t<key>NSKern</key>\n\t\t\t\t<real>0.0</real>\n\t\t\t\t<key>Size</key>\n\t\t\t\t<real>12</real>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>692</integer>\n\t\t\t<key>Magnets</key>\n\t\t\t<array>\n\t\t\t\t<string>{0, 0}</string>\n\t\t\t\t<string>{0.376543, 0}</string>\n\t\t\t\t<string>{-0.0308642, -0.233333}</string>\n\t\t\t</array>\n\t\t\t<key>Shape</key>\n\t\t\t<string>Cloud</string>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>fill</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t<real>80</real>\n\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<key>shadow</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t</dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t<real>5</real>\n\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Text</key>\n\t\t\t<dict>\n\t\t\t\t<key>Text</key>\n\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf410\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs24 \\cf1 Browser}</string>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>Class</key>\n\t\t\t<string>LineGraphic</string>\n\t\t\t<key>Head</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>767</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>8</integer>\n\t\t\t</dict>\n\t\t\t<key>ID</key>\n\t\t\t<integer>833</integer>\n\t\t\t<key>Points</key>\n\t\t\t<array>\n\t\t\t\t<string>{171, 491.875}</string>\n\t\t\t\t<string>{237, 475}</string>\n\t\t\t\t<string>{302, 326}</string>\n\t\t\t\t<string>{310.052, 218.688}</string>\n\t\t\t</array>\n\t\t\t<key>Style</key>\n\t\t\t<dict>\n\t\t\t\t<key>stroke</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t<string>0</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>Tail</key>\n\t\t\t<dict>\n\t\t\t\t<key>ID</key>\n\t\t\t\t<integer>764</integer>\n\t\t\t\t<key>Info</key>\n\t\t\t\t<integer>5</integer>\n\t\t\t</dict>\n\t\t</dict>\n\t</array>\n\t<key>GridInfo</key>\n\t<dict>\n\t\t<key>ShowsGrid</key>\n\t\t<string>YES</string>\n\t</dict>\n\t<key>GuidesLocked</key>\n\t<string>NO</string>\n\t<key>GuidesVisible</key>\n\t<string>YES</string>\n\t<key>HPages</key>\n\t<integer>1</integer>\n\t<key>ImageCounter</key>\n\t<integer>1</integer>\n\t<key>IsPalette</key>\n\t<string>NO</string>\n\t<key>KeepToScale</key>\n\t<false/>\n\t<key>Layers</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>Lock</key>\n\t\t\t<string>NO</string>\n\t\t\t<key>Name</key>\n\t\t\t<string>Layer 1</string>\n\t\t\t<key>Print</key>\n\t\t\t<string>YES</string>\n\t\t\t<key>View</key>\n\t\t\t<string>YES</string>\n\t\t</dict>\n\t</array>\n\t<key>LayoutInfo</key>\n\t<dict/>\n\t<key>LinksVisible</key>\n\t<string>NO</string>\n\t<key>MagnetsVisible</key>\n\t<string>NO</string>\n\t<key>MasterSheet</key>\n\t<string>Master 1</string>\n\t<key>MasterSheets</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>ActiveLayerIndex</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>AutoAdjust</key>\n\t\t\t<true/>\n\t\t\t<key>CanvasColor</key>\n\t\t\t<dict>\n\t\t\t\t<key>w</key>\n\t\t\t\t<string>1</string>\n\t\t\t</dict>\n\t\t\t<key>CanvasOrigin</key>\n\t\t\t<string>{0, 0}</string>\n\t\t\t<key>CanvasScale</key>\n\t\t\t<real>1</real>\n\t\t\t<key>ColumnAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>ColumnSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>DisplayScale</key>\n\t\t\t<string>1 in = 1 in</string>\n\t\t\t<key>GraphicsList</key>\n\t\t\t<array/>\n\t\t\t<key>GridInfo</key>\n\t\t\t<dict/>\n\t\t\t<key>HPages</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>IsPalette</key>\n\t\t\t<string>NO</string>\n\t\t\t<key>KeepToScale</key>\n\t\t\t<false/>\n\t\t\t<key>Layers</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Lock</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t<key>Name</key>\n\t\t\t\t\t<string>Layer 1</string>\n\t\t\t\t\t<key>Print</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>View</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>LayoutInfo</key>\n\t\t\t<dict/>\n\t\t\t<key>Orientation</key>\n\t\t\t<integer>2</integer>\n\t\t\t<key>OutlineStyle</key>\n\t\t\t<string>Basic</string>\n\t\t\t<key>RowAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>RowSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>SheetTitle</key>\n\t\t\t<string>Master 1</string>\n\t\t\t<key>UniqueID</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>VPages</key>\n\t\t\t<integer>1</integer>\n\t\t</dict>\n\t</array>\n\t<key>ModificationDate</key>\n\t<string>2007-01-30 21:58:39 -0600</string>\n\t<key>Modifier</key>\n\t<string>Jeremy Dunck</string>\n\t<key>NotesVisible</key>\n\t<string>NO</string>\n\t<key>Orientation</key>\n\t<integer>2</integer>\n\t<key>OriginVisible</key>\n\t<string>NO</string>\n\t<key>OutlineStyle</key>\n\t<string>Basic</string>\n\t<key>PageBreaks</key>\n\t<string>YES</string>\n\t<key>PrintInfo</key>\n\t<dict>\n\t\t<key>NSBottomMargin</key>\n\t\t<array>\n\t\t\t<string>float</string>\n\t\t\t<string>0</string>\n\t\t</array>\n\t\t<key>NSLeftMargin</key>\n\t\t<array>\n\t\t\t<string>float</string>\n\t\t\t<string>0</string>\n\t\t</array>\n\t\t<key>NSPaperSize</key>\n\t\t<array>\n\t\t\t<string>size</string>\n\t\t\t<string>{612, 792}</string>\n\t\t</array>\n\t\t<key>NSRightMargin</key>\n\t\t<array>\n\t\t\t<string>float</string>\n\t\t\t<string>0</string>\n\t\t</array>\n\t\t<key>NSTopMargin</key>\n\t\t<array>\n\t\t\t<string>float</string>\n\t\t\t<string>0</string>\n\t\t</array>\n\t</dict>\n\t<key>ReadOnly</key>\n\t<string>NO</string>\n\t<key>RowAlign</key>\n\t<integer>1</integer>\n\t<key>RowSpacing</key>\n\t<real>36</real>\n\t<key>SheetTitle</key>\n\t<string>request/response diagram</string>\n\t<key>SmartAlignmentGuidesActive</key>\n\t<string>YES</string>\n\t<key>SmartDistanceGuidesActive</key>\n\t<string>YES</string>\n\t<key>UniqueID</key>\n\t<integer>1</integer>\n\t<key>UseEntirePage</key>\n\t<true/>\n\t<key>VPages</key>\n\t<integer>1</integer>\n\t<key>WindowInfo</key>\n\t<dict>\n\t\t<key>CurrentSheet</key>\n\t\t<string>0</string>\n\t\t<key>DrawerOpen</key>\n\t\t<true/>\n\t\t<key>DrawerTab</key>\n\t\t<string>Outline</string>\n\t\t<key>DrawerWidth</key>\n\t\t<real>209</real>\n\t\t<key>FitInWindow</key>\n\t\t<false/>\n\t\t<key>Frame</key>\n\t\t<string>{{158, -8}, {603, 714}}</string>\n\t\t<key>ShowRuler</key>\n\t\t<false/>\n\t\t<key>ShowStatusBar</key>\n\t\t<true/>\n\t\t<key>VisibleRegion</key>\n\t\t<string>{{-6, 0}, {588, 600}}</string>\n\t\t<key>Zoom</key>\n\t\t<string>1</string>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "Python/DjangoBook/graphics/chapter20.graffle",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CreationDate</key>\n\t<string>2007-01-23 22:42:00 -0600</string>\n\t<key>Creator</key>\n\t<string>Jacob Kaplan-Moss</string>\n\t<key>GraphDocumentVersion</key>\n\t<integer>5</integer>\n\t<key>GuidesLocked</key>\n\t<string>NO</string>\n\t<key>GuidesVisible</key>\n\t<string>NO</string>\n\t<key>ImageCounter</key>\n\t<integer>1</integer>\n\t<key>LinksVisible</key>\n\t<string>NO</string>\n\t<key>MagnetsVisible</key>\n\t<string>NO</string>\n\t<key>MasterSheets</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>ActiveLayerIndex</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>AutoAdjust</key>\n\t\t\t<true/>\n\t\t\t<key>CanvasColor</key>\n\t\t\t<dict>\n\t\t\t\t<key>w</key>\n\t\t\t\t<string>1</string>\n\t\t\t</dict>\n\t\t\t<key>CanvasOrigin</key>\n\t\t\t<string>{0, 0}</string>\n\t\t\t<key>CanvasScale</key>\n\t\t\t<real>1</real>\n\t\t\t<key>ColumnAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>ColumnSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>DisplayScale</key>\n\t\t\t<string>1 in = 1 in</string>\n\t\t\t<key>GraphicsList</key>\n\t\t\t<array/>\n\t\t\t<key>GridInfo</key>\n\t\t\t<dict/>\n\t\t\t<key>HPages</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>IsPalette</key>\n\t\t\t<string>NO</string>\n\t\t\t<key>KeepToScale</key>\n\t\t\t<false/>\n\t\t\t<key>Layers</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Lock</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t<key>Name</key>\n\t\t\t\t\t<string>Layer 1</string>\n\t\t\t\t\t<key>Print</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>View</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>LayoutInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>LayoutTarget</key>\n\t\t\t\t<integer>3</integer>\n\t\t\t</dict>\n\t\t\t<key>Orientation</key>\n\t\t\t<integer>2</integer>\n\t\t\t<key>OutlineStyle</key>\n\t\t\t<string>Basic</string>\n\t\t\t<key>RowAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>RowSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>SheetTitle</key>\n\t\t\t<string>Master 1</string>\n\t\t\t<key>UniqueID</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>VPages</key>\n\t\t\t<integer>1</integer>\n\t\t</dict>\n\t</array>\n\t<key>ModificationDate</key>\n\t<string>2007-01-24 00:22:27 -0600</string>\n\t<key>Modifier</key>\n\t<string>Jacob Kaplan-Moss</string>\n\t<key>NotesVisible</key>\n\t<string>NO</string>\n\t<key>OriginVisible</key>\n\t<string>NO</string>\n\t<key>PageBreaks</key>\n\t<string>YES</string>\n\t<key>PrintInfo</key>\n\t<dict>\n\t\t<key>NSBottomMargin</key>\n\t\t<array>\n\t\t\t<string>float</string>\n\t\t\t<string>0</string>\n\t\t</array>\n\t\t<key>NSLeftMargin</key>\n\t\t<array>\n\t\t\t<string>float</string>\n\t\t\t<string>0</string>\n\t\t</array>\n\t\t<key>NSRightMargin</key>\n\t\t<array>\n\t\t\t<string>float</string>\n\t\t\t<string>0</string>\n\t\t</array>\n\t\t<key>NSTopMargin</key>\n\t\t<array>\n\t\t\t<string>float</string>\n\t\t\t<string>0</string>\n\t\t</array>\n\t</dict>\n\t<key>ReadOnly</key>\n\t<string>NO</string>\n\t<key>Sheets</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>ActiveLayerIndex</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>AutoAdjust</key>\n\t\t\t<true/>\n\t\t\t<key>CanvasColor</key>\n\t\t\t<dict>\n\t\t\t\t<key>w</key>\n\t\t\t\t<string>1</string>\n\t\t\t</dict>\n\t\t\t<key>CanvasOrigin</key>\n\t\t\t<string>{0, 0}</string>\n\t\t\t<key>CanvasScale</key>\n\t\t\t<real>1</real>\n\t\t\t<key>ColumnAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>ColumnSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>DisplayScale</key>\n\t\t\t<string>1 in = 1 in</string>\n\t\t\t<key>GraphicsList</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>685</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>-1</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{68.94, 97.834}</string>\n\t\t\t\t\t\t<string>{68.94, 126}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>663</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{38.88, 54}, {60.12, 45}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Bold</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>12</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>663</integer>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Cloud</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{23.94, 207}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>684</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nmedia}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{23.94, 171}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>683</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndatabase}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{23.94, 135}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>682</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndjango}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{14.94, 126}, {108, 135}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 server}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>GridInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>SnapsToGrid</key>\n\t\t\t\t<string>YES</string>\n\t\t\t</dict>\n\t\t\t<key>HPages</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>IsPalette</key>\n\t\t\t<string>NO</string>\n\t\t\t<key>KeepToScale</key>\n\t\t\t<false/>\n\t\t\t<key>Layers</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Lock</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t<key>Name</key>\n\t\t\t\t\t<string>Layer 1</string>\n\t\t\t\t\t<key>Print</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>View</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>LayoutInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>LayoutTarget</key>\n\t\t\t\t<integer>3</integer>\n\t\t\t</dict>\n\t\t\t<key>MasterSheet</key>\n\t\t\t<string>Master 1</string>\n\t\t\t<key>Orientation</key>\n\t\t\t<integer>2</integer>\n\t\t\t<key>OutlineStyle</key>\n\t\t\t<string>Basic</string>\n\t\t\t<key>RowAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>RowSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>SheetTitle</key>\n\t\t\t<string>single server</string>\n\t\t\t<key>UniqueID</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>VPages</key>\n\t\t\t<integer>1</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>ActiveLayerIndex</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>AutoAdjust</key>\n\t\t\t<true/>\n\t\t\t<key>CanvasColor</key>\n\t\t\t<dict>\n\t\t\t\t<key>w</key>\n\t\t\t\t<string>1</string>\n\t\t\t</dict>\n\t\t\t<key>CanvasOrigin</key>\n\t\t\t<string>{0, 0}</string>\n\t\t\t<key>CanvasScale</key>\n\t\t\t<real>1</real>\n\t\t\t<key>ColumnAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>ColumnSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>DisplayScale</key>\n\t\t\t<string>1 in = 1 in</string>\n\t\t\t<key>GraphicsList</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>689</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>-1</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 189}</string>\n\t\t\t\t\t\t<string>{171, 216}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>685</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>-1</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 61.834}</string>\n\t\t\t\t\t\t<string>{171, 90}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>663</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{140.94, 18}, {60.12, 45}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Bold</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>12</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>663</integer>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Cloud</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 135}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>684</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nmedia}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 225}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>683</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndatabase}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>682</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndjango}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{117, 90}, {108, 99}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 web server}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{117, 216}, {108, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 database server}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>GridInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>SnapsToGrid</key>\n\t\t\t\t<string>YES</string>\n\t\t\t</dict>\n\t\t\t<key>HPages</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>IsPalette</key>\n\t\t\t<string>NO</string>\n\t\t\t<key>KeepToScale</key>\n\t\t\t<false/>\n\t\t\t<key>Layers</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Lock</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t<key>Name</key>\n\t\t\t\t\t<string>Layer 1</string>\n\t\t\t\t\t<key>Print</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>View</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>LayoutInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>LayoutTarget</key>\n\t\t\t\t<integer>3</integer>\n\t\t\t</dict>\n\t\t\t<key>MasterSheet</key>\n\t\t\t<string>Master 1</string>\n\t\t\t<key>Orientation</key>\n\t\t\t<integer>2</integer>\n\t\t\t<key>OutlineStyle</key>\n\t\t\t<string>Basic</string>\n\t\t\t<key>RowAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>RowSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>SheetTitle</key>\n\t\t\t<string>seperate database server</string>\n\t\t\t<key>UniqueID</key>\n\t\t\t<integer>2</integer>\n\t\t\t<key>VPages</key>\n\t\t\t<integer>1</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>ActiveLayerIndex</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>AutoAdjust</key>\n\t\t\t<true/>\n\t\t\t<key>CanvasColor</key>\n\t\t\t<dict>\n\t\t\t\t<key>w</key>\n\t\t\t\t<string>1</string>\n\t\t\t</dict>\n\t\t\t<key>CanvasOrigin</key>\n\t\t\t<string>{0, 0}</string>\n\t\t\t<key>CanvasScale</key>\n\t\t\t<real>1</real>\n\t\t\t<key>ColumnAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>ColumnSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>DisplayScale</key>\n\t\t\t<string>1 in = 1 in</string>\n\t\t\t<key>GraphicsList</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>690</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>693</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{249.864, 49.3595}</string>\n\t\t\t\t\t\t<string>{279, 90}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>692</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>689</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>-1</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 153}</string>\n\t\t\t\t\t\t<string>{171, 189}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>694</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{224.182, 50.7874}</string>\n\t\t\t\t\t\t<string>{198, 90}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>692</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{207, 9}, {60.12, 45}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Bold</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>12</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>692</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{0, 0}</string>\n\t\t\t\t\t\t<string>{0, -0.25}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Cloud</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{261, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>684</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nmedia}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 198}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>683</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndatabase}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>682</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndjango}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{117, 90}, {108, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596284}</string>\n\t\t\t\t\t\t<string>{-1.33333, -6.35783e-07}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 web server}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{117, 189}, {108, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596284}</string>\n\t\t\t\t\t\t<string>{1.33333, 1.27157e-06}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596286}</string>\n\t\t\t\t\t\t<string>{0.596284, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596284, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596286}</string>\n\t\t\t\t\t\t<string>{-1.33333, 1.27157e-06}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596284}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 database server}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{252, 90}, {108, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>690</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 3.17891e-07}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596284}</string>\n\t\t\t\t\t\t<string>{-1.33333, -3.17891e-07}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 media server}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>GridInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>SnapsToGrid</key>\n\t\t\t\t<string>YES</string>\n\t\t\t</dict>\n\t\t\t<key>HPages</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>IsPalette</key>\n\t\t\t<string>NO</string>\n\t\t\t<key>KeepToScale</key>\n\t\t\t<false/>\n\t\t\t<key>Layers</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Lock</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t<key>Name</key>\n\t\t\t\t\t<string>Layer 1</string>\n\t\t\t\t\t<key>Print</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>View</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>LayoutInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>LayoutTarget</key>\n\t\t\t\t<integer>3</integer>\n\t\t\t</dict>\n\t\t\t<key>MasterSheet</key>\n\t\t\t<string>Master 1</string>\n\t\t\t<key>Orientation</key>\n\t\t\t<integer>2</integer>\n\t\t\t<key>OutlineStyle</key>\n\t\t\t<string>Basic</string>\n\t\t\t<key>RowAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>RowSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>SheetTitle</key>\n\t\t\t<string>seperate media server 1</string>\n\t\t\t<key>UniqueID</key>\n\t\t\t<integer>3</integer>\n\t\t\t<key>VPages</key>\n\t\t\t<integer>1</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>ActiveLayerIndex</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>AutoAdjust</key>\n\t\t\t<true/>\n\t\t\t<key>CanvasColor</key>\n\t\t\t<dict>\n\t\t\t\t<key>w</key>\n\t\t\t\t<string>1</string>\n\t\t\t</dict>\n\t\t\t<key>CanvasOrigin</key>\n\t\t\t<string>{0, 0}</string>\n\t\t\t<key>CanvasScale</key>\n\t\t\t<real>1</real>\n\t\t\t<key>ColumnAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>ColumnSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>DisplayScale</key>\n\t\t\t<string>1 in = 1 in</string>\n\t\t\t<key>GraphicsList</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>699</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>3</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>703</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{247.5, 225}</string>\n\t\t\t\t\t\t<string>{198, 288}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>695</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>9</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>699</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>702</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 225}</string>\n\t\t\t\t\t\t<string>{171, 288}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>683</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>8</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>699</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>701</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{94.5, 225}</string>\n\t\t\t\t\t\t<string>{144, 288}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>696</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>7</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 297}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>700</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndatabase}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{117, 288}, {108, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>699</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 3.17891e-07}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596284}</string>\n\t\t\t\t\t\t<string>{-1.33333, -3.17891e-07}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 database server}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>695</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>698</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{198, 153}</string>\n\t\t\t\t\t\t<string>{247.5, 198}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>7</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>683</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>697</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 153}</string>\n\t\t\t\t\t\t<string>{171, 198}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>8</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>696</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>685</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{144, 153}</string>\n\t\t\t\t\t\t<string>{94.5, 198}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>9</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{27, 198}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>696</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndjango}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{225, 198}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>695</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndjango}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>690</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>1</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>693</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{249.864, 49.3595}</string>\n\t\t\t\t\t\t<string>{279, 90}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>692</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>694</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{224.182, 50.7874}</string>\n\t\t\t\t\t\t<string>{198, 90}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>692</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{207, 9}, {60.12, 45}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Bold</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>12</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>692</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{0, 0}</string>\n\t\t\t\t\t\t<string>{0, -0.25}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Cloud</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{261, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>684</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nmedia}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 198}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>683</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndjango}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>682</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nperlbal}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{117, 90}, {108, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596284}</string>\n\t\t\t\t\t\t<string>{-1.33333, -6.35783e-07}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 load balancer}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{18, 189}, {306, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596284}</string>\n\t\t\t\t\t\t<string>{1.33333, 1.27157e-06}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596286}</string>\n\t\t\t\t\t\t<string>{0.596284, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596284, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596286}</string>\n\t\t\t\t\t\t<string>{-1.33333, 1.27157e-06}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596284}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 web server cluster}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{252, 90}, {108, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>690</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 3.17891e-07}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596284}</string>\n\t\t\t\t\t\t<string>{-1.33333, -3.17891e-07}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 media server}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>GridInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>SnapsToGrid</key>\n\t\t\t\t<string>YES</string>\n\t\t\t</dict>\n\t\t\t<key>HPages</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>IsPalette</key>\n\t\t\t<string>NO</string>\n\t\t\t<key>KeepToScale</key>\n\t\t\t<false/>\n\t\t\t<key>Layers</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Lock</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t<key>Name</key>\n\t\t\t\t\t<string>Layer 1</string>\n\t\t\t\t\t<key>Print</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>View</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>LayoutInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>LayoutTarget</key>\n\t\t\t\t<integer>3</integer>\n\t\t\t</dict>\n\t\t\t<key>MasterSheet</key>\n\t\t\t<string>Master 1</string>\n\t\t\t<key>Orientation</key>\n\t\t\t<integer>2</integer>\n\t\t\t<key>OutlineStyle</key>\n\t\t\t<string>Basic</string>\n\t\t\t<key>RowAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>RowSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>SheetTitle</key>\n\t\t\t<string>multiple web servers</string>\n\t\t\t<key>UniqueID</key>\n\t\t\t<integer>4</integer>\n\t\t\t<key>VPages</key>\n\t\t\t<integer>1</integer>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>ActiveLayerIndex</key>\n\t\t\t<integer>0</integer>\n\t\t\t<key>AutoAdjust</key>\n\t\t\t<true/>\n\t\t\t<key>CanvasColor</key>\n\t\t\t<dict>\n\t\t\t\t<key>w</key>\n\t\t\t\t<string>1</string>\n\t\t\t</dict>\n\t\t\t<key>CanvasOrigin</key>\n\t\t\t<string>{0, 0}</string>\n\t\t\t<key>CanvasScale</key>\n\t\t\t<real>1</real>\n\t\t\t<key>ColumnAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>ColumnSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>DisplayScale</key>\n\t\t\t<string>1 in = 1 in</string>\n\t\t\t<key>GraphicsList</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>711</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>11</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>693</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>-1</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{324, 220.5}</string>\n\t\t\t\t\t\t<string>{360, 220.5}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>742</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>743</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>-1</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{324, 121.5}</string>\n\t\t\t\t\t\t<string>{360, 121.5}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>700</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>735</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>-1</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 252}</string>\n\t\t\t\t\t\t<string>{171, 297}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>8</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>708</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>734</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>10</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 252}</string>\n\t\t\t\t\t\t<string>{72, 297}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>8</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>709</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>733</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>10</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 252}</string>\n\t\t\t\t\t\t<string>{270, 297}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>8</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>683</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>732</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>-1</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 153}</string>\n\t\t\t\t\t\t<string>{171, 198}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>8</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>695</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>731</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>10</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 153}</string>\n\t\t\t\t\t\t<string>{247.5, 198}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>8</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>696</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>728</integer>\n\t\t\t\t\t<key>OrthogonalBarAutomatic</key>\n\t\t\t\t\t<true/>\n\t\t\t\t\t<key>OrthogonalBarPosition</key>\n\t\t\t\t\t<real>10</real>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171, 153}</string>\n\t\t\t\t\t\t<string>{72, 198}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>LineType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t\t<key>Info</key>\n\t\t\t\t\t\t<integer>8</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{369, 198}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>713</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nmemcached}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{468, 198}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>712</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nmemcached}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{360, 189}, {207, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>711</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-0.5, 2.38419e-07}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 cache cluster}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{225, 297}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>709</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndatabase}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{27, 297}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>708</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndatabase}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{27, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>707</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nperlbal}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{225, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>706</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nperlbal}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{369, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>705</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nmedia}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{468, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>704</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nmedia}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 297}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>700</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndatabase}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{18, 288}, {306, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>699</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 database server cluster}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{27, 198}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>696</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndjango}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{225, 198}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>695</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndjango}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>LineGraphic</string>\n\t\t\t\t\t<key>Head</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>694</integer>\n\t\t\t\t\t<key>Points</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{171.285, 61.7992}</string>\n\t\t\t\t\t\t<string>{171, 90}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>HeadArrow</key>\n\t\t\t\t\t\t\t<string>FilledArrow</string>\n\t\t\t\t\t\t\t<key>TailArrow</key>\n\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Tail</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t\t<integer>692</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{140, 18}, {63, 45}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Bold</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>12</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>692</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{0, 0}</string>\n\t\t\t\t\t\t<string>{0, -0.25}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Cloud</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 198}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>683</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\ndjango}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{126, 99}, {90, 27}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue</string>\n\t\t\t\t\t\t<key>NSKern</key>\n\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>14</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>682</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 0}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.341176</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.478431</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.215686</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>FillType</key>\n\t\t\t\t\t\t\t<integer>2</integer>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.239216</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.372549</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0941176</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Beneath</key>\n\t\t\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.75</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.0702481</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.108696</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.0192689</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>0.0</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs28 \\cf1 \\expnd0\\expndtw0\\kerning0\nperlbal}</string>\n\t\t\t\t\t</dict>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{18, 90}, {306, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>650</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{0.5, 1.19209e-07}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596284}</string>\n\t\t\t\t\t\t<string>{-1.33333, -3.17891e-07}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 load balancing cluster}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{18, 189}, {306, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>686</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596284}</string>\n\t\t\t\t\t\t<string>{1.33333, 6.35783e-07}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{-1.33333, 0}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596284}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 web server cluster}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Bounds</key>\n\t\t\t\t\t<string>{{360, 90}, {207, 63}}</string>\n\t\t\t\t\t<key>Class</key>\n\t\t\t\t\t<string>ShapedGraphic</string>\n\t\t\t\t\t<key>FontInfo</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t<string>0.298039</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>Font</key>\n\t\t\t\t\t\t<string>HelveticaNeue-Light</string>\n\t\t\t\t\t\t<key>Size</key>\n\t\t\t\t\t\t<real>13</real>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>ID</key>\n\t\t\t\t\t<integer>742</integer>\n\t\t\t\t\t<key>Magnets</key>\n\t\t\t\t\t<array>\n\t\t\t\t\t\t<string>{-0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{0, -1.33333}</string>\n\t\t\t\t\t\t<string>{0.596285, -1.19257}</string>\n\t\t\t\t\t\t<string>{1.19257, -0.596285}</string>\n\t\t\t\t\t\t<string>{1.33333, 3.17891e-07}</string>\n\t\t\t\t\t\t<string>{1.19257, 0.596285}</string>\n\t\t\t\t\t\t<string>{0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{0, 1.33333}</string>\n\t\t\t\t\t\t<string>{-0.596285, 1.19257}</string>\n\t\t\t\t\t\t<string>{-1.19257, 0.596284}</string>\n\t\t\t\t\t\t<string>{-0.5, 2.38419e-07}</string>\n\t\t\t\t\t\t<string>{-1.19257, -0.596285}</string>\n\t\t\t\t\t</array>\n\t\t\t\t\t<key>Shape</key>\n\t\t\t\t\t<string>Rectangle</string>\n\t\t\t\t\t<key>Style</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>fill</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.721569</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>1</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.878431</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>GradientAngle</key>\n\t\t\t\t\t\t\t<real>80</real>\n\t\t\t\t\t\t\t<key>GradientColor</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0.254902</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0.392157</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0.113725</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>shadow</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>Color</key>\n\t\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t\t<key>a</key>\n\t\t\t\t\t\t\t\t<string>0.65</string>\n\t\t\t\t\t\t\t\t<key>b</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>g</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t\t<key>r</key>\n\t\t\t\t\t\t\t\t<string>0</string>\n\t\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t\t<key>Fuzziness</key>\n\t\t\t\t\t\t\t<real>1.9227639436721802</real>\n\t\t\t\t\t\t\t<key>ShadowVector</key>\n\t\t\t\t\t\t\t<string>{1, 1}</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t\t<key>stroke</key>\n\t\t\t\t\t\t<dict>\n\t\t\t\t\t\t\t<key>CornerRadius</key>\n\t\t\t\t\t\t\t<real>5</real>\n\t\t\t\t\t\t\t<key>Draws</key>\n\t\t\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t\t</dict>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t<dict>\n\t\t\t\t\t\t<key>Text</key>\n\t\t\t\t\t\t<string>{\\rtf1\\mac\\ansicpg10000\\cocoartf824\\cocoasubrtf420\n{\\fonttbl\\f0\\fnil\\fcharset77 HelveticaNeue-Light;}\n{\\colortbl;\\red255\\green255\\blue255;\\red76\\green76\\blue76;}\n\\pard\\tx560\\tx1120\\tx1680\\tx2240\\tx2800\\tx3360\\tx3920\\tx4480\\tx5040\\tx5600\\tx6160\\tx6720\\qc\\pardirnatural\n\n\\f0\\fs26 \\cf2 media server cluster}</string>\n\t\t\t\t\t\t<key>VerticalPad</key>\n\t\t\t\t\t\t<integer>5</integer>\n\t\t\t\t\t</dict>\n\t\t\t\t\t<key>TextPlacement</key>\n\t\t\t\t\t<integer>2</integer>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>GridInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>SnapsToGrid</key>\n\t\t\t\t<string>YES</string>\n\t\t\t</dict>\n\t\t\t<key>HPages</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>IsPalette</key>\n\t\t\t<string>NO</string>\n\t\t\t<key>KeepToScale</key>\n\t\t\t<false/>\n\t\t\t<key>Layers</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>Lock</key>\n\t\t\t\t\t<string>NO</string>\n\t\t\t\t\t<key>Name</key>\n\t\t\t\t\t<string>Layer 1</string>\n\t\t\t\t\t<key>Print</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t\t<key>View</key>\n\t\t\t\t\t<string>YES</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t\t<key>LayoutInfo</key>\n\t\t\t<dict>\n\t\t\t\t<key>LayoutTarget</key>\n\t\t\t\t<integer>3</integer>\n\t\t\t</dict>\n\t\t\t<key>MasterSheet</key>\n\t\t\t<string>Master 1</string>\n\t\t\t<key>Orientation</key>\n\t\t\t<integer>2</integer>\n\t\t\t<key>OutlineStyle</key>\n\t\t\t<string>Basic</string>\n\t\t\t<key>RowAlign</key>\n\t\t\t<integer>1</integer>\n\t\t\t<key>RowSpacing</key>\n\t\t\t<real>36</real>\n\t\t\t<key>SheetTitle</key>\n\t\t\t<string>large-scale</string>\n\t\t\t<key>UniqueID</key>\n\t\t\t<integer>5</integer>\n\t\t\t<key>VPages</key>\n\t\t\t<integer>1</integer>\n\t\t</dict>\n\t</array>\n\t<key>SmartAlignmentGuidesActive</key>\n\t<string>YES</string>\n\t<key>SmartDistanceGuidesActive</key>\n\t<string>YES</string>\n\t<key>UseEntirePage</key>\n\t<true/>\n\t<key>WindowInfo</key>\n\t<dict>\n\t\t<key>CurrentSheet</key>\n\t\t<string>4</string>\n\t\t<key>DrawerOpen</key>\n\t\t<true/>\n\t\t<key>DrawerTab</key>\n\t\t<string>Canvases</string>\n\t\t<key>DrawerWidth</key>\n\t\t<real>209</real>\n\t\t<key>FitInWindow</key>\n\t\t<false/>\n\t\t<key>Frame</key>\n\t\t<string>{{458, 91}, {655, 914}}</string>\n\t\t<key>ShowRuler</key>\n\t\t<false/>\n\t\t<key>ShowStatusBar</key>\n\t\t<true/>\n\t\t<key>VisibleRegion</key>\n\t\t<string>{{-26, -28}, {640, 824}}</string>\n\t\t<key>Zoom</key>\n\t\t<string>1</string>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "Python/DjangoBook/index.rst",
    "content": "===============\nThe Django Book\n===============\n\nWelcome to the online version of The Django Book, a free book about the Django Web framework for the Python programming language.\n\n.. admonition:: A note about this edition\n\n   Welcome to the community edition of the Django Book!\n\n   This book was originally published by Apress in 2009, and covered Django 1.0. Since then, it's languished. We're working on getting the book updated to cover Django 1.4, 1.5, and beyond. But **we need your help**, so we're making this book — warts and all —\n   `open source`__ in the hopes that it'll find love as a community project.\n\n   So, if you'd like to help out, `hop on over to GitHub`__ and send us a\n   pull request!\n\n__ http://github.com/jacobian/djangobook.com\n__ http://github.com/jacobian/djangobook.com\n\n.. toctree::\n   :maxdepth: 1\n   :glob:\n\n   frontmatter\n   introduction\n   chapter*\n   appendix*\n   license\n"
  },
  {
    "path": "Python/DjangoBook/introduction.rst",
    "content": "============\nIntroduction\n============\n\nIn the early days, Web developers wrote every page by hand. Updating a Web site\nmeant editing HTML; a \"redesign\" involved redoing every single page, one at a\ntime.\n\nAs Web sites grew and became more ambitious, it quickly became obvious that that\nsituation was tedious, time-consuming, and ultimately untenable. A group of\nenterprising hackers at NCSA (the National Center for Supercomputing\nApplications, where Mosaic, the first graphical Web browser, was developed)\nsolved this problem by letting the Web server spawn external programs that could\ndynamically generate HTML. They called this protocol the Common Gateway\nInterface, or CGI, and it changed the Web forever.\n\nIt's hard now to imagine what a revelation CGI must have been: instead of\ntreating HTML pages as simple files on disk, CGI allows you to think of your\npages as resources generated dynamically on demand. The development of CGI\nushered in the first generation of dynamic Web sites.\n\nHowever, CGI has its problems: CGI scripts need to contain a lot of repetitive\n\"boilerplate\" code, they make code reuse difficult, and they can be difficult\nfor first-time developers to write and understand.\n\nPHP fixed many of these problems, and it took the world by storm -- it's now by\nfar the most popular tool used to create dynamic Web sites, and dozens of\nsimilar languages and environments (ASP, JSP, etc.) followed PHP's design\nclosely. PHP's major innovation is its ease of use: PHP code is simply embedded\ninto plain HTML; the learning curve for someone who already knows HTML is\nextremely shallow.\n\nBut PHP has its own problems; its very ease of use encourages sloppy,\nrepetitive, ill-conceived code. Worse, PHP does little to protect programmers\nfrom security vulnerabilities, and thus many PHP developers found themselves\nlearning about security only once it was too late.\n\nThese and similar frustrations led directly to the development of the current\ncrop of \"third-generation\" Web development frameworks. These frameworks --\nDjango and Ruby on Rails appear to be the most popular these days -- recognize\nthat the Web's importance has escalated of late. With this new explosion of Web\ndevelopment comes yet another increase in ambition; Web developers are expected\nto do more and more every day.\n\nDjango was invented to meet these new ambitions. Django lets you build deep,\ndynamic, interesting sites in an extremely short time. Django is designed to let\nyou focus on the fun, interesting parts of your job while easing the pain of the\nrepetitive bits. In doing so, it provides high-level abstractions of common Web\ndevelopment patterns, shortcuts for frequent programming tasks, and clear\nconventions on how to solve problems. At the same time, Django tries to stay out\nof your way, letting you work outside the scope of the framework as needed. We\nwrote this book because we firmly believe that Django makes Web development\nbetter. It's designed to quickly get you moving on your own Django projects, and\nthen ultimately teach you everything you need to know to successfully design,\ndevelop, and deploy a site that you'll be proud of.\n\nWe're extremely interested in your feedback. The online version of this book\nwill let you comment on any part of the book, and discuss it with other readers.\nWe'll do our best to read all the comments posted there, and to respond to as\nmany as possible. If you prefer email, please drop us a line at\nfeedback@djangobook.com. Either way, we'd love to hear from you! We're glad\nyou're here, and we hope you find Django as exciting, fun, and useful as we do."
  },
  {
    "path": "Python/DjangoBook/license.rst",
    "content": "===================\nLicense & Copyright\n===================\n\nCopyright Adrian Holovaty, Jacob Kaplan-Moss, and contributors.\n\nPermission is granted to copy, distribute and/or modify this document under the\nterms of the GNU Free Documentation License, Version 1.2 or any later version\npublished by the Free Software Foundation; with no Invariant Sections, no Front-\nCover Texts, and no Back-Cover Texts. A copy of the license is included in the\nsection below entitled \"GNU Free Documentation License\".\n\nGNU Free Documentation License\n==============================\n\nVersion 1.2, November 2002\n\nCopyright (C) 2000,2001,2002  Free Software Foundation, Inc.\n51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\nEveryone is permitted to copy and distribute verbatim copies\nof this license document, but changing it is not allowed.\n\n0. PREAMBLE\n-----------\n\nThe purpose of this License is to make a manual, textbook, or other functional\nand useful document \"free\" in the sense of freedom: to assure everyone the\neffective freedom to copy and redistribute it, with or without modifying it,\neither commercially or noncommercially. Secondarily, this License preserves for\nthe author and publisher a way to get credit for their work, while not being\nconsidered responsible for modifications made by others.\n\nThis License is a kind of \"copyleft\", which means that derivative works of the\ndocument must themselves be free in the same sense. It complements the GNU\nGeneral Public License, which is a copyleft license designed for free software.\n\nWe have designed this License in order to use it for manuals for free software,\nbecause free software needs free documentation: a free program should come with\nmanuals providing the same freedoms that the software does. But this License is\nnot limited to software manuals; it can be used for any textual work, regardless\nof subject matter or whether it is published as a printed book. We recommend\nthis License principally for works whose purpose is instruction or reference.\n\n1. APPLICABILITY AND DEFINITIONS\n--------------------------------\n\nThis License applies to any manual or other work, in any medium, that contains a\nnotice placed by the copyright holder saying it can be distributed under the\nterms of this License. Such a notice grants a world-wide, royalty-free license,\nunlimited in duration, to use that work under the conditions stated herein. The\n\"Document\", below, refers to any such manual or work. Any member of the public\nis a licensee, and is addressed as \"you\". You accept the license if you copy,\nmodify or distribute the work in a way requiring permission under copyright law.\n\nA \"Modified Version\" of the Document means any work containing the Document or a\nportion of it, either copied verbatim, or with modifications and/or translated\ninto another language.\n\nA \"Secondary Section\" is a named appendix or a front-matter section of the\nDocument that deals exclusively with the relationship of the publishers or\nauthors of the Document to the Document's overall subject (or to related\nmatters) and contains nothing that could fall directly within that overall\nsubject. (Thus, if the Document is in part a textbook of mathematics, a\nSecondary Section may not explain any mathematics.) The relationship could be a\nmatter of historical connection with the subject or with related matters, or of\nlegal, commercial, philosophical, ethical or political position regarding them.\n\nThe \"Invariant Sections\" are certain Secondary Sections whose titles are\ndesignated, as being those of Invariant Sections, in the notice that says that\nthe Document is released under this License. If a section does not fit the above\ndefinition of Secondary then it is not allowed to be designated as Invariant.\nThe Document may contain zero Invariant Sections. If the Document does not\nidentify any Invariant Sections then there are none.\n\nThe \"Cover Texts\" are certain short passages of text that are listed, as Front-\nCover Texts or Back-Cover Texts, in the notice that says that the Document is\nreleased under this License. A Front-Cover Text may be at most 5 words, and a\nBack-Cover Text may be at most 25 words.\n\nA \"Transparent\" copy of the Document means a machine-readable copy, represented\nin a format whose specification is available to the general public, that is\nsuitable for revising the document straightforwardly with generic text editors\nor (for images composed of pixels) generic paint programs or (for drawings) some\nwidely available drawing editor, and that is suitable for input to text\nformatters or for automatic translation to a variety of formats suitable for\ninput to text formatters. A copy made in an otherwise Transparent file format\nwhose markup, or absence of markup, has been arranged to thwart or discourage\nsubsequent modification by readers is not Transparent. An image format is not\nTransparent if used for any substantial amount of text. A copy that is not\n\"Transparent\" is called \"Opaque\".\n\nExamples of suitable formats for Transparent copies include plain ASCII without\nmarkup, Texinfo input format, LaTeX input format, SGML or XML using a publicly\navailable DTD, and standard-conforming simple HTML, PostScript or PDF designed\nfor human modification. Examples of transparent image formats include PNG, XCF\nand JPG. Opaque formats include proprietary formats that can be read and edited\nonly by proprietary word processors, SGML or XML for which the DTD and/or\nprocessing tools are not generally available, and the machine-generated HTML,\nPostScript or PDF produced by some word processors for output purposes only.\n\nThe \"Title Page\" means, for a printed book, the title page itself, plus such\nfollowing pages as are needed to hold, legibly, the material this License\nrequires to appear in the title page. For works in formats which do not have any\ntitle page as such, \"Title Page\" means the text near the most prominent\nappearance of the work's title, preceding the beginning of the body of the text.\n\nA section \"Entitled XYZ\" means a named subunit of the Document whose title\neither is precisely XYZ or contains XYZ in parentheses following text that\ntranslates XYZ in another language. (Here XYZ stands for a specific section name\nmentioned below, such as \"Acknowledgements\", \"Dedications\", \"Endorsements\", or\n\"History\".) To \"Preserve the Title\" of such a section when you modify the\nDocument means that it remains a section \"Entitled XYZ\" according to this\ndefinition.\n\nThe Document may include Warranty Disclaimers next to the notice which states\nthat this License applies to the Document. These Warranty Disclaimers are\nconsidered to be included by reference in this License, but only as regards\ndisclaiming warranties: any other implication that these Warranty Disclaimers\nmay have is void and has no effect on the meaning of this License.\n\n2. VERBATIM COPYING\n-------------------\n\nYou may copy and distribute the Document in any medium, either commercially or\nnoncommercially, provided that this License, the copyright notices, and the\nlicense notice saying this License applies to the Document are reproduced in all\ncopies, and that you add no other conditions whatsoever to those of this\nLicense. You may not use technical measures to obstruct or control the reading\nor further copying of the copies you make or distribute. However, you may accept\ncompensation in exchange for copies. If you distribute a large enough number of\ncopies you must also follow the conditions in section 3.\n\nYou may also lend copies, under the same conditions stated above, and you may\npublicly display copies.\n\n3. COPYING IN QUANTITY\n-----------------------\n\nIf you publish printed copies (or copies in media that commonly have printed\ncovers) of the Document, numbering more than 100, and the Document's license\nnotice requires Cover Texts, you must enclose the copies in covers that carry,\nclearly and legibly, all these Cover Texts: Front-Cover Texts on the front\ncover, and Back-Cover Texts on the back cover. Both covers must also clearly and\nlegibly identify you as the publisher of these copies. The front cover must\npresent the full title with all words of the title equally prominent and\nvisible. You may add other material on the covers in addition. Copying with\nchanges limited to the covers, as long as they preserve the title of the\nDocument and satisfy these conditions, can be treated as verbatim copying in\nother respects.\n\nIf the required texts for either cover are too voluminous to fit legibly, you\nshould put the first ones listed (as many as fit reasonably) on the actual\ncover, and continue the rest onto adjacent pages.\n\nIf you publish or distribute Opaque copies of the Document numbering more than\n100, you must either include a machine-readable Transparent copy along with each\nOpaque copy, or state in or with each Opaque copy a computer-network location\nfrom which the general network-using public has access to download using public-\nstandard network protocols a complete Transparent copy of the Document, free of\nadded material. If you use the latter option, you must take reasonably prudent\nsteps, when you begin distribution of Opaque copies in quantity, to ensure that\nthis Transparent copy will remain thus accessible at the stated location until\nat least one year after the last time you distribute an Opaque copy (directly or\nthrough your agents or retailers) of that edition to the public.\n\nIt is requested, but not required, that you contact the authors of the Document\nwell before redistributing any large number of copies, to give them a chance to\nprovide you with an updated version of the Document.\n\n4. MODIFICATIONS\n----------------\n\nYou may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:\n\nA. Use in the Title Page (and on the covers, if any) a title distinct from that\nof the Document, and from those of previous versions (which should, if there\nwere any, be listed in the History section of the Document). You may use the\nsame title as a previous version if the original publisher of that version gives\npermission.\n\nB. List on the Title Page, as authors, one or more persons or entities\nresponsible for authorship of the modifications in the Modified Version,\ntogether with at least five of the principal authors of the Document (all of its\nprincipal authors, if it has fewer than five), unless they release you from this\nrequirement.\n\nC. State on the Title page the name of the publisher of the Modified Version, as\nthe publisher.\n\nD. Preserve all the copyright notices of the Document.\n\nE. Add an appropriate copyright notice for your modifications adjacent to the\nother copyright notices.\n\nF. Include, immediately after the copyright notices, a license notice giving the\npublic permission to use the Modified Version under the terms of this License,\nin the form shown in the Addendum below.\n\nG. Preserve in that license notice the full lists of Invariant Sections and\nrequired Cover Texts given in the Document's license notice.\n\nH. Include an unaltered copy of this License.\n\nI. Preserve the section Entitled \"History\", Preserve its Title, and add to it an\nitem stating at least the title, year, new authors, and publisher of the\nModified Version as given on the Title Page. If there is no section Entitled\n\"History\" in the Document, create one stating the title, year, authors, and\npublisher of the Document as given on its Title Page, then add an item\ndescribing the Modified Version as stated in the previous sentence.\n\nJ. Preserve the network location, if any, given in the Document for public\naccess to a Transparent copy of the Document, and likewise the network locations\ngiven in the Document for previous versions it was based on. These may be placed\nin the \"History\" section. You may omit a network location for a work that was\npublished at least four years before the Document itself, or if the original\npublisher of the version it refers to gives permission.\n\nK. For any section Entitled \"Acknowledgements\" or \"Dedications\", Preserve the\nTitle of the section, and preserve in the section all the substance and tone of\neach of the contributor acknowledgements and/or dedications given therein.\n\nL. Preserve all the Invariant Sections of the Document, unaltered in their text\nand in their titles. Section numbers or the equivalent are not considered part\nof the section titles.\n\nM. Delete any section Entitled \"Endorsements\". Such a section may not be\nincluded in the Modified Version.\n\nN. Do not retitle any existing section to be Entitled \"Endorsements\" or to\nconflict in title with any Invariant Section.\n\nO. Preserve any Warranty Disclaimers.\n\nIf the Modified Version includes new front-matter sections or appendices that\nqualify as Secondary Sections and contain no material copied from the Document,\nyou may at your option designate some or all of these sections as invariant. To\ndo this, add their titles to the list of Invariant Sections in the Modified\nVersion's license notice. These titles must be distinct from any other section\ntitles.\n\nYou may add a section Entitled \"Endorsements\", provided it contains nothing but\nendorsements of your Modified Version by various parties--for example,\nstatements of peer review or that the text has been approved by an organization\nas the authoritative definition of a standard.\n\nYou may add a passage of up to five words as a Front-Cover Text, and a passage\nof up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in\nthe Modified Version. Only one passage of Front-Cover Text and one of Back-Cover\nText may be added by (or through arrangements made by) any one entity. If the\nDocument already includes a cover text for the same cover, previously added by\nyou or by arrangement made by the same entity you are acting on behalf of, you\nmay not add another; but you may replace the old one, on explicit permission\nfrom the previous publisher that added the old one.\n\nThe author(s) and publisher(s) of the Document do not by this License give\npermission to use their names for publicity for or to assert or imply\nendorsement of any Modified Version.\n\n5. COMBINING DOCUMENTS\n----------------------\n\nYou may combine the Document with other documents released under this License,\nunder the terms defined in section 4 above for modified versions, provided that\nyou include in the combination all of the Invariant Sections of all of the\noriginal documents, unmodified, and list them all as Invariant Sections of your\ncombined work in its license notice, and that you preserve all their Warranty\nDisclaimers.\n\nThe combined work need only contain one copy of this License, and multiple\nidentical Invariant Sections may be replaced with a single copy. If there are\nmultiple Invariant Sections with the same name but different contents, make the\ntitle of each such section unique by adding at the end of it, in parentheses,\nthe name of the original author or publisher of that section if known, or else a\nunique number. Make the same adjustment to the section titles in the list of\nInvariant Sections in the license notice of the combined work.\n\nIn the combination, you must combine any sections Entitled \"History\" in the\nvarious original documents, forming one section Entitled \"History\"; likewise\ncombine any sections Entitled \"Acknowledgements\", and any sections Entitled\n\"Dedications\". You must delete all sections Entitled \"Endorsements.\"\n\n6. COLLECTIONS OF DOCUMENTS\n---------------------------\n\nYou may make a collection consisting of the Document and other documents\nreleased under this License, and replace the individual copies of this License\nin the various documents with a single copy that is included in the collection,\nprovided that you follow the rules of this License for verbatim copying of each\nof the documents in all other respects.\n\nYou may extract a single document from such a collection, and distribute it\nindividually under this License, provided you insert a copy of this License into\nthe extracted document, and follow this License in all other respects regarding\nverbatim copying of that document.\n\n7. AGGREGATION WITH INDEPENDENT WORKS\n-------------------------------------\n\nA compilation of the Document or its derivatives with other separate and\nindependent documents or works, in or on a volume of a storage or distribution\nmedium, is called an \"aggregate\" if the copyright resulting from the compilation\nis not used to limit the legal rights of the compilation's users beyond what the\nindividual works permit. When the Document is included in an aggregate, this\nLicense does not apply to the other works in the aggregate which are not\nthemselves derivative works of the Document.\n\nIf the Cover Text requirement of section 3 is applicable to these copies of the\nDocument, then if the Document is less than one half of the entire aggregate,\nthe Document's Cover Texts may be placed on covers that bracket the Document\nwithin the aggregate, or the electronic equivalent of covers if the Document is\nin electronic form. Otherwise they must appear on printed covers that bracket\nthe whole aggregate.\n\n8. TRANSLATION\n--------------\n\nTranslation is considered a kind of modification, so you may distribute\ntranslations of the Document under the terms of section 4. Replacing Invariant\nSections with translations requires special permission from their copyright\nholders, but you may include translations of some or all Invariant Sections in\naddition to the original versions of these Invariant Sections. You may include a\ntranslation of this License, and all the license notices in the Document, and\nany Warranty Disclaimers, provided that you also include the original English\nversion of this License and the original versions of those notices and\ndisclaimers. In case of a disagreement between the translation and the original\nversion of this License or a notice or disclaimer, the original version will\nprevail.\n\nIf a section in the Document is Entitled \"Acknowledgements\", \"Dedications\", or\n\"History\", the requirement (section 4) to Preserve its Title (section 1) will\ntypically require changing the actual title.\n\n9. TERMINATION\n--------------\n\nYou may not copy, modify, sublicense, or distribute the Document except as\nexpressly provided for under this License. Any other attempt to copy, modify,\nsublicense or distribute the Document is void, and will automatically terminate\nyour rights under this License. However, parties who have received copies, or\nrights, from you under this License will not have their licenses terminated so\nlong as such parties remain in full compliance.\n\n10. FUTURE REVISIONS OF THIS LICENSE\n------------------------------------\n\nThe Free Software Foundation may publish new, revised versions of the GNU Free\nDocumentation License from time to time. Such new versions will be similar in\nspirit to the present version, but may differ in detail to address new problems\nor concerns. See http://www.gnu.org/copyleft/.:\n\nEach version of the License is given a distinguishing version number. If the\nDocument specifies that a particular numbered version of this License \"or any\nlater version\" applies to it, you have the option of following the terms and\nconditions either of that specified version or of any later version that has\nbeen published (not as a draft) by the Free Software Foundation. If the Document\ndoes not specify a version number of this License, you may choose any version\never published (not as a draft) by the Free Software Foundation. How to use this\nLicense for your documents:\n\nTo use this License in a document you have written, include a copy of the\nLicense in the document and put the following copyright and license notices just\nafter the title page::\n\n  Copyright (c)  YEAR  YOUR NAME.\n  Permission is granted to copy, distribute and/or modify this document\n  under the terms of the GNU Free Documentation License, Version 1.2\n  or any later version published by the Free Software Foundation;\n  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover\n  Texts.  A copy of the license is included in the section entitled \"GNU\n  Free Documentation License\".\n\nIf you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace\nthe \"with...Texts.\" line with this::\n\n  with the Invariant Sections being LIST THEIR TITLES, with the\n  Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.\n\nIf you have Invariant Sections without Cover Texts, or some other combination of\nthe three, merge those two alternatives to suit the situation.\n\nIf your document contains nontrivial examples of program code, we recommend\nreleasing these examples in parallel under your choice of free software license,\nsuch as the GNU General Public License, to permit their use in free software.\n"
  },
  {
    "path": "Python/DjangoBook/requirements.txt",
    "content": "docutils==0.9.1\ngevent==0.13.8\ngreenlet==0.4.0\ngunicorn==0.14.6\nJinja2==2.6\nPygments==1.5\nresolver==0.2.1\nselector==0.9.4\nSphinx==1.1.3\nstatic==0.4\nUnipath==0.2.1\n"
  },
  {
    "path": "Python/DjangoBook/themes/djangobook/layout.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n  <head>\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n    <title>{% block title %}The Django Book{% endblock %}</title>\n    <link rel=\"stylesheet\" href=\"{{ pathto(\"_static/reset-min.css\", 1) }}\" type=\"text/css\">\n    <link rel=\"stylesheet\" href=\"{{ pathto(\"_static/grids-min.css\", 1) }}\" type=\"text/css\">\n    <link rel=\"stylesheet\" href=\"{{ pathto(\"_static/djangobook.css\", 1) }}\" type=\"text/css\">\n    {% block extrahead %}{% endblock %}\n  </head>\n  <body>\n    <div id=\"doc\" class=\"yui-t7\">\n      <div id=\"hd\">\n        <h1><a href=\"{{ pathto(\"index\") }}\">The Django Book</a></h1>\n        <div id=\"global-nav\">\n            <a class=\"about\" href=\"{{ pathto(\"frontmatter\") }}\">About</a>\n        </div>\n        {% block hdnav %}{% endblock %}\n      </div>\n      <div id=\"bd\">\n        <div id=\"yui-main\">\n          <div class=\"yui-b\">\n            {% block content %}{% endblock %}\n          </div>\n        </div>\n      </div>\n      <div id=\"ft\">\n        {% block ftnav %}{% endblock %}\n        Copyright Adrian Holovaty, Jacob Kaplan-Moss, et al.<br>This\n        work is licensed under the <a href=\"{{ pathto(\"license\") }}\">GNU Free Document\n        License</a>.\n      </div>\n    </div>\n  {% block afterbody %}{% endblock %}\n  </body>\n</html>\n"
  },
  {
    "path": "Python/DjangoBook/themes/djangobook/page.html",
    "content": "{% extends \"layout.html\" %}\n\n{% block title %}{{ title }}{% endblock %}\n\n{% macro nav() %}\n<div class=\"nav\">\n    {% if prev %}\n        <a href='{{ prev.link }}'>&laquo; previous</a> &loz;\n    {% endif %}\n    <a href=\"{{ pathto('index') }}\">table of contents</a>\n    {% if next %}\n        &loz; <a href='{{ next.link }}'>next &raquo;</a>\n    {% endif %}\n</div>\n{% endmacro %}\n\n{% block hdnav %}{{ nav() }}{% endblock %}\n{% block ftnav %}{{ nav() }}{% endblock %}\n\n{% block content %}\n  <div id=\"chapter-body\">{{ body }}</div>\n{% endblock %}\n"
  },
  {
    "path": "Python/DjangoBook/themes/djangobook/search.html",
    "content": "TODO!\n"
  },
  {
    "path": "Python/DjangoBook/themes/djangobook/static/djangobook.css",
    "content": "/*** setup ***/\nbody { font:12px/1.5 Verdana,sans-serif; background:#092e20; color: white;}\n#bd { background:#487858; }\n#doc { padding-top:16px; }\n\n/*** links ***/\na img {border: none;}\na {text-decoration: none;}\na:hover { color:#ffe761; }\na:link, a:visited { color:#ffc757; }\nh2 a, h3 a, h4 a { text-decoration:none !important; }\n#bd a:hover { background-color:#E0FFB8; color:#234f32; text-decoration:none; }\n#bd a:link, #bd a:visited { color:#ab5603; }\n\n/*** nav ***/\ndiv.nav { margin: 0; font-size: 11px; text-align: right; color: #487858;}\n#hd div.nav { margin-top: -27px; }\n#ft div.nav { margin-bottom: -18px; }\n\n#hd h1 a { color: white; }\n\n#global-nav { position:absolute; top:5px; padding:7px 0; color:#263E2B;}\n#global-nav a:link, #global-nav a:visited {color:#487858;}\n#global-nav a {padding:0 4px;}\n#global-nav a.about {padding-left:0;}\n#global-nav:hover {color:#fff;}\n#global-nav:hover a:link, #global-nav:hover a:visited  { color:#ffc757; }\n\n/*** content ***/\n#chapter-body { position: relative; }\n#yui-main div.yui-b { margin: 0 0 0 20px; background: white; color: black; padding: 0.3em 2em 1em 2em; }\ndd { margin-left:15px; }\nh1 { font-size:218%; margin-top:0.6em; margin-bottom:.4em; line-height:1.1em; }\nh1,h2,h3,h4 { margin-top:1.4em; font-family:\"Trebuchet MS\",sans-serif; font-weight:normal; }\nh2 { font-size:150%; margin-bottom:.6em; line-height:1.2em; color:#092e20; }\nh3 { font-size:125%; font-weight:bold; margin-bottom:.2em; color:#487858; }\nh4 { font-size:1em; font-weight:bold; margin-top:1.5em; margin-bottom:3px; }\ndiv.figure { text-align: center; }\ndiv.figure p.caption { font-size:1em; margin-top:0; margin-bottom:1.5em; color: #555;}\nhr { color:#ccc; background-color:#ccc; height:1px; border:0; }\np, ul, dl { margin-top:.6em; margin-bottom:1em; padding-bottom: 0.1em;}\n#chapter-body img { max-width: 50em; margin-left: auto; margin-right: auto; display: block; }\ntable { color:#000; margin-bottom: 1em; width: 100%; }\ntable.docutils td p { margin-top:0; margin-bottom:.5em; }\ntable.docutils td, table.docutils th { border-bottom:1px solid #dfdfdf; padding:4px 2px;}\ntable.docutils thead th { border-bottom:2px solid #dfdfdf; text-align:left; font-weight: bold; white-space: nowrap; }\ntable.docutils thead th p { margin: 0; padding: 0; }\ntable.docutils { border-collapse:collapse; }\ncaption { font-size:1em; font-weight:bold; margin-top:0.5em; margin-bottom:0.5em; margin-left: 2px; text-align: center; }\nblockquote { padding: 0 1em; margin: 1em 0; font:125%/1.2em \"Trebuchet MS\", sans-serif; color:#234f32; border-left:2px solid #94da3a; }\nstrong { font-weight: bold; }\nem { font-style: italic; }\n\n/*** one-off for chapter 7 ***/\n#chapter-body #cn0 strong { font-size:150%; margin-bottom:.6em; line-height:1.2em; color:#092e20; }\n\n/*** messages ***/\ndiv.newer-version, div.message {color:#092e20; background: #FAFBD1 url(images/error.png) no-repeat 10px 50%; padding:3px 2px 5px 35px; font-size:13px; margin-top:1.5em;}\n\n/*** lists ***/\nul { padding-left:30px; }\nol { padding-left:30px; }\nol.arabic { list-style-type: decimal; }\nul li { list-style-type:square; margin-bottom:.4em; }\nol li { margin-bottom: .4em; }\nul ul { padding-left:1.2em; }\nul ul ul { padding-left:1em; }\nul.linklist { padding-left:0; }\nul.linklist li { list-style-type:none; }\ndt { font-weight:bold; margin-top:.5em; font-size:1.1em; }\ndd { margin-bottom:.8em; }\n\n/*** toctree ***/\n.toctree-wrapper ul { margin-bottom: 2em; padding-left: 0; }\n.toctree-wrapper ul li { font-size:125%; padding: .5em; margin-left: 0; line-height:1.2em; clear: right; list-style-type: none; }\n.toctree-wrapper ul li:nth-child(2n) { background-color: #E0FFB8; }\n.toctree-wrapper ul li a:hover { background-color: transparent !important; text-decoration: underline !important; }\n\n/*** code blocks ***/\n.literal { white-space:nowrap; }\n.literal, .literal-block { color:#234f32; }\n.sidebar .literal { color:white; background:transparent; font-size:11px; }\nh4 .literal { color: #234f32; font-size: 13px; }\npre, .literal-block { font-size:medium; background:#E0FFB8; border:1px solid #94da3a; border-width:1px 0; margin: 1em 0; padding: .3em .4em; overflow: hidden; }\ndt .literal, table .literal { background:none; }\n\n/*** notes & admonitions ***/\n.note, .admonition { padding:.8em 1em .8em; margin: 1em 0; border:1px solid #94da3a; }\n.admonition-title { font-weight:bold; margin-top:0 !important; margin-bottom:0 !important;}\n.admonition .last { margin-bottom:0 !important; }\n.admonition-philosophy { padding-left:65px; background:url(http://media.djangoproject.com/img/doc/icons/docicons-philosophy.gif) .8em .8em no-repeat;}\n.note, .admonition { padding-left:65px; background:url(http://media.djangoproject.com/img/doc/icons/docicons-note.gif) .8em .8em no-repeat;}\n.admonition-behind-the-scenes { padding-left:65px; background:url(http://media.djangoproject.com/img/doc/icons/docicons-behindscenes.gif) .8em .8em no-repeat;}\n\n/*** footer ***/\n#ft { color:#487858; font-size:90%; padding-bottom: 2em; }\n\n/*** IE hacks ***/\n* pre { width: 100%; }\n* div.has-comments span { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\"http://media.djangobook.com/images/comment-active.png\", sizingMethod=\"scale\"); }\n* #comments div.tab input { width: 95%; }\n"
  },
  {
    "path": "Python/DjangoBook/themes/djangobook/static/grids-min.css",
    "content": "/* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt Version: 0.11.3 */\nbody{text-align:center;}#doc{width:57.69em;*width:56.3em;min-width:750px;margin:auto;text-align:left;}#hd,#bd{margin-bottom:1em;text-align:left;}#ft{font-size:77%;font-family:verdana;clear:both;}.yui-t1 #yui-main .yui-b, .yui-t2 #yui-main .yui-b, .yui-t3 #yui-main .yui-b, .yui-t4 .yui-b, .yui-t5 .yui-b, .yui-t6 .yui-b{float:right;}.yui-t1 .yui-b, .yui-t2 .yui-b, .yui-t3 .yui-b, .yui-t4 #yui-main .yui-b, .yui-t5 #yui-main .yui-b, .yui-t6 #yui-main .yui-b{float:left;}.yui-t1 #yui-main .yui-b{width:76%;min-width:570px;}.yui-t1 .yui-b{width:21.33%;min-width:160px;}.yui-t2 #yui-main .yui-b, .yui-t4 #yui-main .yui-b{width:73.4%;min-width:550px;}.yui-t2 .yui-b, .yui-t4 .yui-b{width:24%;min-width:180px;}.yui-t3 #yui-main .yui-b, .yui-t6 #yui-main .yui-b{width:57.6%;min-width:430px;}.yui-t3 .yui-b, .yui-t6 .yui-b{width:40%;min-width:300px;}.yui-t5 #yui-main .yui-b{width:65.4%;min-width:490px;}.yui-t5 .yui-b{width:32%;min-width:240px;}.yui-g .yui-u, .yui-g .yui-g, .yui-ge .yui-u, .yui-gf .yui-u{float:right;display:inline;}.yui-g .first, .yui-gd .first, .yui-ge .first, .yui-gf .first{float:left;}.yui-g .yui-u, .yui-g .yui-g{width:49.1%;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-gb .yui-u, .yui-gc .yui-u, .yui-gd .yui-u{float:left;margin-left:2%;*margin-left:1.895%;width:32%;}.yui-gb .first, .yui-gc .first, .yui-gd .first{margin-left:0;}.yui-gc .first, .yui-gd .yui-u{width:66%;}.yui-gd .first{width:32%;}.yui-ge .yui-u{width:24%;}.yui-ge .first, .yui-gf .yui-u{width:74.2%;}.yui-gf .first{width:24%;}.yui-ge .first{width:74.2%;}#bd:after, .yui-g:after, .yui-gb:after, .yui-gc:after, .yui-gd:after, .yui-ge:after, .yui-gf:after{content:\".\";display:block;height:0;clear:both;visibility:hidden;}#bd, .yui-g, .yui-gb, .yui-gc, .yui-gd, .yui-ge, .yui-gf{zoom:1;}"
  },
  {
    "path": "Python/DjangoBook/themes/djangobook/static/pea.py",
    "content": "#!/usr/bin/env python\n\"\"\"peastat - simple live web stats\nhttp://www.throwingbeans.org/peastat/\n\ninstructions: \n1. configure the 'logfile' and 'rooturl' values below\n2. upload peastat.py somewhere it can be executed on your web server (e.g. your cgi-bin)\n3. make peastat.py executable (set its permissions to 755)\n\"\"\"\n__version__ = \"0.2\"\n__author__ = \"Tom Dyson (tomdyson at spamcop dot net)\"\n__copyright__ = \"(C) 2005 Tom Dyson. GNU GPL 2.\" \n__url__ = 'http://www.throwingbeans.org/peastat/'\n\nimport cgitb\ncgitb.enable()\nimport cgi, os, re, time, urllib\ntry: import dbm # anydbm is unreliable...\nexcept: import dumbdbm as dbm\n\n# start configuring:\nlogfile = \"/home/jacob/web/log/djangobook.com/www.log\" # full path to log file\nrooturl = \"http://www.djangobook.com/\" # root url of site whose logs we're analysing\n# configure if you want to:\nminresults = 10 # minimum results to include in overview\nlastlines = 5000 # number of most recent requests to analyse\nispage = re.compile('/$').search # requests matching this regex count as pages\nignorelines = re.compile('24\\.124\\.4\\.220').search # ignore lines including this regex\nrecentreferrers = 20 # show this many recent referrers \nrecentsearches = 20 # show this many recent search terms\ndatabase = \"/tmp/jkmpeastat.db\" # store DNS lookups here\n# stop configuring\n\nurl = None; ip = None; atom = False\ncgiloc = os.environ.get('SCRIPT_NAME', '')\nrequest_uri = os.environ.get('REQUEST_URI', '')\nserver_name = os.environ.get('SERVER_NAME', '')\napachetoday = time.strftime('%d/%b/%Y')\n# todo ooh\n\nform = cgi.FieldStorage()\nif form.has_key( \"url\" ): url = form[\"url\"].value\nif form.has_key( \"ip\" ): ip = form[\"ip\"].value\nif form.has_key( \"atom\" ): atom = True\n\ndef justdomain(url): \n\t# Return only the domain of a URL\n\ttry:\n\t\treturn url.split('//')[1].split('/')[0]\n\texcept IndexError: # catch evil referrers\n\t\treturn 'bad referrer'\n\nthisdomain = justdomain(rooturl)\n\ndef sortByValue(d):\n    \"\"\" Returns the keys of dictionary d sorted by their values \"\"\"\n    items=d.items()\n    backitems=[ [v[1],v[0]] for v in items]\n    backitems.sort(); backitems.reverse()\n    return [ backitems[i][1] for i in range(0,len(backitems))]\n    \ndef tailLines(filename,linesback):\n\t\"\"\"python tail - modified from recipe at \n\t\thttp://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/157035\n\t\treturns list of [linesback] lines from end of [filename]\"\"\"\n\tavgcharsperline=150\n\t\n\tfile = open(filename,'r')\n\twhile 1:\n\t\ttry: file.seek(-1 * avgcharsperline * linesback,2)\n\t\texcept IOError: file.seek(0) \n\t\tif file.tell() == 0: atstart=1 \n\t\telse: atstart=0\n\t\tlines=file.read().split(\"\\n\")\n\t\tif (len(lines) > (linesback+1)) or atstart: break\n\t\t#The lines are bigger than we thought\n\t\tavgcharsperline=avgcharsperline * 1.3 #Inc avg for retry\n\tfile.close()\n\t\n\tif len(lines) > linesback: start=len(lines)-linesback -1\n\telse: start=0\n\treturn lines[start:len(lines)-1]\n\ndef timeSinceApacheDate(apacheDate):\n\tthen = time.strptime(apacheDate,'%d/%b/%Y:%H:%M:%S')\n\tthen = time.mktime(then)\n\tnow = time.mktime(time.localtime())\n\tminutesSince = (now-then) / 60\n\thours, minutes = divmod(minutesSince,60)\n\treturn int(hours), int(minutes)\n\ndef getDNS(ip):\n\t# get the domain name, if we've seen it before\n\ttry:\n\t\tdb = dbm.open(database, \"c\")\n\t\tif db.has_key(ip): addr = db[ip]\n\t\telse: addr = ip\n\t\tdb.close()\t\n\texcept: addr = ip\n\treturn addr\n\ndef getLogLines(logfile):\n\ttry: logLines = tailLines(logfile,lastlines)\n\texcept: # or try system's tail\n\t\tlogLines = os.popen('/usr/bin/tail -n ' \n\t\t+ str(lastlines) + ' ' + logfile).readlines()\n\tif len(logLines) == 0: # can't handle popen exceptions properly\n\t\traise Exception ('No lines found')\n\treturn logLines\n\t\nloglines = getLogLines(logfile)\n\ndef getOverview():\n\n\tt0 = time.time()\n\toverview = {'cgiloc':cgiloc}\n\thits = {}\n\tpagecount = 0\n\toverview[\"totalhits\"] = len(loglines)\n\treferrers = []\n\tqueries = {}\n\ttimeoffirsthit = loglines[0].split(' ')[3].replace('[','')\n\t\n\tfor line in loglines:\n\t\tresource = line.split(' ')[6]\n\t\tif ispage(resource) and not ignorelines(line):\n\t\t\tpagecount = pagecount + 1\n\t\t\thits[resource] = hits.get(resource,0) + 1\n\t\t\tlastres = resource\n\t\t\tline = line.replace('\\\\\"','&quot;') # some agents include escaped quotes\n\t\t\treferrer = line.split('\"')[-4]\n\t\t\tif len(referrer) > 1 and referrer.find(thisdomain) == -1:\n\t\t\t\t# count queries\n\t\t\t\tquerydict = cgi.parse_qs(referrer.split(\"?\")[-1])\n\t\t\t\tif referrer.count(\".yahoo.\"):\n\t\t\t\t\tq = querydict.get(\"p\")\n\t\t\t\telse: q = querydict.get(\"q\")\n\t\t\t\tif q: \n\t\t\t\t\tq = q[0].lower()\n\t\t\t\t\tqueries[q] = queries.get(q,0) + 1\n\t\t\t\treferrers.append([referrer, q])\n\t\t\t\t\n\tt1 = time.time()\n\toverview[\"timing\"] = int((t1 - t0) * 1000)\n\toverview[\"logfile\"] = logfile\n\toverview[\"timeoffirsthit\"] = timeoffirsthit\t\n\toverview[\"hits\"] = hits\n\toverview[\"lastrequest\"] = lastres\n\toverview[\"pagecount\"] = pagecount\n\toverview[\"referrers\"] = referrers\n\toverview[\"queries\"] = queries\n\thourssince, minutessince = timeSinceApacheDate(timeoffirsthit)\n\tpagehitsperhour = pagecount / (hourssince + ( float(minutessince) / 60 ))\n\toverview[\"hourssince\"], overview[\"minutessince\"] = hourssince, minutessince\n\toverview[\"pagehitsperhour\"] = int(round(pagehitsperhour))\n\t\n\treturn overview\n\t\ndef displayOverviewHTML(overview):\n\tprint \"\"\"\n\t\t<p class = \"section\"><strong>Summary</strong><br />\n\t\tFirst hit counted %(hourssince)s hours, %(minutessince)s minutes ago<br />\n\t\tTotal hits: %(totalhits)s<br />\n\t\tPage hits: %(pagecount)s (%(pagehitsperhour)s per hour)<br />\n\t\tLast page request: %(lastrequest)s <a href = \"%(cgiloc)s?url=%(lastrequest)s\">details</a><br />\n\t\tProcessing time: %(timing)s ms</p>\"\"\" % overview\n\n\tprint \"\"\"<p class = \"section\"><strong>Recent popular pages (%s or more requests)</strong><br />\"\"\" % minresults\n\n\thits = overview[\"hits\"]\n\tfor res in sortByValue(hits):\n\t\tscore = hits[res]\n\t\tif score >= minresults:\n\t\t\tprint \"\"\"%s: \n\t\t\t\t<a href = \"%s?url=%s\">%s</a>\n\t\t\t\t<br />\"\"\" % (res, overview[\"cgiloc\"], urllib.quote(res), score)\n\t\n\tprint  \"\"\"</p><p class = \"section\"><strong>%s recent referrers</strong><br />\"\"\" % recentreferrers\n\t\n\treferrers = overview[\"referrers\"]\n\treferrers.reverse()\n\tfor referrer, query in referrers[0:recentreferrers]:\n\t\treferrer = referrer.replace(\"&\",\"&amp;\")\n\t\tprint \"\"\"<a href = \"%s\" title = \"%s\" rel = \"nofollow\">%s</a>\"\"\" % (referrer, referrer, justdomain(referrer))\n\t\tif query: print \"<i> - %s</i>\" % query\n\t\tprint \"<br />\"\n\tprint \"</p>\"\n\t\n\tprint  \"\"\"<p class = \"section\"><strong>%s recent popular search terms</strong><br />\"\"\" % recentsearches\n\t\n\tqueries = overview[\"queries\"]\n\tfor query in sortByValue(queries)[0:recentsearches]:\n\t\tquery_score = queries[query]\n\t\tquoted_query = query.replace('\"','%22')\n\t\tprint \"\"\"<a href = \"http://www.google.com/search?q=%(quoted_query)s\">%(query)s</a>: \n\t\t\t%(query_score)s<br />\"\"\" % vars()\n\tprint \"</p>\"\n\ndef urldetails(url, cgiloc):\n\n\tprint \"\"\"<p class = \"section\" id = \"urldetails\">Requests for <b>%s</b><br /><br />\"\"\" % url\n\tcounter = 1\n\tfor line in loglines:\n\t\tresource = line.split(' ')[6]\n\t\tif resource == url and not ignorelines(line):\n\t\t\ttime = line.split(' ')[3].replace('[','')\n\t\t\tif time.startswith(apachetoday): time = time.replace(apachetoday +':','today, ')\n\t\t\tip = line.split(' ')[0]\n\t\t\taddr = getDNS(ip)\n\t\t\tprint \"\"\"%(counter)s: %(time)s: <a href = \"%(cgiloc)s?ip=%(ip)s\">%(addr)s</a>\n\t\t\t<br />\"\"\" % vars()\n\t\t\tcounter = counter + 1\n\tprint \"</p>\"\n\t\t\t\ndef ipdetails(ip, cgiloc):\n\n\timport socket\n\ttry: addr = socket.gethostbyaddr(ip)[0]\n\texcept: addr = 'unknown host'\n\tif addr != 'unknown host': # add successful lookups to the DNS cache\n\t\ttry:\n\t\t\tdb = dbm.open(database, \"c\")\n\t\t\tdb[ip] = addr\n\t\t\tdb.close()\n\t\texcept: pass # fail silently - lots of things could have gone wrong...\n\tprint \"\"\"<p class = \"section\">Visit details for <b>%s</b><br /><b>hostname:</b> %s<br />\"\"\" % (ip, addr)\n\tcounter = 1; pagecounter = 1\n\tfor line in loglines:\n\t\taddress = line.split(' ')[0]\n\t\tif address == ip:\n\t\t\ttime = line.split(' ')[3].replace('[','')\n\t\t\tif time.startswith(apachetoday): time = time.replace(apachetoday +':','today, ')\n\t\t\tresource = line.split(' ')[6]\n\t\t\tif counter == 1:\n\t\t\t\treferrer = line.split('\"')[-4]\n\t\t\t\tuser_agent = line.split('\"')[-2]\n\t\t\t\tif len(user_agent) > 50: user_agent = user_agent[0:50].strip() + \"...\"\n\t\t\t\tif len(referrer) > 1: \n\t\t\t\t\tprint \"\"\"<b>referrer:</b> <a href = \"%(referrer)s\">%(referrer)s</a><br />\"\"\" % vars()\n\t\t\t\tprint \"\"\"<b>browser:</b> %(user_agent)s<br /><br />\"\"\" % vars()\n\t\t\tif ispage(resource):\n\t\t\t\tquotedresource = urllib.quote(resource)\n\t\t\t\tprint \"\"\"%(pagecounter)s: <b>%(time)s</b>: %(resource)s [<a href = \"%(cgiloc)s?url=%(quotedresource)s\">details</a>]\n\t\t\t\t<br />\"\"\" % vars()\n\t\t\t\tpagecounter += 1\n\t\t\tcounter += 1\n\tprint \"</p>\"\t\n\ndef header():\n\tprint \"Content-type: text/html\\n\\n\"\n\tprint \"\"\"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \n\t\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n\t\t<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n\t\t<head>\n\t\t\t<title>peastat</title>\n\t\t\t<link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom\" href=\"http://%s%s?atom=true\" />\"\"\" % (server_name, request_uri)\n\tprint \"\"\"<meta http-equiv=\"content-type\" content=\"text/html\" />\n\t\t\t<meta http-equiv=\"content-language\" content=\"en\" />\n\t\t\t<style>\n\t\t\t\t#container {width: 450px; margin: 10px auto 10px auto; \ttext-align: left; border: dotted 0px #999}\n\t\t\t\tbody{\n\t\t\t\t\tmargin: 0px 0px 0px 0px;\n\t\t\t\t\tbackground-color: #F5F5F5;\n\t\t\t\t\ttext-align: center;\n\t\t\t\t\tfont-family: 'Lucida Grande', 'Lucida Sans Unicode', Lucida, 'Trebuchet MS', Trebuchet, Verdana, Geneva, Arial, Helvetica, sans-serif;\n\t\t\t\t\t#border-color: #CCF; border-width: 6px; border-style: dotted none none none; \n\t\t\t\t\tborder-color: white; border-width: 8px; border-style: dotted none none none; \n\t\t\t\t\tfont-size: small;\n\t\t\t\t\tcolor: #333;line-height: 150%;\n\t\t\t\t}\n\t\t\t\tstrong {color:orange}\n\t\t\t\ta:visited, a:active, a:link {color: #C30; text-decoration: none; border-bottom: dotted 1px #999;}\n\t\t\t\ta:hover {color: red; text-decoration: none; border-bottom: dotted 1px #999;}\n\t\t\t\th4 {font-weight: bold; font-size: 26px; color: #666; margin-bottom: 3px; margin-top:3px}\n\t\t\t\th4 a {border-bottom: dotted 0px white !important}\n\t\t\t\t.section {padding:4px;  border:1px solid #ddd; background-color:#FFF}\n\t\t\t\t.greysection {\n\t\t\t\t\tpadding:4px;  border:1px solid #ddd; background-color:#F5F5F5;\n\t\t\t\t\tcolor:grey}\n\t\t\t\t.greysection a {color: gray}\n\t\t\t\t.section:hover {border:1px dotted red;}\n\t\t\t\t#urldetails a:visited {color:#333;}\n\t\t\t</style>\n\t\t\t<script type=\"text/javascript\">\n\t\t\t\t// simple AJAX library\n\t\t\t\t// see http://homepage.mac.com/kevinmarks/staticjah.html\n\t\t\t\tfunction jah(url,target) {\n\t\t\t\t\t// native XMLHttpRequest object\n\t\t\t\t\tdocument.getElementById(target).innerHTML = 'sending...';\n\t\t\t\t\tif (window.XMLHttpRequest) {\n\t\t\t\t\t\treq = new XMLHttpRequest();\n\t\t\t\t\t\treq.onreadystatechange = function() {jahDone(target);};\n\t\t\t\t\t\treq.open(\"GET\", url, true);\n\t\t\t\t\t\treq.send(null);\n\t\t\t\t\t// IE/Windows ActiveX version\n\t\t\t\t\t} else if (window.ActiveXObject) {\n\t\t\t\t\t\treq = new ActiveXObject(\"Microsoft.XMLHTTP\");\n\t\t\t\t\t\tif (req) {\n\t\t\t\t\t\t\treq.onreadystatechange = function() {jahDone(target);};\n\t\t\t\t\t\t\treq.open(\"GET\", url, true);\n\t\t\t\t\t\t\treq.send();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}    \n\t\t\t\tfunction jahDone(target) {\n\t\t\t\t\t// only if req is \"loaded\"\n\t\t\t\t\tif (req.readyState == 4) {\n\t\t\t\t\t\t// only if \"OK\"\n\t\t\t\t\t\tif (req.status == 200) {\n\t\t\t\t\t\t\tresults = req.responseText;\n\t\t\t\t\t\t\tdocument.getElementById(target).innerHTML = results;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdocument.getElementById(target).innerHTML=\"jah error: \" + req.statusText;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</script>\n\t\t</head>\n\t\t<body><div id = \"container\">\"\"\"\n\t\n\tprint \"\"\"<h4><a href = \"%s\">peastat</a></h4>\"\"\" % (cgiloc)\n\t\t\ndef footer(): print \"\"\"\n\t<p class = \"greysection\">\n\t\tpeastat %s \n\t\t&copy; <a href = \"http://www.throwingbeans.org/\">tom dyson</a> 2005 // \n\t\t<a href = \"http://www.throwingbeans.org/peastat/\">updates, bugs, suggestions</a>\n\t</p>\n\t</div></body></html>\"\"\" % (__version__)\n\ndef atomHeader():\n\tbasehref = server_name + request_uri\n\tcleanurl = rooturl.replace(\"http://\",\"\")\n\ttimestamp = time.strftime(\"%Y-%m-%dT%H:%M:%SZ\")\n\tprint \"\"\"Content-type: application/atom+xml\\n\\n<?xml version='1.0' encoding='UTF-8'?>\n\t\t<feed xmlns=\"http://www.w3.org/2005/Atom\">\n\t\t\t<title>peastat for %(cleanurl)s</title>\n\t\t\t<link href=\"http://%(basehref)s/\"/>\n\t\t\t<updated>%(timestamp)s</updated>\n\t\t\t<author><name>peastat</name></author>\n\t\t\t<id>http://%(basehref)s/</id>\"\"\" % vars()\n\t\t\t\t\t\ndef atomSummary(overview):\n\tbasehref = server_name + request_uri\n\tcleanurl = rooturl.replace(\"http://\",\"\")\n\ttimestamp = time.strftime(\"%Y-%m-%dT%H:%M:%SZ\")\n\tprint \"\"\"<entry>\n\t\t<title>Summary for %(cleanurl)s</title>\n\t\t<link href='%(basehref)s' />\n\t\t<id>http://%(basehref)s</id>\n\t\t<updated>%(timestamp)s</updated>\n\t\t<content type=\"xhtml\">\n      \t\t<div xmlns=\"http://www.w3.org/1999/xhtml\">\"\"\" % vars()\n\t\t\t\n\tdisplayOverviewHTML(overview)\n\t\t\t\n\tprint \"\"\"</div></content></entry>\"\"\"\n\t\t\t\ndef atomFooter():\n\tprint \"</feed>\"\n\nif __name__ == \"__main__\":\n\tif atom:\n\t\tatomHeader()\n\t\toverview = getOverview()\n\t\tatomSummary(overview)\n\t\tatomFooter()\n\telse:\n\t\theader()\n\t\tif url: urldetails(url, cgiloc)\n\t\telif ip: ipdetails(ip, cgiloc)\n\t\telse: \n\t\t\toverview = getOverview()\n\t\t\tdisplayOverviewHTML(overview)\n\t\tfooter()\n"
  },
  {
    "path": "Python/DjangoBook/themes/djangobook/static/reset-min.css",
    "content": "/* Copyright (c) 2006, Yahoo! Inc. All rights reserved. Code licensed under the BSD License:http://developer.yahoo.net/yui/license.txt Version: 0.11.3 */\nbody,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}"
  },
  {
    "path": "Python/DjangoBook/themes/djangobook/theme.conf.txt",
    "content": "[theme]\ninherit = none\nstylesheet = djangobook.css\npygments_style = sphinx\n"
  },
  {
    "path": "README.md",
    "content": "# programming-ebooks-to-help-you-code-better\n\nThis are some of  the eBooks I use to learn coding\n\n"
  }
]