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