mirror of
				https://github.com/django/django.git
				synced 2025-11-03 21:25:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			729 lines
		
	
	
	
		
			28 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			729 lines
		
	
	
	
		
			28 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
=====================================
 | 
						|
Writing your first Django app, part 1
 | 
						|
=====================================
 | 
						|
 | 
						|
Let's learn by example.
 | 
						|
 | 
						|
Throughout this tutorial, we'll walk you through the creation of a basic
 | 
						|
poll application.
 | 
						|
 | 
						|
It'll consist of two parts:
 | 
						|
 | 
						|
* A public site that lets people view polls and vote in them.
 | 
						|
* An admin site that lets you add, change and delete polls.
 | 
						|
 | 
						|
We'll assume you have :doc:`Django installed </intro/install>` already. You can
 | 
						|
tell Django is installed and which version by running the following command:
 | 
						|
 | 
						|
.. code-block:: bash
 | 
						|
 | 
						|
    python -c "import django; print(django.get_version())"
 | 
						|
 | 
						|
If Django is installed, you should see the version of your installation. If it
 | 
						|
isn't, you'll get an error telling "No module named django".
 | 
						|
 | 
						|
This tutorial is written for Django |version| and Python 2.x. If the Django
 | 
						|
version doesn't match, you can refer to the tutorial for your version of
 | 
						|
Django by using the version switcher at the bottom right corner of this page,
 | 
						|
or update Django to the newest version. If you are using Python 3.x, be aware
 | 
						|
that your code may need to differ from what is in the tutorial and you should
 | 
						|
continue using the tutorial only if you know what you are doing with Python
 | 
						|
3.x.
 | 
						|
 | 
						|
See :doc:`How to install Django </topics/install>` for advice on how to remove
 | 
						|
older versions of Django and install a newer one.
 | 
						|
 | 
						|
.. admonition:: Where to get help:
 | 
						|
 | 
						|
    If you're having trouble going through this tutorial, please post a message
 | 
						|
    to `django-users`__ or drop by `#django on irc.freenode.net`__ to chat
 | 
						|
    with other Django users who might be able to help.
 | 
						|
 | 
						|
__ http://groups.google.com/group/django-users
 | 
						|
__ irc://irc.freenode.net/django
 | 
						|
 | 
						|
Creating a project
 | 
						|
==================
 | 
						|
 | 
						|
If this is your first time using Django, you'll have to take care of some
 | 
						|
initial setup. Namely, you'll need to auto-generate some code that establishes a
 | 
						|
Django :term:`project` -- a collection of settings for an instance of Django,
 | 
						|
including database configuration, Django-specific options and
 | 
						|
application-specific settings.
 | 
						|
 | 
						|
From the command line, ``cd`` into a directory where you'd like to store your
 | 
						|
code, then run the following command:
 | 
						|
 | 
						|
.. code-block:: bash
 | 
						|
 | 
						|
   django-admin.py startproject mysite
 | 
						|
 | 
						|
This will create a ``mysite`` directory in your current directory. If it didn't
 | 
						|
work, see :ref:`troubleshooting-django-admin-py`.
 | 
						|
 | 
						|
.. note::
 | 
						|
 | 
						|
    You'll need to avoid naming projects after built-in Python or Django
 | 
						|
    components. In particular, this means you should avoid using names like
 | 
						|
    ``django`` (which will conflict with Django itself) or ``test`` (which
 | 
						|
    conflicts with a built-in Python package).
 | 
						|
 | 
						|
.. admonition:: Where should this code live?
 | 
						|
 | 
						|
    If your background is in plain old PHP (with no use of modern frameworks),
 | 
						|
    you're probably used to putting code under the Web server's document root
 | 
						|
    (in a place such as ``/var/www``). With Django, you don't do that. It's
 | 
						|
    not a good idea to put any of this Python code within your Web server's
 | 
						|
    document root, because it risks the possibility that people may be able
 | 
						|
    to view your code over the Web. That's not good for security.
 | 
						|
 | 
						|
    Put your code in some directory **outside** of the document root, such as
 | 
						|
    :file:`/home/mycode`.
 | 
						|
 | 
						|
Let's look at what :djadmin:`startproject` created::
 | 
						|
 | 
						|
    mysite/
 | 
						|
        manage.py
 | 
						|
        mysite/
 | 
						|
            __init__.py
 | 
						|
            settings.py
 | 
						|
            urls.py
 | 
						|
            wsgi.py
 | 
						|
 | 
						|
.. admonition:: Doesn't match what you see?
 | 
						|
 | 
						|
    The default project layout recently changed. If you're seeing a "flat"
 | 
						|
    layout (with no inner :file:`mysite/` directory), you're probably using
 | 
						|
    a version of Django that doesn't match this tutorial version.  You'll
 | 
						|
    want to either switch to the older tutorial or the newer Django version.
 | 
						|
 | 
						|
