python

学习过程中总结的经验

博客园 首页 新随笔 联系 订阅 管理

欢迎各位python django爱好者加入我们的PDW大家庭!QQ群:80692368

MTV开发模式

M 代表模型(Model),即数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。

T 代表模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。

V 代表视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你可以把它看作模型与模板之间的桥梁。

Django MVC 中:视图用来描述要展现给用户的数据;不是数据 如何展现 ,而且展现 哪些 数据。 ?

Ruby on Rails 及一些同类框架:控制器负责决定向用户展现哪些数据,而视图则仅决定 如何 展现数据,而不是展现 哪些 数据。 ?

数据库配置

settings.py

DATABASE_ENGINE = '' #数据库引擎
DATABASE_NAME = ''    #数据库名称
DATABASE_USER = ''    #用哪个用户连接数据库
DATABASE_PASSWORD = '' #连接用户的密码
DATABASE_HOST = ''     #数据库服务器
DATABASE_PORT = ''    #数据库服务器端口

测试

>>> from django.db import connection

>>> cursor = connection.cursor()

Django项目(project)和应用(app)

一个project包含很多个Django app以及对它们的配置。

技术上,project的作用是提供配置文件,比方说哪里定义数据库连接信息, 安装的app列表,TEMPLATE_DIRS ,等等

一个app是一套Django功能的集合,通常包括模型和视图,按Python的包结构的方式存在。

例如,Django本身内建有一些app,例如注释系统和自动管理界面。 app的一个关键点是它们是很容易移植到其他project和被多个project复用。当然,一个project也可以不用创建app,但是如果你使用了Django的数据库层(模型),你 必须创建一个Django app

创建app

python manage.py startapp books
创建模型
Django模型是用Python代码形式表述的数据在数据库中的定义。
对数据层来说它等同于 CREATE TABLE 语句,只不过执行的是Python代码而不是 SQL,
而且还包含了比数据库字段定义更多的含义(如URL)。

#Django提供了实用工具来从现有的数据库表中自动扫描生成模型。

#“每个数据库表对应一个类”这条规则的例外情况是多对多关系

from django.db import models
class Author(models.Model): #创建模型的示例
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)

        email = models.EmailField('e-mail',blank=True, null=True)

                      #blank=True,null=True设置字段是可选,可null的,'e-mail‘|verbose_name='e-mail' 自定义标签为e-mail

        def __unicode__(sefl): #此方法告诉Python如何将对象以unicode的方式显示出来,'e-mail'是

                 return self.first_name

        class Meta:                 #缺省人排序方式
                 ordering = ['first_name']

#会自动为模型生成一个自增长的整数主键字段,每个Django模型都要求有单独的主键:id

#请确保你的每一个模型里都包含 __unicode__() 方法

模型安装
激活 模型
settings.pyINSTALLED_APPS 设置 告诉 Django 项目哪些 app 处于激活状态。
            MIDDLEWARE_CLASSES  设置
验检 模型
python manage.py validate
创建数据表

生成 CREATETABLE 语句

python manage.py sqlall books

生成数据表

python manage.py sqlall books 打印出books app的数据表的sql语句#主要是用来检查

python manage.py syncdb 生成表

syncdb 命令是同步模型到数据库的一个简单方法。 它根据 INSTALLED_APPS 的设置检查数据库,如表不存在,就会创建它。 注意:syncdb 并 不能将模型的修改或删除同步到数据库。重复运行pythonmanage.pysyncdb总是安全的,因为它不会重复执行SQL语句

基本数据访问

from books.models import Publisher   #导入Publisher模型类

1.增加

>>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue') #创建类实例,设置字段值
>>> p1.save()   #将对象保存到数据库中。 Django 会在后台执行一条 INSERT 语句

>>> Publisher.objects.create(name='Apress', address='2855 Telegraph Avenue')#一步完成对象的创建与存储,等同上两句

2查询

>>> publisher_list = Publisher.objects.all() #从数据库取出出版商的信息,后台执行一条 select 语句,返回QuerySet 对象

