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.