django (三) 第一个django app 创建model

经过上一章,我们已经创建好一个django app了,接下来,我们开始完善它。

首先,我们先了解些基本概念。

Django中创建的每个应用程序都是由Python的包组成,遵循某些约定。Django配有一个实用程序,自动生成一个应用程序的基本目录结构,所以您可以专注于编写代码,而不是创建目录。

那么项目和应用程序到底有什么区别呢?

一个app是一个web应用:比如一个博客系统,一个简单的投票系统。而一个项目是一个集合的配置和应用程序特定的Web站点。一个项目可以包含多个应用程序。应用程序可以存在于在多个项目。

应用程序可以放置在任何Python路径下。在本文中,我们将应用与manage.py文件放在同一个目录下,以便它可以作为一个顶级模块,而不是为mysite的子模块。

所以首先,我们进入到manage.py的同级目录下,也就是C:\mysite,输入下面的命令:

manage.py startapp polls

polls的目录结构如下:

polls/
    __init__.py
    models.py
    tests.py
    views.py

写数据库Web应用程序的第一步就是定义模型,从本质上讲就是用一些额外的元数据,定义数据库布局。模型需要对必要字段和数据行为进行定义。

在我们的程序中,我们需要建立两个模型:Poll 和 Choice,Poll包含提问和提问的日期,Choice包含投票的选项和票数的统计,每一个Choice都与一个Poll相关联。

下面修改polls/models.py:

# -*- coding: utf-8 -*-
from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

 

这里的代码很直观,每一个model都代表了django.db.models.Model的子类,每一个model都有一些变量,用来定义数据的类型与范围。

每一个变量都是一个字段的实例,CharField表示字符串字段,DateTimeField表示日期字段,每个字段实例(如question或pub_date)在数据库中代表一列。你可以在第一个参数位置字段输入一个字符串,告诉人们这个变量的含义,比如'date published'。有些变量你需要给他设置一些初始参数。比如IntegerField。表与表之间会有一些外键,可以用ForeignKey去设置。Django里的外键有many-to-ones, many-to-manys and one-to-ones.

这些代码将告诉Django做以下事情:

  • 为这个应用创建数据结构(为这些表创建声明) .
  • 为Poll和Choice等对象创建数据接口。

做这些之前,我们首先得告诉程序,Poll应用已经建好了。修改setting.py里的INSTALLED_APPS,向里面添加polls如下:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'polls'
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
)

现在,程序知道polls应用已经安好,下面来执行另外一个命令:

manage.py sql polls

出现如下内容:

BEGIN;
CREATE TABLE "polls_poll" (
    "id" integer NOT NULL PRIMARY KEY,
    "question" varchar(200) NOT NULL,
    "pub_date" datetime NOT NULL
)
;
CREATE TABLE "polls_choice" (
    "id" integer NOT NULL PRIMARY KEY,
    "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"),
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL
)
;

COMMIT;

让我们来解释一下它:

这里的polls_poll 和 polls_choice都是系统根据model里的变量自动生成的,由于我们没有设置主键,所以系统将主键设置为id.

sql命令并没有真的去数据库中执行SQL语句——它只是打印到屏幕上,这样你可以看到SQL Django认为是必需的。

下面介绍几个命令:

manage.py validate

用来检查模型是否正确。

manage.py sqlcustom polls

输出任何自定义SQL语句(如表的修改或为应用程序定义的约束)。

manage.py sqlclear polls

为这个应用程序输出必要的DROP TABLE语句,根据哪些表已经存在于您的数据库(如果有的话)。

manage.py sqlindexes polls

为这个应用程序输出CREATE INDEX语句。

manage.py sqlall polls

上述所有命令的集合。


现在,可以为这些模型创建表了,执行:

manage.py syncdb

注意,这个命令只会为没有创建过表app去创建新表。

下面,我们将进入交互模式,去做一些测试,输入:

manage.py shell

效果如下:

>>> from polls.models import Poll, Choice # Import the model classes we just wrote.
# No polls are in the system yet.
>>> Poll.objects.all()
[]
# Create a new Poll.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> p = Poll(question="What’s new?", pub_date=timezone.now())
# Save the object into the database. You have to call save() explicitly.
>>> p.save()
# Now it has an ID. Note that this might say "1L" instead of "1", depending
# on which database you’re using. That’s no biggie; it just means your
# database backend prefers to return integers as Python long integer
# objects.
>>> p.id
1
# Access database columns via Python attributes.
>>> p.question
"What’s new?"
>>> p.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# Change values by changing the attributes, then calling save().
>>> p.question = "What’s up?"
>>> p.save()
# objects.all() displays all the polls in the database.
>>> Poll.objects.all()
[<Poll: Poll object>]

Poll对象的名字现在显示为Poll object,为了给他一个独一无二的名字我们需要修改模型如下:

# -*- coding: utf-8 -*-
from django.db import models
from django.utils import timezone
import datetime

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __unicode__(self): # Python 3: def __str__(self):
        return self.question

    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
    
class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __unicode__(self): # Python 3: def __str__(self):
        return self.choice_text

下面我们再为Poll类定义一个方法,判断是否是最近出版,代码如下:

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __unicode__(self): # Python 3: def __str__(self):
        return self.question

    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

然后我们按如下进行测试:

>>> from polls.models import Poll, Choice
# Make sure our __unicode__() addition worked.
>>> Poll.objects.all()
[<Poll: What’s up?>]
# Django provides a rich database lookup API that’s entirely driven by
# keyword arguments.
>>> Poll.objects.filter(id=1)
[<Poll: What’s up?>]
>>> Poll.objects.filter(question__startswith=’What’)
[<Poll: What’s up?>]
# Get the poll that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Poll.objects.get(pub_date__year=current_year)
<Poll: What’s up?>
# Request an ID that doesn’t exist, this will raise an exception.
>>> Poll.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Poll matching query does not exist. Lookup parameters were {’id’: 2}
# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Poll.objects.get(id=1).
>>> Poll.objects.get(pk=1)
<Poll: What’s up?>
# Make sure our custom method worked.
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_recently()
True
# Give the Poll a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a poll’s choices) which can be accessed via the API.
>>> p = Poll.objects.get(pk=1)
# Display any choices from the related object set -- none so far.
>>> p.choice_set.all()
[]
# Create three choices.
>>> p.choice_set.create(choice_text=’Not much’, votes=0)
<Choice: Not much>
>>> p.choice_set.create(choice_text=’The sky’, votes=0)
<Choice: The sky>
>>> c = p.choice_set.create(choice_text=’Just hacking again’, votes=0)
# Choice objects have API access to their related Poll objects.
>>> c.poll
<Poll: What’s up?>
# And vice versa: Poll objects get access to Choice objects.
>>> p.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
>>> p.choice_set.count()
3
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there’s no limit.
# Find all Choices for any poll whose pub_date is in this year
# (reusing the ’current_year’ variable we created above).
>>> Choice.objects.filter(poll__pub_date__year=current_year)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
# Let’s delete one of the choices. Use delete() for that.
>>> c = p.choice_set.filter(choice_text__startswith=’Just hacking’)
>>> c.delete()
Traceback (most recent call last):
...
DoesNotExist: Poll matching query does not exist. Lookup parameters were {’id’: 2}
View Code

 

posted @ 2015-04-18 18:33  坐观云起时  阅读(697)  评论(0编辑  收藏  举报