These files are:
 | 
						|
 | 
						|
* The outer :file:`mysite/` root directory is just a container for your
 | 
						|
  project. Its name doesn't matter to Django; you can rename it to anything
 | 
						|
  you like.
 | 
						|
 | 
						|
* :file:`manage.py`: A command-line utility that lets you interact with this
 | 
						|
  Django project in various ways. You can read all the details about
 | 
						|
  :file:`manage.py` in :doc:`/ref/django-admin`.
 | 
						|
 | 
						|
* The inner :file:`mysite/` directory is the actual Python package for your
 | 
						|
  project. Its name is the Python package name you'll need to use to import
 | 
						|
  anything inside it (e.g. ``mysite.urls``).
 | 
						|
 | 
						|
* :file:`mysite/__init__.py`: An empty file that tells Python that this
 | 
						|
  directory should be considered a Python package. (Read `more about
 | 
						|
  packages`_ in the official Python docs if you're a Python beginner.)
 | 
						|
 | 
						|
* :file:`mysite/settings.py`: Settings/configuration for this Django
 | 
						|
  project.  :doc:`/topics/settings` will tell you all about how settings
 | 
						|
  work.
 | 
						|
 | 
						|
* :file:`mysite/urls.py`: The URL declarations for this Django project; a
 | 
						|
  "table of contents" of your Django-powered site. You can read more about
 | 
						|
  URLs in :doc:`/topics/http/urls`.
 | 
						|
 | 
						|
* :file:`mysite/wsgi.py`: An entry-point for WSGI-compatible web servers to
 | 
						|
  serve your project. See :doc:`/howto/deployment/wsgi/index` for more details.
 | 
						|
 | 
						|
.. _more about packages: http://docs.python.org/tutorial/modules.html#packages
 | 
						|
 | 
						|
The development server
 | 
						|
----------------------
 | 
						|
 | 
						|
Let's verify this worked. Change into the outer :file:`mysite` directory, if
 | 
						|
you haven't already, and run the command ``python manage.py runserver``. You'll
 | 
						|
see the following output on the command line:
 | 
						|
 | 
						|
.. parsed-literal::
 | 
						|
 | 
						|
    Validating models...
 | 
						|
 | 
						|
    0 errors found
 | 
						|
    |today| - 15:50:53
 | 
						|
    Django version |version|, using settings 'mysite.settings'
 | 
						|
    Starting development server at http://127.0.0.1:8000/
 | 
						|
    Quit the server with CONTROL-C.
 | 
						|
 | 
						|
You've started the Django development server, a lightweight Web server written
 | 
						|
purely in Python. We've included this with Django so you can develop things
 | 
						|
rapidly, without having to deal with configuring a production server -- such as
 | 
						|
Apache -- until you're ready for production.
 | 
						|
 | 
						|
Now's a good time to note: **Don't** use this server in anything resembling a
 | 
						|
production environment. It's intended only for use while developing. (We're in
 | 
						|
the business of making Web frameworks, not Web servers.)
 | 
						|
 | 
						|
Now that the server's running, visit http://127.0.0.1:8000/ with your Web
 | 
						|
browser. You'll see a "Welcome to Django" page, in pleasant, light-blue pastel.
 | 
						|
It worked!
 | 
						|
 | 
						|
.. admonition:: Changing the port
 | 
						|
 | 
						|
    By default, the :djadmin:`runserver` command starts the development server
 | 
						|
    on the internal IP at port 8000.
 | 
						|
 | 
						|
    If you want to change the server's port, pass
 | 
						|
    it as a command-line argument. For instance, this command starts the server
 | 
						|
    on port 8080:
 | 
						|
 | 
						|
    .. code-block:: bash
 | 
						|
 | 
						|
        python manage.py runserver 8080
 | 
						|
 | 
						|
    If you want to change the server's IP, pass it along with the port. So to
 | 
						|
    listen on all public IPs (useful if you want to show off your work on other
 | 
						|
    computers), use:
 | 
						|
 | 
						|
    .. code-block:: bash
 | 
						|
 | 
						|
        python manage.py runserver 0.0.0.0:8000
 | 
						|
 | 
						|
    Full docs for the development server can be found in the
 | 
						|
    :djadmin:`runserver` reference.
 | 
						|
 | 
						|
Database setup
 | 
						|
--------------
 | 
						|
 | 
						|
Now, edit :file:`mysite/settings.py`. It's a normal Python module with
 | 
						|
module-level variables representing Django settings.
 | 
						|
 | 
						|
By default, the configuration uses SQLite. If you're new to databases, or
 | 
						|
