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