Declarative语法

一些Django很突出的便利特性,其中有“declarative syntax(声明性语法)”,从读写,理解上都很简单的。这种语法设计是最小化重复的样板语法,并提供优雅,可读性的代码。举例来说,这里有一个典型的Django model:

class Contact(models.Model):
    """
    Contact information provided when sending messages to the owner of the site.
    """
    name = models.CharField(max_length=255)
    email = models.EmailField()

这 个declarative语法已经成为django代码里的标志性特性,因此许多提供框架的第三方应用都和django类似采用这种语法。这有助于开发人 员通过代码的内聚性容易理解和处理新的代码。一旦你理解了怎样使用declarative语法来创建一个类,你就能很容易的创建采用django特性的 类,包括官方和社区提供的。

看看declarative语法示例,用这种模式为django创建一个完全崭新的框架,将变得容易起来。在你自己的代码中使用declarative语法将会帮助你和同事更容易失陪代码,确保高生产率。总之,开发人员的效率是django, python首要目标。

下一部分内容描述的是declarative语法的通常用法,例子来自django的ORM,细节见第3章。

存取中心点

典型的,一个包将提供一个单一的模块,从这里应用程序可以存取所有必要的工具。这个模块可以把位于自己树下其他的地方的类和函数都拉过来,但他们将只在一个中心点上集中起来处理。

from django.db import models

一旦导入,这个模块提供一个类作为一个base class,供所有基于框架的子类使用。任何保留在类中的东西都用作新的子类属性。这些对象将会结合在一起来控制新类的运转。

基类(Base class)

每 一个特性都伴随着至少一个base class开始,可能会有多个,依赖于框架的需要,但为了让这个特性起作用至少是要有一个base class的。没有它的话,每一个类的定义中都不得不显式地包括一个__metaclass__属性,这是一个实现的细节,大多数用户本不应该知道它。

class Contact(models.Model):

除了检查已经定义的属性外,这个base class将提供一组方法和属性,子类会自动继承。像其他的类一样,它可简单,也可以复杂,要看框架要求提供什么特性。

属性类(Attribute Classes)

带有基类(base class)的模块也将提供一组被实例化的类,通常是带有可选的参数,来定制行为特征,这些实例化的类是作为新类的属性。

class Contact(models.Model):
    name = models.CharField(max_length=255)
    email = models.EmailField()

这些对象提供的特性会随着框架变化非常大,有些可能和标准属性完全不一致。通常他们和metaclass结合起来,一起提供一些额外的,超出分配属性范围隐藏在后面的功能。当创建这个额外的功能时,这些属性的选项也通常被metaclass读取。

举 例来说,Django的Model使用字段属性的名字和选项来描述底层数据库表,然后自动在数据库中创建。字段名是来存取表中的列,而属性类和选项把原生 的python数据类型自动转换成正确的数据库值。关于django处理model类和field字段的更多信息参见下一章。

对类属性排序

当 使用declarative语法时,有一个潜在的疑惑就是python的字典类型是不排序的,它不关心分配值的顺序。通常这也不是什么问题,但是当要检查 一个名字空间的字典时,想看看声明关键字的顺序的时候,那就不可能办到了。如果一个框架需要通过一些特殊的属性进行迭代,或者把这些显示给用户或编程者, 那么按照已经定义好的相同顺序来存取属性就很有用处了。这就让编程者能对属性的顺序进行控制,而不是由编程语言决定的任意顺序。

这个问题的一个简单的解决方法是让属性跟踪实例化序列;然后metaclass对它们进行相应排序。这个处理过程是先把所有的属性类继承自一个特殊的基类,由它来计算这个类被实例化多少次,为每个实例分配一个值。

class BaseAttribute(object):
    creation_counter = 1
    def __init__(self):
        self.creation_counter = BaseAttribute.creation_counter
        BaseAttribute.creation_counter += 1

对象实例与类相比有不同的名字空间,因此这个类的所有实例都有一个creation_counter,它用来按被实例化的次序进行排序。这就是django对model和form的字段进行排序的原理。

类声明

用 一个模块中所有的类来创建一个应用类,就像和定义一个子类和属性一样简单。不同的框架有不同的属性类的名字,类的要求也不同,使用的组合情况也不同。甚至 可能还有保留的名字,如果你用保留名定义一个属性,就会引起冲突,但是这样的问题很少,而且当使用这类语法来开发新的框架时,保留名是建议不使用的。通常 的规则是允许开发人员尽可能自取所需,而没有框架的羁绊。

from django.db import module

class Contact(models.Model):
    """
    Contact information provided when sending messages to the owner of the site.
    """
    name = models.CharField(max_length=255)
    email = modles.EmailField()

这段简单的代码想要表达的意思已经足够了,允许框架让新类带有一个健壮的附加功能,而不要求程序员人工介入处理。同时也要注意所有的属性类是怎样由同一个基础模块提供的,以及当分配model时,怎样被实例化的。

对于只是框架提供的特性,一个类的声明是没有限制的。既然任何有效的python代码都允许,你的类也可以包含不同的方法和属性,和框架提供的特性混杂在一起。