you're just interested in trying Django, this is the easiest choice. SQLite is
 | 
						|
included in Python, so you won't need to install anything else to support your
 | 
						|
database.
 | 
						|
 | 
						|
If you wish to use another database, install the appropriate :ref:`database
 | 
						|
bindings <database-installation>`, and change the following keys in the
 | 
						|
:setting:`DATABASES` ``'default'`` item to match your database connection
 | 
						|
settings:
 | 
						|
 | 
						|
* :setting:`ENGINE <DATABASE-ENGINE>` -- Either
 | 
						|
  ``'django.db.backends.sqlite3'``,
 | 
						|
  ``'django.db.backends.postgresql_psycopg2'``,
 | 
						|
  ``'django.db.backends.mysql'``, or
 | 
						|
  ``'django.db.backends.oracle'``. Other backends are :setting:`also available
 | 
						|
  <DATABASE-ENGINE>`.
 | 
						|
 | 
						|
* :setting:`NAME` -- The name of your database. If you're using SQLite, the
 | 
						|
  database will be a file on your computer; in that case, :setting:`NAME`
 | 
						|
  should be the full absolute path, including filename, of that file. The
 | 
						|
  default value, ``os.path.join(BASE_DIR, 'db.sqlite3')``, will store the file
 | 
						|
  in your project directory.
 | 
						|
 | 
						|
If you are not using SQLite as your database, additional settings such as :setting:`USER`, :setting:`PASSWORD`, :setting:`HOST` must be added.
 | 
						|
For more details, see the reference documentation for :setting:`DATABASES`.
 | 
						|
 | 
						|
.. note::
 | 
						|
 | 
						|
    If you're using PostgreSQL or MySQL, make sure you've created a database by
 | 
						|
    this point. Do that with "``CREATE DATABASE database_name;``" within your
 | 
						|
    database's interactive prompt.
 | 
						|
 | 
						|
    If you're using SQLite, you don't need to create anything beforehand - the
 | 
						|
    database file will be created automatically when it is needed.
 | 
						|
 | 
						|
While you're editing :file:`mysite/settings.py`, set :setting:`TIME_ZONE` to
 | 
						|
your time zone.
 | 
						|
 | 
						|
Also, note the :setting:`INSTALLED_APPS` setting at the top of the file. That
 | 
						|
holds the names of all Django applications that are activated in this Django
 | 
						|
instance. Apps can be used in multiple projects, and you can package and
 | 
						|
distribute them for use by others in their projects.
 | 
						|
 | 
						|
By default, :setting:`INSTALLED_APPS` contains the following apps, all of which
 | 
						|
come with Django:
 | 
						|
 | 
						|
