官术网_书友最值得收藏!

Models: Designing an Initial Database Schema

Almost every Web 2.0 application requires a database to store and manage its data. The database engine is a fundamental component of web development nowadays. Web applications offer the user a UI to enter and manage their data, and use a database engine behind the scenes to manage this data.

Note

In Django, you can think of the view as the component responsible for collecting and displaying data, and the model as the component responsible for storing and managing it.

We will chose the database engine that configured our database settings in the previous chapter. In this section, we will make use of the database to store and manage user accounts and bookmarks.

If you are used to dealing with the database directly through SQL queries, then you may find Django's approach to database access a bit different. Loosely speaking, Django abstracts access to database tables through Python classes. To store, manipulate and retrieve objects from the database, the developer uses a Python-based API. In order to do this, SQL knowledge is useful but not required.

This technique is best explained by example. For our bookmarking application, we need to store three types of data in the database:

  • Users (ID, username, password, email)
  • Links (ID, URL)
  • Bookmarks (ID, title, user_id, link_id)

Each user will have their own entry in the Users table. This entry stores the username, password and email. Similarly, each link will have a corresponding entry in the links table. We will only store the link's URL for now.

As for the Bookmarks table, you can think of it as the joining table between Users and Links. When a user adds a bookmark, an entry for the bookmark's URL is added to the links table if it doesn't already exist, and then a joining entry is added to the Bookmarks table. This entry connects the user with the link, and stores the title that the user entered for their bookmark.

To convert this table design into Python code, we need to edit models.py in bookmarks and enter the details of each object type. models.py is the file where database models are stored, and it only contains an import line when it's created by manage.py startapp.

The Link Data Model

Let's start by creating the data model for the Links table, because it's the simplest one. Open bookmarks/models.py in your editor and type the following code:

from django.db import models

class Link(models.Model):
  url = models.URLField(unique=True)

Going through the code line by line, we learn the following:

  • The models package contains classes that are required to define models, so it is imported first.
  • We define a class named Link. This class inherits from models.Model, which is the base class for all models. The class contains one field named url, and it's of the type models.URLField. This field must be unique.

models.URLField is one of many field types provided by Django. Below is a partial table of these types:

To use this model, we first need to activate it in our Django project. This is done by editing settings.py, looking for the INSTALLED_APPS variable, and adding our application name (django_bookmarks.bookmarks) to it:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django_bookmarks.bookmarks',
)

Now, issue the following command to create a table for the Link data model in the database:

$ python manage.py syncdb

You may remember that we used this command in the previous chapter to create Django's own administrative tables. Whenever you add a data model, you need to issue this command in order to create its table in the database.

If you are familiar with SQL, you can examine the SQL query generated by Django by running the following command:

$ python manage.py sql bookmarks

The output from this command may differ slightly depending on your database engine. For SQLite, it should look similar to the following:

BEGIN;
CREATE TABLE "bookmarks_link" (
    "id" integer NOT NULL PRIMARY KEY,
    "url" varchar(200) NOT NULL UNIQUE
);
COMMIT;

What has happened here? Django analyzed our Link model, which is a regular Python class, and generated an SQL CREATE statement for a database table named bookmarks_link; this table will store instances of the Link class. Notice that Django automatically added an id field to the table. This field is the primary key of the table and can be used to identify links and connect them to bookmarks.

The power of Django's Python database API does not stop at creating tables. We can use it to create entries in the table, to modify entries, to search and browse the table contents, among many other things. To explore the API, we will use the Python interactive console. To launch the console use this command:

$ python manage.py shell

This shell differs from the standard Python shell in two ways. Firstly, the project path is added to sys.path, which simplifies importing modules from our project. Secondly, a special environment variable is created to hold the path to our settings.py. So whenever you need a Python shell to interact with your project, use the above command.

Now import the contents of the models module:

>>> from bookmarks.models import *

To add a new link, create a new instance of the Link class and call the save method on it:

>>> link1 = Link(url='http://www.packtpub.com/')
>>> link1.save()
>>> link2 = Link(url='http://www.example.com/')
>>> link2.save()

Calling the save method is required to store the object in the database. Before that, the object exists in memory only, and it will be lost if you close the console. However, when you call save, the object is stored in the database.

Table fields become attributes of objects. To examine and change a link's URL, type the following:

>>> link2.url
          'http://www.example.com/'
>>> link2.url = 'http://www.google.com/'
>>> link2.save()

To get a list of all available Link objects, type the following:

>>> links = Link.objects.all()
>>> for link in links:
... print link.url
...
http://www.packtpub.com/
http://www.google.com/

To get an object by ID, type the following:

>>> Link.objects.get(id=1)
        <Link: Link object>

Finally, to delete a link, use the following:

>>> link2.delete()
>>> Link.objects.count()
        1

And output of 1 indicates that there is now only one remaining link. Notice that we were able to do all of the above without needing a single SQL statement. Django's model API can do a lot more; it covers all the tasks commonly done through SQL. Actually, the above method calls are converted to SQL statements, and the results of the statements are returned. The benefits of this approach are numerous:

  • You don't have to learn another language to access the database. You already know Python and how use it to write views, so it's obviously a benefit if you can also use it to access the database.
  • Django transparently handles the conversion between Python objects and table rows. You only work with Python objects, and Django automatically stores and retrieves them from the database for you.
  • You don't have to worry about any special SQL syntax for different database engines, especially if you have to switch from one engine to another. The Django model API is the same no matter what engine you use, and it takes care of the differences for you.