返回一个记录集(QuerySet)

Publisher.objects.filter(country="U.S.A.", state_province="CA",name__contains="press")

查找类型有:contains(like),icontains(大小写无关的LIKE),startswith和endswith, 还有range(BETWEEN查询)

返回单个对象

Publisher.objects.get(name="Apress") #如果结果是多个对象,会导致抛出异常DoesNotExist

捕获并处理DoesNotExist异常

try:
   p = Publisher.objects.get(name='Apress')
except Publisher.DoesNotExist:
   print "Apress isn't in the database yet."
else:
   print "Apress is in the database."

数据排序

>>> Publisher.objects.order_by("state_province", "address","-name") [0] #减号是反向排序 [0]是取第一个也可用[0:2]不可用负

3. 更新

>>>Publisher.objects.all().update(country='USA') #修改所有记录某字段

>>>Publisher.objects.filter(id=52).update(name='Apress Publishing')#修改指定记录指定字段

4.删除
>>> p = Publisher.objects.get(name="O'Reilly")  
>>> p.delete()                                       #删除指定记录
>>> Publisher.objects.filter(country='USA').delete() #删除记录集
>>> Publisher.objects.all().delete()                 #删除所有记录

访问外键(Foreign Key)值

当你获取一个ForeignKey 字段时,你会得到相关的数据模型对象。 例如:

>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'

对于用`` ForeignKey`` 来定义的关系来说,在关系的另一端也能反向的追溯回来,只不过由于不对称性的关系而稍有不同。 通过一个`` publisher`` 对象,直接获取 books ,用 publisher.book_set.all() ,如下:

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]

实际上,book_set 只是一个 QuerySet(参考第5章的介绍),所以它可以像QuerySet一样,能实现数据过滤和分切,例如:

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.filter(name__icontains='django')
[<Book: The Django Book>, <Book: Pro Django>]

属性名称book_set是由模型名称的小写(如book)加_set组成的。

访问多对多值(Many-to-Many Values)

>>> b = Book.objects.get(id=50)
>>> b.authors.all()
>>> b.authors.filter(first_name='Adrian')
#反向查询也可以

更改数据库模式

Django的数据库层的工作流程

*如果模型包含一个未曾在数据库里建立的字段,Django会报出错信息。 当你第一次用Django的数据库API请求表中不存在的字段时会导致错误(就是说,它会在运行时出错,而不是编译时)。

*Django关心数据库表中是否存在未在模型中定义的列。

*Django关心数据库中是否存在未被模型表示的表格。

*改变模型的模式架构意味着需要按照顺序更改Python代码和数据库。

1添加字段

添加 非NULL 字段

首先,进入开发环境(也就是说,不是在发布环境里):

     在你的模型里添加字段。

     运行 manage.pysqlall[yourapp] 来测试模型新的 CREATETABLE 语句。 注意为新字段的列定义。

     开启数据库交互命令界面(比如psql或mysql ,或者可以使用 manage.pydbshell ),执行 ALTERTABLE 语句来添加新列。

     使用Python的manage.pyshell,通过导入模型和选中表单来验证字段是否正确添加 ,如一切顺利,所有语句都不会报错。

然后在你的产品服务器上再实施一遍这些步骤:

     启动数据库的交互界面

     执行在开发环境步骤中,第三步的ALTERTABLE语句。

     将新的字段加入到模型中,如果你使用了某种版本控制工具,并且在第一步中,已经提交了你在开发环境上的修改,现在,可以在生产环境中更新你的代码了(例如,如果你使用Subversion,执行svnupdate)

      重新启动Web server,使修改生效。

2删除字段

  从Model中删除字段,然后重新启动你的web服务器,用以下命令从数据库中删除字段

  ALTER TABLE books_book DROP COLUMN num_pages;

3删除多对多关联字段

  从你的模型中删除ManyToManyField,然后重启web服务器,用下面的命令从数据库删除关联表:

  DROP TABLE books_book_authors;