* :mod:`django.contrib.admin` -- The admin site. You'll use it in :doc:`part 2
 | 
						|
  of this tutorial </intro/tutorial02>`.
 | 
						|
 | 
						|
* :mod:`django.contrib.auth` -- An authentication system.
 | 
						|
 | 
						|
* :mod:`django.contrib.contenttypes` -- A framework for content types.
 | 
						|
 | 
						|
* :mod:`django.contrib.sessions` -- A session framework.
 | 
						|
 | 
						|
* :mod:`django.contrib.messages` -- A messaging framework.
 | 
						|
 | 
						|
* :mod:`django.contrib.staticfiles` -- A framework for managing
 | 
						|
  static files.
 | 
						|
 | 
						|
These applications are included by default as a convenience for the common case.
 | 
						|
 | 
						|
Some of these applications makes use of at least one database table, though,
 | 
						|
so we need to create the tables in the database before we can use them. To do
 | 
						|
that, run the following command:
 | 
						|
 | 
						|
.. code-block:: bash
 | 
						|
 | 
						|
    python manage.py syncdb
 | 
						|
 | 
						|
The :djadmin:`syncdb` command looks at the :setting:`INSTALLED_APPS` setting
 | 
						|
and creates any necessary database tables according to the database settings
 | 
						|
in your :file:`mysite/settings.py` file. You'll see a message for each
 | 
						|
database table it creates, and you'll get a prompt asking you if you'd like to
 | 
						|
create a superuser account for the authentication system. Go ahead and do
 | 
						|
that.
 | 
						|
 | 
						|
If you're interested, run the command-line client for your database and type
 | 
						|
``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to
 | 
						|
display the tables Django created.
 | 
						|
 | 
						|
.. admonition:: For the minimalists
 | 
						|
 | 
						|
    Like we said above, the default applications are included for the common
 | 
						|
    case, but not everybody needs them. If you don't need any or all of them,
 | 
						|
    feel free to comment-out or delete the appropriate line(s) from
 | 
						|
    :setting:`INSTALLED_APPS` before running :djadmin:`syncdb`. The
 | 
						|
    :djadmin:`syncdb` command will only create tables for apps in
 | 
						|
    :setting:`INSTALLED_APPS`.
 | 
						|
 | 
						|
.. _creating-models:
 | 
						|
 | 
						|
Creating models
 | 
						|
===============
 | 
						|
 | 
						|
Now that your environment -- a "project" -- is set up, you're set to start
 | 
						|
doing work.
 | 
						|
 | 
						|
Each application you write in Django consists of a Python package that follows
 | 
						|
a certain convention. Django comes with a utility that automatically generates
 | 
						|
the basic directory structure of an app, so you can focus on writing code
 | 
						|
rather than creating directories.
 | 
						|
 | 
						|
.. admonition:: Projects vs. apps
 | 
						|
 | 
						|
    What's the difference between a project and an app? An app is a Web
 | 
						|
    application that does something -- e.g., a Weblog system, a database of
 | 
						|
    public records or a simple poll app. A project is a collection of
 | 
						|
    configuration and apps for a particular Web site. A project can contain
 | 
						|
    multiple apps. An app can be in multiple projects.
 | 
						|
 | 
						|
Your apps can live anywhere on your `Python path`_. In this tutorial, we'll
 | 
						|
create our poll app right next to your :file:`manage.py` file so that it can be
 | 
						|
imported as its own top-level module, rather than a submodule of ``mysite``.
 | 
						|
 | 
						|
To create your app, make sure you're in the same directory as :file:`manage.py`
 | 
						|
and type this command:
 | 
						|
 | 
						|
.. code-block:: bash
 | 
						|
 | 
						|
    python manage.py startapp polls
 | 
						|
 | 
						|
That'll create a directory :file:`polls`, which is laid out like this::
 | 
						|
 | 
						|
    polls/
 | 
						|
        __init__.py
 | 
						|
        admin.py
 | 
						|
        models.py
 | 
						|
        tests.py
 | 
						|
        views.py
 | 
						|
 | 
						|
This directory structure will house the poll application.
 | 
						|
 | 
						|
The first step in writing a database Web app in Django is to define your models
 | 
						|
-- essentially, your database layout, with additional metadata.
 | 
						|
 | 
						|
.. admonition:: Philosophy
 | 
						|
 | 
						|
   A model is the single, definitive source of data about your data. It contains
 | 
						|
   the essential fields and behaviors of the data you're storing. Django follows
 | 
						|
   the :ref:`DRY Principle <dry>`. The goal is to define your data model in one
 | 
						|
   place and automatically derive things from it.
 | 
						|
 | 
						|
In our simple poll app, we'll create two models: ``Poll`` and ``Choice``.
 | 
						|
A ``Poll`` has a question and a publication date. A ``Choice`` has two fields:
 | 
						|
the text of the choice and a vote tally. Each ``Choice`` is associated with a
 | 
						|
``Poll``.
 | 
						|
 | 
						|
These concepts are represented by simple Python classes. Edit the
 | 
						|
:file:`polls/models.py` file so it looks like this::
 | 
						|
 | 
						|
    from django.db import models
 | 
						|
 | 
						|
    class Poll(models.Model):
 | 
						|
        question = models.CharField(max_length=200)
 | 
						|
        pub_date = models.DateTimeField('date published')
 | 
						|
 | 
						|
    class Choice(models.Model):
 | 
						|
        poll = models.ForeignKey(Poll)
 | 
						|
        choice_text = models.CharField(max_length=200)
 | 
						|
        votes = models.IntegerField(default=0)
 | 
						|
 | 
						|
The code is straightforward. Each model is represented by a class that
 | 
						|
subclasses :class:`django.db.models.Model`. Each model has a number of class
 | 
						|
variables, each of which represents a database field in the model.
 | 
						|
 | 
						|
Each field is represented by an instance of a :class:`~django.db.models.Field`
 | 
						|
class -- e.g., :class:`~django.db.models.CharField` for character fields and
 | 
						|
:class:`~django.db.models.DateTimeField` for datetimes. This tells Django what
 | 
						|
type of data each field holds.
 | 
						|
 | 
						|
The name of each :class:`~django.db.models.Field` instance (e.g. ``question`` or
 | 
						|
``pub_date``) is the field's name, in machine-friendly format. You'll use this
 | 
						|
value in your Python code, and your database will use it as the column name.
 | 
						|
 | 
						|
You can use an optional first positional argument to a
 | 
						|
:class:`~django.db.models.Field` to designate a human-readable name. That's used
 | 
						|
in a couple of introspective parts of Django, and it doubles as documentation.
 | 
						|
If this field isn't provided, Django will use the machine-readable name. In this
 | 
						|
example, we've only defined a human-readable name for ``Poll.pub_date``. For all
 | 
						|
other fields in this model, the field's machine-readable name will suffice as
 | 
						|
its human-readable name.
 | 
						|
 | 
						|
Some :class:`~django.db.models.Field` classes have required arguments.
 | 
						|
:class:`~django.db.models.CharField`, for example, requires that you give it a
 | 
						|
:attr:`~django.db.models.CharField.max_length`. That's used not only in the
 | 
						|
database schema, but in validation, as we'll soon see.
 | 
						|
 | 
						|
A :class:`~django.db.models.Field` can also have various optional arguments; in
 | 
						|
this case, we've set the :attr:`~django.db.models.Field.default` value of
 | 
						|
``votes`` to 0.
 | 
						|
 | 
						|
Finally, note a relationship is defined, using
 | 
						|
:class:`~django.db.models.ForeignKey`. That tells Django each ``Choice`` is related
 | 
						|
to a single ``Poll``. Django supports all the common database relationships:
 | 
						|
many-to-ones, many-to-manys and one-to-ones.
 | 
						|
 | 
						|
.. _`Python path`: http://docs.python.org/tutorial/modules.html#the-module-search-path
 | 
						|
 | 
						|
Activating models
 | 
						|
=================
 | 
						|
 | 
						|
That small bit of model code gives Django a lot of information. With it, Django
 | 
						|
is able to:
 | 
						|
 | 
						|
* Create a database schema (``CREATE TABLE`` statements) for this app.
 | 
						|
* Create a Python database-access API for accessing ``Poll`` and ``Choice`` objects.
 | 
						|
 | 
						|
But first we need to tell our project that the ``polls`` app is installed.
 | 
						|
 | 
						|
.. admonition:: Philosophy
 | 
						|
 | 
						|
    Django apps are "pluggable": You can use an app in multiple projects, and
 | 
						|
    you can distribute apps, because they don't have to be tied to a given
 | 
						|
    Django installation.
 | 
						|
 | 
						|
Edit the :file:`mysite/settings.py` file again, and change the
 | 
						|
:setting:`INSTALLED_APPS` setting to include the string ``'polls'``. So it'll
 | 
						|
look like this::
 | 
						|
 | 
						|
    INSTALLED_APPS = (
 | 
						|
        'django.contrib.admin',
 | 
						|
        'django.contrib.auth',
 | 
						|
        'django.contrib.contenttypes',
 | 
						|
        'django.contrib.sessions',
 | 
						|
        'django.contrib.messages',
 | 
						|
        'django.contrib.staticfiles',
 | 
						|
        'polls',
 | 
						|
    )
 | 
						|
 | 
						|
Now Django knows to include the ``polls`` app. Let's run another command:
 | 
						|
 | 
						|
.. code-block:: bash
 | 
						|
 | 
						|
    python manage.py sql polls
 | 
						|
 | 
						|
You should see something similar to the following (the ``CREATE TABLE`` SQL
 | 
						|
statements for the polls app):
 | 
						|
 | 
						|
.. code-block:: sql
 | 
						|
 | 
						|
    BEGIN;
 | 
						|
    CREATE TABLE "polls_poll" (
 | 
						|
        "id" integer NOT NULL PRIMARY KEY,
 | 
						|
        "question" varchar(200) NOT NULL,
 | 
						|
        "pub_date" datetime NOT NULL
 | 
						|
    );
 | 
						|
    CREATE TABLE "polls_choice" (
 | 
						|
        "id" integer NOT NULL PRIMARY KEY,
 | 
						|
        "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"),
 | 
						|
        "choice_text" varchar(200) NOT NULL,
 | 
						|
        "votes" integer NOT NULL
 | 
						|
    );
 | 
						|
    COMMIT;
 | 
						|
 | 
						|
Note the following:
 | 
						|
 | 
						|
* The exact output will vary depending on the database you are using. The
 | 
						|
  example above is generated for SQLite.
 | 
						|
 | 
						|
* Table names are automatically generated by combining the name of the app
 | 
						|
  (``polls``) and the lowercase name of the model -- ``poll`` and
 | 
						|
  ``choice``. (You can override this behavior.)
 | 
						|
 | 
						|
* Primary keys (IDs) are added automatically. (You can override this, too.)
 | 
						|
 | 
						|
* By convention, Django appends ``"_id"`` to the foreign key field name.
 | 
						|
  (Yes, you can override this, as well.)
 | 
						|
 | 
						|
* The foreign key relationship is made explicit by a ``REFERENCES``
 | 
						|
  statement.
 | 
						|
 | 
						|
* It's tailored to the database you're using, so database-specific field
 | 
						|
  types such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or
 | 
						|
  ``integer primary key`` (SQLite) are handled for you automatically. Same
 | 
						|
  goes for quoting of field names -- e.g., using double quotes or single
 | 
						|
  quotes.
 | 
						|
 | 
						|
* The :djadmin:`sql` command doesn't actually run the SQL in your database -
 | 
						|
  it just prints it to the screen so that you can see what SQL Django thinks
 | 
						|
  is required. If you wanted to, you could copy and paste this SQL into your
 | 
						|
  database prompt. However, as we will see shortly, Django provides an
 | 
						|
  easier way of committing the SQL to the database.
 | 
						|
 | 
						|
If you're interested, also run the following commands:
 | 
						|
 | 
						|
* :djadmin:`python manage.py validate <validate>` -- Checks for any errors
 | 
						|
  in the construction of your models.
 | 
						|
 | 
						|
* :djadmin:`python manage.py sqlcustom polls <sqlcustom>` -- Outputs any
 | 
						|
  :ref:`custom SQL statements <initial-sql>` (such as table modifications or
 | 
						|
  constraints) that are defined for the application.
 | 
						|
 | 
						|
* :djadmin:`python manage.py sqlclear polls <sqlclear>` -- Outputs the
 | 
						|
  necessary ``DROP TABLE`` statements for this app, according to which
 | 
						|
  tables already exist in your database (if any).
 | 
						|
 | 
						|
* :djadmin:`python manage.py sqlindexes polls <sqlindexes>` -- Outputs the
 | 
						|
  ``CREATE INDEX`` statements for this app.
 | 
						|
 | 
						|
* :djadmin:`python manage.py sqlall polls <sqlall>` -- A combination of all
 | 
						|
  the SQL from the :djadmin:`sql`, :djadmin:`sqlcustom`, and
 | 
						|
  :djadmin:`sqlindexes` commands.
 | 
						|
 | 
						|
Looking at the output of those commands can help you understand what's actually
 | 
						|
happening under the hood.
 | 
						|
 | 
						|
Now, run :djadmin:`syncdb` again to create those model tables in your database:
 | 
						|
 | 
						|
.. code-block:: bash
 | 
						|
 | 
						|
    python manage.py syncdb
 | 
						|
 | 
						|
The :djadmin:`syncdb` command runs the SQL from :djadmin:`sqlall` on your
 | 
						|
database for all apps in :setting:`INSTALLED_APPS` that don't already exist in
 | 
						|
your database. This creates all the tables, initial data and indexes for any
 | 
						|
apps you've added to your project since the last time you ran syncdb.
 | 
						|
:djadmin:`syncdb` can be called as often as you like, and it will only ever
 | 
						|
create the tables that don't exist.
 | 
						|
 | 
						|
Read the :doc:`django-admin.py documentation </ref/django-admin>` for full
 | 
						|
information on what the ``manage.py`` utility can do.
 | 
						|
 | 
						|
Playing with the API
 | 
						|
====================
 | 
						|
 | 
						|
Now, let's hop into the interactive Python shell and play around with the free
 | 
						|
API Django gives you. To invoke the Python shell, use this command:
 | 
						|
 | 
						|
.. code-block:: bash
 | 
						|
 | 
						|
    python manage.py shell
 | 
						|
 | 
						|
We're using this instead of simply typing "python", because :file:`manage.py`
 | 
						|
sets the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives Django
 | 
						|
the Python import path to your :file:`mysite/settings.py` file.
 | 
						|
 | 
						|
.. admonition:: Bypassing manage.py
 | 
						|
 | 
						|
    If you'd rather not use :file:`manage.py`, no problem. Just set the
 | 
						|
    ``DJANGO_SETTINGS_MODULE`` environment variable to ``mysite.settings`` and
 | 
						|
    run ``python`` from the same directory :file:`manage.py` is in (or ensure
 | 
						|
    that directory is on the Python path, so that ``import mysite`` works).
 | 
						|
 | 
						|
    For more information on all of this, see the :doc:`django-admin.py
 | 
						|
    documentation </ref/django-admin>`.
 | 
						|
 | 
						|
Once you're in the shell, explore the :doc:`database API </topics/db/queries>`::
 | 
						|
 | 
						|
    >>> from polls.models import Poll, Choice   # Import the model classes we just wrote.
 | 
						|
 | 
						|
    # No polls are in the system yet.
 | 
						|
    >>> Poll.objects.all()
 | 
						|
    []
 | 
						|
 | 
						|
    # Create a new Poll.
 | 
						|
    # Support for time zones is enabled in the default settings file, so
 | 
						|
    # Django expects a datetime with tzinfo for pub_date. Use timezone.now()
 | 
						|
    # instead of datetime.datetime.now() and it will do the right thing.
 | 
						|
    >>> from django.utils import timezone
 | 
						|
    >>> p = Poll(question="What's new?", pub_date=timezone.now())
 | 
						|
 | 
						|
    # Save the object into the database. You have to call save() explicitly.
 | 
						|
    >>> p.save()
 | 
						|
 | 
						|
    # Now it has an ID. Note that this might say "1L" instead of "1", depending
 | 
						|
    # on which database you're using. That's no biggie; it just means your
 | 
						|
    # database backend prefers to return integers as Python long integer
 | 
						|
    # objects.
 | 
						|
    >>> p.id
 | 
						|
    1
 | 
						|
 | 
						|
    # Access database columns via Python attributes.
 | 
						|
    >>> p.question
 | 
						|
    "What's new?"
 | 
						|
    >>> p.pub_date
 | 
						|
    datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
 | 
						|
 | 
						|
    # Change values by changing the attributes, then calling save().
 | 
						|
    >>> p.question = "What's up?"
 | 
						|
    >>> p.save()
 | 
						|
 | 
						|
    # objects.all() displays all the polls in the database.
 | 
						|
    >>> Poll.objects.all()
 | 
						|
    [<Poll: Poll object>]
 | 
						|
 | 
						|
 | 
						|
Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful representation
 | 
						|
of this object. Let's fix that by editing the polls model (in the
 | 
						|
``polls/models.py`` file) and adding a
 | 
						|
:meth:`~django.db.models.Model.__unicode__` method to both ``Poll`` and
 | 
						|
``Choice``. On Python 3, simply replace ``__unicode__`` by ``__str__`` in the
 | 
						|
following example::
 | 
						|
 | 
						|
    from django.db import models
 | 
						|
 | 
						|
    class Poll(models.Model):
 | 
						|
        # ...
 | 
						|
        def __unicode__(self):  # Python 3: def __str__(self):
 | 
						|
            return self.question
 | 
						|
 | 
						|
    class Choice(models.Model):
 | 
						|
        # ...
 | 
						|
        def __unicode__(self):  # Python 3: def __str__(self):
 | 
						|
            return self.choice_text
 | 
						|
 | 
						|
It's important to add :meth:`~django.db.models.Model.__unicode__` methods (or
 | 
						|
:meth:`~django.db.models.Model.__str__` on Python 3) to your models, not only
 | 
						|
for your own sanity when dealing with the interactive prompt, but also because
 | 
						|
objects' representations are used throughout Django's automatically-generated
 | 
						|
admin.
 | 
						|
 | 
						|
.. admonition:: ``__unicode__`` or ``__str__``?
 | 
						|
 | 
						|
    On Python 3, things are simpler, just use
 | 
						|
    :meth:`~django.db.models.Model.__str__` and forget about
 | 
						|
    :meth:`~django.db.models.Model.__unicode__`.
 | 
						|
 | 
						|
    If you're familiar with Python 2, you might be in the habit of adding
 | 
						|
    :meth:`~django.db.models.Model.__str__` methods to your classes, not
 | 
						|
    :meth:`~django.db.models.Model.__unicode__` methods. We use
 | 
						|
    :meth:`~django.db.models.Model.__unicode__` here because Django models deal
 | 
						|
    with Unicode by default. All data stored in your database is converted to
 | 
						|
    Unicode when it's returned.
 | 
						|
 | 
						|
    Django models have a default :meth:`~django.db.models.Model.__str__` method
 | 
						|
    that calls :meth:`~django.db.models.Model.__unicode__` and converts the
 | 
						|
    result to a UTF-8 bytestring. This means that ``unicode(p)`` will return a
 | 
						|
    Unicode string, and ``str(p)`` will return a normal string, with characters
 | 
						|
    encoded as UTF-8.
 | 
						|
 | 
						|
    If all of this is gibberish to you, just remember to add
 | 
						|
    :meth:`~django.db.models.Model.__unicode__` methods to your models. With any
 | 
						|
    luck, things should Just Work for you.
 | 
						|
 | 
						|
Note these are normal Python methods. Let's add a custom method, just for
 | 
						|
demonstration::
 | 
						|
 | 
						|
    import datetime
 | 
						|
    from django.utils import timezone
 | 
						|
    # ...
 | 
						|
    class Poll(models.Model):
 | 
						|
        # ...
 | 
						|
        def was_published_recently(self):
 | 
						|
            return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
 | 
						|
 | 
						|
Note the addition of ``import datetime`` and ``from django.utils import
 | 
						|
timezone``, to reference Python's standard :mod:`datetime` module and Django's
 | 
						|
time-zone-related utilities in :mod:`django.utils.timezone`, respectively. If
 | 
						|
you aren't familiar with time zone handling in Python, you can learn more in
 | 
						|
the :doc:`time zone support docs </topics/i18n/timezones>`.
 | 
						|
 | 
						|
Save these changes and start a new Python interactive shell by running
 | 
						|
``python manage.py shell`` again::
 | 
						|
 | 
						|
    >>> from polls.models import Poll, Choice
 | 
						|
 | 
						|
    # Make sure our __unicode__() addition worked.
 | 
						|
    >>> Poll.objects.all()
 | 
						|
    [<Poll: What's up?>]
 | 
						|
 | 
						|
    # Django provides a rich database lookup API that's entirely driven by
 | 
						|
    # keyword arguments.
 | 
						|
    >>> Poll.objects.filter(id=1)
 | 
						|
    [<Poll: What's up?>]
 | 
						|
    >>> Poll.objects.filter(question__startswith='What')
 | 
						|
    [<Poll: What's up?>]
 | 
						|
 | 
						|
    # Get the poll that was published this year.
 | 
						|
    >>> from django.utils import timezone
 | 
						|
    >>> current_year = timezone.now().year
 | 
						|
    >>> Poll.objects.get(pub_date__year=current_year)
 | 
						|
    <Poll: What's up?>
 | 
						|
 | 
						|
    # Request an ID that doesn't exist, this will raise an exception.
 | 
						|
    >>> Poll.objects.get(id=2)
 | 
						|
    Traceback (most recent call last):
 | 
						|
        ...
 | 
						|
    DoesNotExist: Poll matching query does not exist. Lookup parameters were {'id': 2}
 | 
						|
 | 
						|
    # Lookup by a primary key is the most common case, so Django provides a
 | 
						|
    # shortcut for primary-key exact lookups.
 | 
						|
    # The following is identical to Poll.objects.get(id=1).
 | 
						|
    >>> Poll.objects.get(pk=1)
 | 
						|
    <Poll: What's up?>
 | 
						|
 | 
						|
    # Make sure our custom method worked.
 | 
						|
    >>> p = Poll.objects.get(pk=1)
 | 
						|
    >>> p.was_published_recently()
 | 
						|
    True
 | 
						|
 | 
						|
    # Give the Poll a couple of Choices. The create call constructs a new
 | 
						|
    # Choice object, does the INSERT statement, adds the choice to the set
 | 
						|
    # of available choices and returns the new Choice object. Django creates
 | 
						|
    # a set to hold the "other side" of a ForeignKey relation
 | 
						|
    # (e.g. a poll's choices) which can be accessed via the API.
 | 
						|
    >>> p = Poll.objects.get(pk=1)
 | 
						|
 | 
						|
    # Display any choices from the related object set -- none so far.
 | 
						|
    >>> p.choice_set.all()
 | 
						|
    []
 | 
						|
 | 
						|
    # Create three choices.
 | 
						|
    >>> p.choice_set.create(choice_text='Not much', votes=0)
 | 
						|
    <Choice: Not much>
 | 
						|
    >>> p.choice_set.create(choice_text='The sky', votes=0)
 | 
						|
    <Choice: The sky>
 | 
						|
    >>> c = p.choice_set.create(choice_text='Just hacking again', votes=0)
 | 
						|
 | 
						|
    # Choice objects have API access to their related Poll objects.
 | 
						|
    >>> c.poll
 | 
						|
    <Poll: What's up?>
 | 
						|
 | 
						|
    # And vice versa: Poll objects get access to Choice objects.
 | 
						|
    >>> p.choice_set.all()
 | 
						|
    [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
 | 
						|
    >>> p.choice_set.count()
 | 
						|
    3
 | 
						|
 | 
						|
    # The API automatically follows relationships as far as you need.
 | 
						|
    # Use double underscores to separate relationships.
 | 
						|
    # This works as many levels deep as you want; there's no limit.
 | 
						|
    # Find all Choices for any poll whose pub_date is in this year
 | 
						|
    # (reusing the 'current_year' variable we created above).
 | 
						|
    >>> Choice.objects.filter(poll__pub_date__year=current_year)
 | 
						|
    [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
 | 
						|
 | 
						|
    # Let's delete one of the choices. Use delete() for that.
 | 
						|
    >>> c = p.choice_set.filter(choice_text__startswith='Just hacking')
 | 
						|
    >>> c.delete()
 | 
						|
 | 
						|
For more information on model relations, see :doc:`Accessing related objects
 | 
						|
</ref/models/relations>`. For more on how to use double underscores to perform
 | 
						|
field lookups via the API, see :ref:`Field lookups <field-lookups-intro>`. For
 | 
						|
full details on the database API, see our :doc:`Database API reference
 | 
						|
</topics/db/queries>`.
 | 
						|
 | 
						|
When you're comfortable with the API, read :doc:`part 2 of this tutorial
 | 
						|
</intro/tutorial02>` to get Django's automatic admin working.
 |