The User Data Model

Now that you are comfortable with the concept of data models, let's move to the User object. Fortunately for us, management of user accounts is so common that Django comes with a user model ready for us to use. This model contains fields that are often associated with user accounts, such as username, password and email and so on. The model is called User and it's located in the django.contrib.auth.models package.

To explore the contents of this model, open the interactive console and type the following:

>>> from django.contrib.auth.models import User
>>> User.objects.all()
          [<User: ayman>]

We can see that the table represented by this model already contains a user. Remember when we configured the database in the previous chapter? We had to create the superuser account, and Django stored this user in the table of the User model.

You can examine the fields of User objects by using the dir function:

>>> user = User.objects.get(id=1)
>>> dir(user)

You will get a very long list of attributes. Among them you will find the username, email address and password. Good news! This model fulfills our needs. Django provides all the necessary attributes for our user objects, and we can use directly use the User model directly without any extra code.

The Bookmark Data Model

Only one model remains, the Bookmark model. When we examined it earlier, we realized that a bookmark connects a user to a link. A bookmark belongs to one user and one link. However, one user may have many bookmarks, and one link may be bookmarked by many users. In database language we say there is a many-to-many relationship between users and links. However, there is no way to actually represent a many-to-many relationship such as this one using a standard database system. In our particular case, we will invent the concept of a bookmark to break up this many-to-many relationship into its constituent one-to-many relationships.

The first of these is the one-to-many relationship between the user and their bookmarks. One user can have many bookmarks, but each bookmark is associated with only one user. That is to say, each user can bookmark a particular link once.

The second of these is the one-to-many relationship between a link and its bookmarks. One link can have many bookmarks associated with it if multiple users have bookmarked it, but each bookmark is associated with only one link.

Now that we have two separate one-to-many relationships, it is possible to represent all of this in a database system. To do so, we create a third table, the bookmarks table, which connects the user table and the links table. Each row in the bookmarks table has a reference to a row in the users table (that is to a particular user) and a reference to the links table (that is to a particular link). In SQL, these references to rows in "foreign" tables are known as foreign keys, but instead of working with SQL to define tables and foreign keys, we will use the Django model API to write a data model for the bookmarks.

The following code listing contains the Bookmark data model. You should insert it into bookmarks/models.py. For those who are new to relational databases and SQL, this section may seem a little obscure at first. However, it will all make more sense when you see it in action. Here is the code for the Bookmark data model:

from django.contrib.auth.models import User
class Bookmark(models.Model):
  title = models.CharField(maxlength=200)
  user = models.ForeignKey(User)
  link = models.ForeignKey(Link)

We first import the User class in order to refer to it in the Bookmark model. Next, we define a class for the Bookmark model as we did with Link. The new model contains a text field called title, and two foreign keys that refer back to the User and Link models.

Tip

Code Snippets and import statements

Python conventions suggest putting import statements at the beginning of the source file. When adding code to an existing file, there will be new import statements at the beginning of the new code snippet, but you are recommended to move these statements to the beginning of the file.

After you enter the model's code into models.py, you need to run manage.py syncdb in order to create its corresponding table.

Let's examine the SQL query generated by Django to see how it automatically handles foreign keys. Again, issue the following command:

$ python manage.py sql bookmarks

And you will see the CREATE statement for the Bookmark data model:

BEGIN;
CREATE TABLE "bookmarks_bookmark" (
 "id" integer NOT NULL PRIMARY KEY,
 "title" varchar(200) NOT NULL,
 "user_id" integer NOT NULL REFERENCES
 "auth_user" ("id"),
 "link_id" integer NOT NULL REFERENCES
 "bookmarks_link" ("id"),
);
CREATE TABLE "bookmarks_link" (
    "id" integer NOT NULL PRIMARY KEY,
    "url" varchar(200) NOT NULL UNIQUE
);
COMMIT;

Notice how Django appended _id to the table name to create foreign key fields and generated the necessary SQL for expressing one-to-many relations.

Now that the data models are ready, we have the facilities to store and manage our data. Django offers an elegant and straightforward Python API to store Python objects in the database, thus sparing the developer the burden of working with SQL and converting between SQL and Python types and idioms.

Next, we will learn about another major Django component, the template system. We will use it to simplify working with page creation, and then make use of all the information we learned in this chapter to create bookmark listing pages for users.

主站蜘蛛池模板: 大洼县| 肥东县| 思茅市| 汽车| 大邑县| 黄梅县| 郧西县| 合阳县| 囊谦县| 读书| 波密县| 德清县| 秦安县| 汤阴县| 灵璧县| 安国市| 祁东县| 曲靖市| 天气| 灵璧县| 水城县| 孟州市| 辽阳县| 邮箱| 丰顺县| 弥勒县| 筠连县| 蓬莱市| 伊宁市| 杭锦后旗| 枣阳市| 康马县| 东乡| 汾西县| 都兰县| 阿拉善右旗| 巴南区| 武清区| 江西省| 渑池县| 辉南县|