4删除模型

  从文件中删除你想要删除的模型,然后重启web 服务器models.py,然后用以下命令从数据库中删除表:

  DROP TABLE books_book;

Managers

在语句Book.objects.all()中,objects是一个特殊的属性,需要通过它查询数据库。 在第5章,我们只是简要地说这是模块的manager 。现在是时候深入了解managers是什么和如何使用了。

总之,模块manager是一个对象,Django模块通过它进行数据库查询。 每个Django模块至少有一个manager,你可以创建自定义manager以定制数据库访问。

下面是你创建自定义manager的两个原因: 增加额外的manager方法,修改manager返回的初始QuerySet。

为模型增加额外的Manager方法

class BookManager(models.Manager):
  def title_count(self,keyword):
     return self.filter(title__icontains=keyword).count() #此处self指manager本身
class Book(models.Model):
  title=models.CharField(max_length=100)
  authors=models.ManyToManyField(Author)
  publisher=models.ForeignKey(Publisher)
  publication_date=models.DateField()
  num_pages=models.IntegerField(blank=True,null=True)
  objects=BookManager()   #也可objects_test, Book.objects_test.title_count('python')

#将取代模型的默认manager(objects)如没定义,会自动创建,命名为objects,为了与自动创建的manager保持一致
  def __unicode__(self):
    return self.title

调用:
>>> Book.objects.title_count('python')
18

修改manager返回的初始QuerySet

class MaleManager(models.Manager):
    def get_query_set(self):
        return super(MaleManager, self).get_query_set().filter(sex='M')
class FemaleManager(models.Manager):
    def get_query_set(self):
        return super(FemaleManager, self).get_query_set().filter(sex='F')
class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
    people = models.Manager()  #将objects设置成manager的实例,如不这么做,可用的manager只是men,women
    men = MaleManager()
    women = FemaleManager()
这个例子允许你执行`` Person.men.all()`` ,`` Person.women.all()`` ,`` Person.people.all()`` 查询,

注意:Django将会把第一个Manager 定义为默认Manager,你应该小心地选择你的默认manager。因为覆盖get_query_set()

了,你可能接受到一个无用的返回对像

模型方法

from django.contrib.localflavor.us.models import USStateField
from django.db import models
class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    birth_date = models.DateField()
    address = models.CharField(max_length=100)
    city = models.CharField(max_length=50)
    state = USStateField() # Yes, this is U.S.-centric...
    def is_midwestern(self):
        "Returns True if this person is from the Midwest."
        return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')
    def _get_full_name(self):
        "Returns the person's full name."
        return u'%s %s' % (self.first_name, self.last_name)
    full_name = property(_get_full_name) #property ?!

#调用

>>> p = Person.objects.get(first_name='Barack', last_name='Obama')
>>> p.is_midwestern()
>>> p.full_name

执行原始SQL查询

有时候你发现Django数据库API带给你的也只有这么多,那你可以写一些自定义SQL查询。 你可以通过导入django.db.connection对像来实现,它代表当前数据库连接。 要使用它,需要通过connection.cursor()得到一个游标对像。 然后,使用cursor.execute(sql,[params])来执行SQL语句,使用cursor.fetchone()或者cursor.fetchall()来返回记录集。 例如:

from django.db import connection, models
class PersonManager(models.Manager):
    def first_names(self, last_name):
        cursor = connection.cursor()
        cursor.execute("""
            SELECT DISTINCT first_name
            FROM people_person
            WHERE last_name = %s""", [last_name])
        return [row[0] for row in cursor.fetchone()]
class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    objects = PersonManager()

#不要把视图代码和django.db.connection语句混杂,把它们放在自定义模型或自定义manager方法中是个不错的主意。

#使用方法

>>> Person.objects.first_names('Lennon')
['John', 'Cynthia']

posted on 2011-12-10 21:23  や尐莊徍左赱  阅读(1049)  评论(0编辑  收藏  举报