PageRenderTime 107ms CodeModel.GetById 50ms app.highlight 5ms RepoModel.GetById 46ms app.codeStats 0ms

/docs/intro/tutorial01.txt

https://code.google.com/p/mango-py/
Plain Text | 701 lines | 513 code | 188 blank | 0 comment | 0 complexity | 2631b621f3e9e438226499a870af701f MD5 | raw file
  1=====================================
  2Writing your first Django app, part 1
  3=====================================
  4
  5Let's learn by example.
  6
  7Throughout this tutorial, we'll walk you through the creation of a basic
  8poll application.
  9
 10It'll consist of two parts:
 11
 12    * A public site that lets people view polls and vote in them.
 13    * An admin site that lets you add, change and delete polls.
 14
 15We'll assume you have :doc:`Django installed </intro/install>` already. You can
 16tell Django is installed by running the Python interactive interpreter and
 17typing ``import django``. If that command runs successfully, with no errors,
 18Django is installed.
 19
 20.. admonition:: Where to get help:
 21
 22    If you're having trouble going through this tutorial, please post a message
 23    to `django-users`__ or drop by `#django on irc.freenode.net`__ to chat
 24    with other Django users who might be able to help.
 25
 26__ http://groups.google.com/group/django-users
 27__ irc://irc.freenode.net/django
 28
 29Creating a project
 30==================
 31
 32If this is your first time using Django, you'll have to take care of some
 33initial setup. Namely, you'll need to auto-generate some code that establishes a
 34Django :term:`project` -- a collection of settings for an instance of Django,
 35including database configuration, Django-specific options and
 36application-specific settings.
 37
 38From the command line, ``cd`` into a directory where you'd like to store your
 39code, then run the following command:
 40
 41.. code-block:: bash
 42
 43   django-admin.py startproject mysite
 44
 45This will create a ``mysite`` directory in your current directory.
 46
 47.. admonition:: Script name may differ in distribution packages
 48
 49   If you installed Django using a Linux distribution's package manager
 50   (e.g. apt-get or yum) ``django-admin.py`` may have been renamed to
 51   ``django-admin``. You may continue through this documentation by omitting
 52   ``.py`` from each command.
 53
 54.. admonition:: Mac OS X permissions
 55
 56   If you're using Mac OS X, you may see the message "permission denied" when
 57   you try to run ``django-admin.py startproject``. This is because, on
 58   Unix-based systems like OS X, a file must be marked as "executable" before it
 59   can be run as a program. To do this, open Terminal.app and navigate (using
 60   the ``cd`` command) to the directory where :doc:`django-admin.py
 61   </ref/django-admin>` is installed, then run the command
 62   ``chmod +x django-admin.py``.
 63
 64.. note::
 65
 66    You'll need to avoid naming projects after built-in Python or Django
 67    components. In particular, this means you should avoid using names like
 68    ``django`` (which will conflict with Django itself) or ``test`` (which
 69    conflicts with a built-in Python package).
 70
 71:doc:`django-admin.py </ref/django-admin>` should be on your system path if you
 72installed Django via ``python setup.py``. If it's not on your path, you can find
 73it in ``site-packages/django/bin``, where ```site-packages``` is a directory
 74within your Python installation. Consider symlinking to :doc:`django-admin.py
 75</ref/django-admin>` from some place on your path, such as
 76:file:`/usr/local/bin`.
 77
 78.. admonition:: Where should this code live?
 79
 80    If your background is in PHP, you're probably used to putting code under the
 81    Web server's document root (in a place such as ``/var/www``). With Django,
 82    you don't do that. It's not a good idea to put any of this Python code
 83    within your Web server's document root, because it risks the possibility
 84    that people may be able to view your code over the Web. That's not good for
 85    security.
 86
 87    Put your code in some directory **outside** of the document root, such as
 88    :file:`/home/mycode`.
 89
 90Let's look at what :djadmin:`startproject` created::
 91
 92    mysite/
 93        __init__.py
 94        manage.py
 95        settings.py
 96        urls.py
 97
 98These files are:
 99
100    * :file:`__init__.py`: An empty file that tells Python that this directory
101      should be considered a Python package. (Read `more about packages`_ in the
102      official Python docs if you're a Python beginner.)
103
104    * :file:`manage.py`: A command-line utility that lets you interact with this
105      Django project in various ways. You can read all the details about
106      :file:`manage.py` in :doc:`/ref/django-admin`.
107
108    * :file:`settings.py`: Settings/configuration for this Django project.
109      :doc:`/topics/settings` will tell you all about how settings work.
110
111    * :file:`urls.py`: The URL declarations for this Django project; a "table of
112      contents" of your Django-powered site. You can read more about URLs in
113      :doc:`/topics/http/urls`.
114
115.. _more about packages: http://docs.python.org/tutorial/modules.html#packages
116
117The development server
118----------------------
119
120Let's verify this worked. Change into the :file:`mysite` directory, if you
121haven't already, and run the command ``python manage.py runserver``. You'll see
122the following output on the command line::
123
124    Validating models...
125    0 errors found.
126
127    Django version 1.0, using settings 'mysite.settings'
128    Development server is running at http://127.0.0.1:8000/
129    Quit the server with CONTROL-C.
130
131You've started the Django development server, a lightweight Web server written
132purely in Python. We've included this with Django so you can develop things
133rapidly, without having to deal with configuring a production server -- such as
134Apache -- until you're ready for production.
135
136Now's a good time to note: DON'T use this server in anything resembling a
137production environment. It's intended only for use while developing. (We're in
138the business of making Web frameworks, not Web servers.)
139
140Now that the server's running, visit http://127.0.0.1:8000/ with your Web
141browser. You'll see a "Welcome to Django" page, in pleasant, light-blue pastel.
142It worked!
143
144.. admonition:: Changing the port
145
146    By default, the :djadmin:`runserver` command starts the development server
147    on the internal IP at port 8000.
148
149    If you want to change the server's port, pass
150    it as a command-line argument. For instance, this command starts the server
151    on port 8080:
152
153    .. code-block:: bash
154
155        python manage.py runserver 8080
156
157    If you want to change the server's IP, pass it along with the port. So to
158    listen on all public IPs (useful if you want to show off your work on other
159    computers), use:
160
161    .. code-block:: bash
162
163        python manage.py runserver 0.0.0.0:8000
164
165    Full docs for the development server can be found in the
166    :djadmin:`runserver` reference.
167
168Database setup
169--------------
170
171Now, edit :file:`settings.py`. It's a normal Python module with
172module-level variables representing Django settings. Change the
173following keys in the :setting:`DATABASES` ``'default'`` item to match
174your databases connection settings.
175
176    * :setting:`ENGINE <DATABASE-ENGINE>` -- Either
177      ``'django.db.backends.postgresql_psycopg2'``,
178      ``'django.db.backends.mysql'`` or
179      ``'django.db.backends.sqlite3'``. Other backends are
180      :setting:`also available <DATABASE-ENGINE>`.
181
182    * :setting:`NAME` -- The name of your database. If you're using
183      SQLite, the database will be a file on your computer; in that
184      case, :setting:`NAME` should be the full absolute path,
185      including filename, of that file. If the file doesn't exist, it
186      will automatically be created when you synchronize the database
187      for the first time (see below).
188
189      When specifying the path, always use forward slashes, even on
190      Windows (e.g. ``C:/homes/user/mysite/sqlite3.db``).
191
192    * :setting:`USER` -- Your database username (not used for SQLite).
193
194    * :setting:`PASSWORD` -- Your database password (not used for
195      SQLite).
196
197    * :setting:`HOST` -- The host your database is on. Leave this as
198      an empty string if your database server is on the same physical
199      machine (not used for SQLite).
200
201If you're new to databases, we recommend simply using SQLite (by
202setting :setting:`ENGINE` to ``'django.db.backends.sqlite3'``). SQLite
203is included as part of Python 2.5 and later, so you won't need to
204install anything else.
205
206.. note::
207
208    If you're using PostgreSQL or MySQL, make sure you've created a database by
209    this point. Do that with "``CREATE DATABASE database_name;``" within your
210    database's interactive prompt.
211
212    If you're using SQLite, you don't need to create anything beforehand - the
213    database file will be created automatically when it is needed.
214
215While you're editing :file:`settings.py`, take note of the
216:setting:`INSTALLED_APPS` setting towards the bottom of the file. That variable
217holds the names of all Django applications that are activated in this Django
218instance. Apps can be used in multiple projects, and you can package and
219distribute them for use by others in their projects.
220
221By default, :setting:`INSTALLED_APPS` contains the following apps, all of which
222come with Django:
223
224    * :mod:`django.contrib.auth` -- An authentication system.
225
226    * :mod:`django.contrib.contenttypes` -- A framework for content types.
227
228    * :mod:`django.contrib.sessions` -- A session framework.
229
230    * :mod:`django.contrib.sites` -- A framework for managing multiple sites
231      with one Django installation.
232
233    * :mod:`django.contrib.messages` -- A messaging framework.
234
235    * :mod:`django.contrib.staticfiles` -- A framework for managing
236      static files.
237
238These applications are included by default as a convenience for the common case.
239
240Each of these applications makes use of at least one database table, though,
241so we need to create the tables in the database before we can use them. To do
242that, run the following command:
243
244.. code-block:: bash
245
246    python manage.py syncdb
247
248The :djadmin:`syncdb` command looks at the :setting:`INSTALLED_APPS` setting and
249creates any necessary database tables according to the database settings in your
250:file:`settings.py` file. You'll see a message for each database table it
251creates, and you'll get a prompt asking you if you'd like to create a superuser
252account for the authentication system. Go ahead and do that.
253
254If you're interested, run the command-line client for your database and type
255``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to
256display the tables Django created.
257
258.. admonition:: For the minimalists
259
260    Like we said above, the default applications are included for the common
261    case, but not everybody needs them. If you don't need any or all of them,
262    feel free to comment-out or delete the appropriate line(s) from
263    :setting:`INSTALLED_APPS` before running :djadmin:`syncdb`. The
264    :djadmin:`syncdb` command will only create tables for apps in
265    :setting:`INSTALLED_APPS`.
266
267.. _creating-models:
268
269Creating models
270===============
271
272Now that your environment -- a "project" -- is set up, you're set to start
273doing work.
274
275Each application you write in Django consists of a Python package, somewhere
276on your `Python path`_, that follows a certain convention. Django comes with a
277utility that automatically generates the basic directory structure of an app,
278so you can focus on writing code rather than creating directories.
279
280.. admonition:: Projects vs. apps
281
282    What's the difference between a project and an app? An app is a Web
283    application that does something -- e.g., a Weblog system, a database of
284    public records or a simple poll app. A project is a collection of
285    configuration and apps for a particular Web site. A project can contain
286    multiple apps. An app can be in multiple projects.
287
288Your apps can live anywhere on your `Python path`_. In this tutorial, we'll
289create our poll app in the :file:`mysite` directory for simplicity.
290
291To create your app, make sure you're in the :file:`mysite` directory and type
292this command:
293
294.. code-block:: bash
295
296    python manage.py startapp polls
297
298That'll create a directory :file:`polls`, which is laid out like this::
299
300    polls/
301        __init__.py
302        models.py
303        tests.py
304        views.py
305
306This directory structure will house the poll application.
307
308The first step in writing a database Web app in Django is to define your models
309-- essentially, your database layout, with additional metadata.
310
311.. admonition:: Philosophy
312
313   A model is the single, definitive source of data about your data. It contains
314   the essential fields and behaviors of the data you're storing. Django follows
315   the :ref:`DRY Principle <dry>`. The goal is to define your data model in one
316   place and automatically derive things from it.
317
318In our simple poll app, we'll create two models: polls and choices. A poll has
319a question and a publication date. A choice has two fields: the text of the
320choice and a vote tally. Each choice is associated with a poll.
321
322These concepts are represented by simple Python classes. Edit the
323:file:`polls/models.py` file so it looks like this::
324
325    from django.db import models
326
327    class Poll(models.Model):
328        question = models.CharField(max_length=200)
329        pub_date = models.DateTimeField('date published')
330
331    class Choice(models.Model):
332        poll = models.ForeignKey(Poll)
333        choice = models.CharField(max_length=200)
334        votes = models.IntegerField()
335
336The code is straightforward. Each model is represented by a class that
337subclasses :class:`django.db.models.Model`. Each model has a number of class
338variables, each of which represents a database field in the model.
339
340Each field is represented by an instance of a :class:`~django.db.models.Field`
341class -- e.g., :class:`~django.db.models.CharField` for character fields and
342:class:`~django.db.models.DateTimeField` for datetimes. This tells Django what
343type of data each field holds.
344
345The name of each :class:`~django.db.models.Field` instance (e.g. ``question`` or
346``pub_date`` ) is the field's name, in machine-friendly format. You'll use this
347value in your Python code, and your database will use it as the column name.
348
349You can use an optional first positional argument to a
350:class:`~django.db.models.Field` to designate a human-readable name. That's used
351in a couple of introspective parts of Django, and it doubles as documentation.
352If this field isn't provided, Django will use the machine-readable name. In this
353example, we've only defined a human-readable name for ``Poll.pub_date``. For all
354other fields in this model, the field's machine-readable name will suffice as
355its human-readable name.
356
357Some :class:`~django.db.models.Field` classes have required elements.
358:class:`~django.db.models.CharField`, for example, requires that you give it a
359:attr:`~django.db.models.Field.max_length`. That's used not only in the database
360schema, but in validation, as we'll soon see.
361
362Finally, note a relationship is defined, using
363:class:`~django.db.models.ForeignKey`. That tells Django each Choice is related
364to a single Poll. Django supports all the common database relationships:
365many-to-ones, many-to-manys and one-to-ones.
366
367.. _`Python path`: http://docs.python.org/tutorial/modules.html#the-module-search-path
368
369Activating models
370=================
371
372That small bit of model code gives Django a lot of information. With it, Django
373is able to:
374
375    * Create a database schema (``CREATE TABLE`` statements) for this app.
376    * Create a Python database-access API for accessing Poll and Choice objects.
377
378But first we need to tell our project that the ``polls`` app is installed.
379
380.. admonition:: Philosophy
381
382    Django apps are "pluggable": You can use an app in multiple projects, and
383    you can distribute apps, because they don't have to be tied to a given
384    Django installation.
385
386Edit the :file:`settings.py` file again, and change the
387:setting:`INSTALLED_APPS` setting to include the string ``'polls'``. So
388it'll look like this::
389
390    INSTALLED_APPS = (
391        'django.contrib.auth',
392        'django.contrib.contenttypes',
393        'django.contrib.sessions',
394        'django.contrib.sites',
395        'polls'
396    )
397
398Now Django knows to include the ``polls`` app. Let's run another
399command:
400
401.. code-block:: bash
402
403    python manage.py sql polls
404
405You should see something similar to the following (the ``CREATE TABLE`` SQL
406statements for the polls app):
407
408.. code-block:: sql
409
410    BEGIN;
411    CREATE TABLE "polls_poll" (
412        "id" serial NOT NULL PRIMARY KEY,
413        "question" varchar(200) NOT NULL,
414        "pub_date" timestamp with time zone NOT NULL
415    );
416    CREATE TABLE "polls_choice" (
417        "id" serial NOT NULL PRIMARY KEY,
418        "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"),
419        "choice" varchar(200) NOT NULL,
420        "votes" integer NOT NULL
421    );
422    COMMIT;
423
424Note the following:
425
426    * The exact output will vary depending on the database you are using.
427
428    * Table names are automatically generated by combining the name of the app
429      (``polls``) and the lowercase name of the model -- ``poll`` and
430      ``choice``. (You can override this behavior.)
431
432    * Primary keys (IDs) are added automatically. (You can override this, too.)
433
434    * By convention, Django appends ``"_id"`` to the foreign key field name.
435      Yes, you can override this, as well.
436
437    * The foreign key relationship is made explicit by a ``REFERENCES``
438      statement.
439
440    * It's tailored to the database you're using, so database-specific field
441      types such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or
442      ``integer primary key`` (SQLite) are handled for you automatically. Same
443      goes for quoting of field names -- e.g., using double quotes or single
444      quotes. The author of this tutorial runs PostgreSQL, so the example
445      output is in PostgreSQL syntax.
446
447    * The :djadmin:`sql` command doesn't actually run the SQL in your database -
448      it just prints it to the screen so that you can see what SQL Django thinks
449      is required. If you wanted to, you could copy and paste this SQL into your
450      database prompt. However, as we will see shortly, Django provides an
451      easier way of committing the SQL to the database.
452
453If you're interested, also run the following commands:
454
455    * :djadmin:`python manage.py validate <validate>` -- Checks for any errors
456      in the construction of your models.
457
458    * :djadmin:`python manage.py sqlcustom polls <sqlcustom>` -- Outputs any
459      :ref:`custom SQL statements <initial-sql>` (such as table modifications or
460      constraints) that are defined for the application.
461
462    * :djadmin:`python manage.py sqlclear polls <sqlclear>` -- Outputs the
463      necessary ``DROP TABLE`` statements for this app, according to which
464      tables already exist in your database (if any).
465
466    * :djadmin:`python manage.py sqlindexes polls <sqlindexes>` -- Outputs the
467      ``CREATE INDEX`` statements for this app.
468
469    * :djadmin:`python manage.py sqlall polls <sqlall>` -- A combination of all
470      the SQL from the :djadmin:`sql`, :djadmin:`sqlcustom`, and
471      :djadmin:`sqlindexes` commands.
472
473Looking at the output of those commands can help you understand what's actually
474happening under the hood.
475
476Now, run :djadmin:`syncdb` again to create those model tables in your database:
477
478.. code-block:: bash
479
480    python manage.py syncdb
481
482The :djadmin:`syncdb` command runs the sql from 'sqlall' on your database for
483all apps in :setting:`INSTALLED_APPS` that don't already exist in your database.
484This creates all the tables, initial data and indexes for any apps you have
485added to your project since the last time you ran syncdb. :djadmin:`syncdb` can
486be called as often as you like, and it will only ever create the tables that
487don't exist.
488
489Read the :doc:`django-admin.py documentation </ref/django-admin>` for full
490information on what the ``manage.py`` utility can do.
491
492Playing with the API
493====================
494
495Now, let's hop into the interactive Python shell and play around with the free
496API Django gives you. To invoke the Python shell, use this command:
497
498.. code-block:: bash
499
500    python manage.py shell
501
502We're using this instead of simply typing "python", because ``manage.py`` sets
503up the project's environment for you. "Setting up the environment" involves two
504things:
505
506    * Putting ``polls`` on ``sys.path``. For flexibility, several pieces of
507      Django refer to projects in Python dotted-path notation (e.g.
508      ``'polls.models'``). In order for this to work, the ``polls``
509      package has to be on ``sys.path``.
510
511      We've already seen one example of this: the :setting:`INSTALLED_APPS`
512      setting is a list of packages in dotted-path notation.
513
514    * Setting the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives
515      Django the path to your ``settings.py`` file.
516
517.. admonition:: Bypassing manage.py
518
519    If you'd rather not use ``manage.py``, no problem. Just make sure ``mysite``
520    and ``polls`` are at the root level on the Python path (i.e., ``import mysite``
521    and ``import polls`` work) and set the ``DJANGO_SETTINGS_MODULE`` environment
522    variable to ``mysite.settings``.
523
524    For more information on all of this, see the :doc:`django-admin.py
525    documentation </ref/django-admin>`.
526
527Once you're in the shell, explore the :doc:`database API </topics/db/queries>`::
528
529    >>> from polls.models import Poll, Choice # Import the model classes we just wrote.
530
531    # No polls are in the system yet.
532    >>> Poll.objects.all()
533    []
534
535    # Create a new Poll.
536    >>> import datetime
537    >>> p = Poll(question="What's up?", pub_date=datetime.datetime.now())
538
539    # Save the object into the database. You have to call save() explicitly.
540    >>> p.save()
541
542    # Now it has an ID. Note that this might say "1L" instead of "1", depending
543    # on which database you're using. That's no biggie; it just means your
544    # database backend prefers to return integers as Python long integer
545    # objects.
546    >>> p.id
547    1
548
549    # Access database columns via Python attributes.
550    >>> p.question
551    "What's up?"
552    >>> p.pub_date
553    datetime.datetime(2007, 7, 15, 12, 00, 53)
554
555    # Change values by changing the attributes, then calling save().
556    >>> p.pub_date = datetime.datetime(2007, 4, 1, 0, 0)
557    >>> p.save()
558
559    # objects.all() displays all the polls in the database.
560    >>> Poll.objects.all()
561    [<Poll: Poll object>]
562
563
564Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful representation
565of this object. Let's fix that by editing the polls model (in the
566``polls/models.py`` file) and adding a
567:meth:`~django.db.models.Model.__unicode__` method to both ``Poll`` and
568``Choice``::
569
570    class Poll(models.Model):
571        # ...
572        def __unicode__(self):
573            return self.question
574
575    class Choice(models.Model):
576        # ...
577        def __unicode__(self):
578            return self.choice
579
580It's important to add :meth:`~django.db.models.Model.__unicode__` methods to
581your models, not only for your own sanity when dealing with the interactive
582prompt, but also because objects' representations are used throughout Django's
583automatically-generated admin.
584
585.. admonition:: Why :meth:`~django.db.models.Model.__unicode__` and not
586                :meth:`~django.db.models.Model.__str__`?
587
588    If you're familiar with Python, you might be in the habit of adding
589    :meth:`~django.db.models.Model.__str__` methods to your classes, not
590    :meth:`~django.db.models.Model.__unicode__` methods. We use
591    :meth:`~django.db.models.Model.__unicode__` here because Django models deal
592    with Unicode by default. All data stored in your database is converted to
593    Unicode when it's returned.
594
595    Django models have a default :meth:`~django.db.models.Model.__str__` method
596    that calls :meth:`~django.db.models.Model.__unicode__` and converts the
597    result to a UTF-8 bytestring. This means that ``unicode(p)`` will return a
598    Unicode string, and ``str(p)`` will return a normal string, with characters
599    encoded as UTF-8.
600
601    If all of this is gibberish to you, just remember to add
602    :meth:`~django.db.models.Model.__unicode__` methods to your models. With any
603    luck, things should Just Work for you.
604
605Note these are normal Python methods. Let's add a custom method, just for
606demonstration::
607
608    import datetime
609    # ...
610    class Poll(models.Model):
611        # ...
612        def was_published_today(self):
613            return self.pub_date.date() == datetime.date.today()
614
615Note the addition of ``import datetime`` to reference Python's standard
616``datetime`` module.
617
618Save these changes and start a new Python interactive shell by running
619``python manage.py shell`` again::
620
621    >>> from polls.models import Poll, Choice
622
623    # Make sure our __unicode__() addition worked.
624    >>> Poll.objects.all()
625    [<Poll: What's up?>]
626
627    # Django provides a rich database lookup API that's entirely driven by
628    # keyword arguments.
629    >>> Poll.objects.filter(id=1)
630    [<Poll: What's up?>]
631    >>> Poll.objects.filter(question__startswith='What')
632    [<Poll: What's up?>]
633
634    # Get the poll whose year is 2007.
635    >>> Poll.objects.get(pub_date__year=2007)
636    <Poll: What's up?>
637
638    >>> Poll.objects.get(id=2)
639    Traceback (most recent call last):
640        ...
641    DoesNotExist: Poll matching query does not exist.
642
643    # Lookup by a primary key is the most common case, so Django provides a
644    # shortcut for primary-key exact lookups.
645    # The following is identical to Poll.objects.get(id=1).
646    >>> Poll.objects.get(pk=1)
647    <Poll: What's up?>
648
649    # Make sure our custom method worked.
650    >>> p = Poll.objects.get(pk=1)
651    >>> p.was_published_today()
652    False
653
654    # Give the Poll a couple of Choices. The create call constructs a new
655    # choice object, does the INSERT statement, adds the choice to the set
656    # of available choices and returns the new Choice object. Django creates
657    # a set to hold the "other side" of a ForeignKey relation
658    # (e.g. a poll's choices) which can be accessed via the API.
659    >>> p = Poll.objects.get(pk=1)
660
661    # Display any choices from the related object set -- none so far.
662    >>> p.choice_set.all()
663    []
664
665    # Create three choices.
666    >>> p.choice_set.create(choice='Not much', votes=0)
667    <Choice: Not much>
668    >>> p.choice_set.create(choice='The sky', votes=0)
669    <Choice: The sky>
670    >>> c = p.choice_set.create(choice='Just hacking again', votes=0)
671
672    # Choice objects have API access to their related Poll objects.
673    >>> c.poll
674    <Poll: What's up?>
675
676    # And vice versa: Poll objects get access to Choice objects.
677    >>> p.choice_set.all()
678    [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
679    >>> p.choice_set.count()
680    3
681
682    # The API automatically follows relationships as far as you need.
683    # Use double underscores to separate relationships.
684    # This works as many levels deep as you want; there's no limit.
685    # Find all Choices for any poll whose pub_date is in 2007.
686    >>> Choice.objects.filter(poll__pub_date__year=2007)
687    [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
688
689    # Let's delete one of the choices. Use delete() for that.
690    >>> c = p.choice_set.filter(choice__startswith='Just hacking')
691    >>> c.delete()
692
693For more information on model relations, see :doc:`Accessing related objects
694</ref/models/relations>`. For more on how to use double underscores to perform
695field lookups via the API, see `Field lookups`__. For full details on the
696database API, see our :doc:`Database API reference </topics/db/queries>`.
697
698__ http://docs.djangoproject.com/en/1.2/topics/db/queries/#field-lookups
699
700When you're comfortable with the API, read :doc:`part 2 of this tutorial
701</intro/tutorial02>` to get Django's automatic admin working.