??xml version="1.0" encoding="utf-8" standalone="yes"?>久久精品免视看,午夜免费久久久久,亚洲国产最新http://www.aygfsteel.com/sshwsfc/category/29337.html1=1zh-cnSat, 02 Feb 2008 10:39:31 GMTSat, 02 Feb 2008 10:39:31 GMT60Django什么情?1) -- Model?amp;ldquo;造Class”概述http://www.aygfsteel.com/sshwsfc/archive/2008/02/02/179019.html差沙差沙Sat, 02 Feb 2008 09:32:00 GMThttp://www.aygfsteel.com/sshwsfc/archive/2008/02/02/179019.htmlhttp://www.aygfsteel.com/sshwsfc/comments/179019.htmlhttp://www.aygfsteel.com/sshwsfc/archive/2008/02/02/179019.html#Feedback0http://www.aygfsteel.com/sshwsfc/comments/commentRss/179019.htmlhttp://www.aygfsteel.com/sshwsfc/services/trackbacks/179019.html在朋友和同事的极力推荐下最q开始看上了(jin)python,其实主要是还是因为python?007q度语言,怎么的也要与时俱q呀.最q一路看来有些心(j)?希望能与大家分n,弟其实也只接触不到一周的python,有说错的地方q望大家指出Ҏ(gu).

不打从py的语法基说v?直接说说对django的心(j)?

接触django首先需要了(jin)解可能就是他那个modelQ徏立一个model׃么都有了(jin)Q这对于搞java得h员来说还是挺有吸引力的(当然貌似对于动态语aq都是小儿科Q,那么让我们先看一个model的例子:(x)

h?jin),直接拿django-admin里面的User出来?/p>


class User(models.Model): 
    username = models.CharField(_('username'), maxlength=30, unique=True, validator_list=[validators.isAlphaNumeric])) 
    first_name = models.CharField(_('first name'), maxlength=30, blank=True) 
    last_name = models.CharField(_('last name'), maxlength=30, blank=True) 
    email = models.EmailField(_('e-mail address'), blank=True) 
    password = models.CharField(_('password'), maxlength=128)) 
    class Meta: 
        ordering = ('username',)

每个属性就是一个库表的字段Q定义v来非常简单明?jin),models里面提供?jin)很多种cȝFieldcM上面的EmailField。不同的Field有不同的讄Q可以看相应的原来来?jin)解相关的设|.

在model class内部q有一个class MetaQ这个Class的属性制定了(jin)q个表的一些存取策略,例如q里的ordering。MetaClass里面的属性可以用model的_meta属性取得。OKQ那么这样一个model怎么p实现Ҏ(gu)据库表的灉|操作?jin)呢。让我们来看看吧?/p>

首先先分析一?django/django/db/models/base.pyq个文gQ其中包含了(jin)models.Modelq类的定义:(x)

看看class定义的第一行吧Q第一行就够我琢磨一阵子的了(jin)Q?/p>


class Model(object):
    __metaclass__ = ModelBase

Model采用?jin)new style class定义Q关于这个内容大家可以放狗看一下,W一行是一个__metaclass__属性的定义Q该属性的值是ModelBaseQ这是一个类。__metaclass__的意思是Q指定一个classQ这个class的实例就是本classQ相信?zhn)已经晕?jin)。那么就拿这个Model的例子来说明一下,如果没有__metaclass__q个属性,产生一个实例就是正常的程Q有?jin)这个属性流E会(x)有改变:(x)

首先调用BaseModel.__new__(cls, name, bases, attrs)q个Ҏ(gu)Q回q回的值是一个classcdQ然后用q个class来创建实例。其实BaseModel是Model的元c,来制定Modelq个cȝ最l样子。关于元cȝ更多信息L(fng)q里

那么我们的目光一下{UdBaseModelq个cMQ我有种直觉QMetaq个class最后可以用_meta来取是在这里做的手脚,看一下BaseModel的定义吧Q有炚wQ?/p>


class ModelBase(type):
    "Metaclass for all models"
    def __new__(cls, name, bases, attrs):
        # If this isn't a subclass of Model, don't do anything special.
        if name == 'Model' or not filter(lambda b: issubclass(b, Model), bases):    #1
            return super(ModelBase, cls).__new__(cls, name, bases, attrs)

        # Create the class.
        new_class = type.__new__(cls, name, bases, {'__module__': attrs.pop('__module__')})    #2
        new_class.add_to_class('_meta', Options(attrs.pop('Meta', None)))     #3
        new_class.add_to_class('DoesNotExist', types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {}))

        # Build complete list of parents                                      #4
        for base in bases:
            # TODO: Checking for the presence of '_meta' is hackish.
            if '_meta' in dir(base):
                new_class._meta.parents.append(base)
                new_class._meta.parents.extend(base._meta.parents)

        model_module = sys.modules[new_class.__module__]

        if getattr(new_class._meta, 'app_label', None) is None:
            # Figure out the app_label by looking one level up.
            # For 'django.contrib.sites.models', this would be 'sites'.
            new_class._meta.app_label = model_module.__name__.split('.')[-2]  #5

        # Bail out early if we have already created this class.
        m = get_model(new_class._meta.app_label, name, False)                 #6
        if m is not None:
            return m

        # Add all attributes to the class.
        for obj_name, obj in attrs.items():
            new_class.add_to_class(obj_name, obj)                             #7

        # Add Fields inherited from parents
        for parent in new_class._meta.parents:
            for field in parent._meta.fields:
                # Only add parent fields if they aren't defined for this class.
                try:
                    new_class._meta.get_field(field.name)
                except FieldDoesNotExist:
                    field.contribute_to_class(new_class, field.name)          #8

        new_class._prepare()

        register_models(new_class._meta.app_label, new_class)                 #9
        # Because of the way imports happen (recursively), we may or may not be
        # the first class for this model to register with the framework. There
        # should only be one class for each model, so we must always return the
        # registered version.
        return get_model(new_class._meta.app_label, name, False)              #10


单分析一下这个代码:(x)

1. (g)查class是否为Model的子c,不是的话Q不做Q何处理,直接传给父类处理Q也q当于正常的处理了(jin)classQ注意super在多重(h)承的时候应该严g?

2. 用type来创建类Q创建的是正常的ModelClass

3. q句很重要,add_to_class是Model里面的classҎ(gu)Q这个方法其实就是传入name和valueQ给Modeldclass属?看到?jin),原来奇的_meta是q么来的. 提到add_to_classҎ(gu)Q简单看一下它的代码:(x)


    def add_to_class(cls, name, value):
        if name == 'Admin':
            assert type(value) == types.ClassType, "%r attribute of %s model must be a class, not a %s object" % (name, cls.__name__, type(value))
            value = AdminOptions(**dict([(k, v) for k, v in value.__dict__.items() if not k.startswith('_')]))
        if hasattr(value, 'contribute_to_class'):
            value.contribute_to_class(cls, name)
        else:
            setattr(cls, name, value)
    add_to_class = classmethod(add_to_class)


最后一句是制定q个Ҏ(gu)是classҎ(gu)Q特点就是方法的W一个参数是本classQ其实classmethod是一个装饰器Q在2?之后可以使用@来简写。这里不得不提的是他对Admin的特D处理,虽然AdminOption不是在admin模块里面的,但是q么做还是跟一个Admin的东东绑定v来了(jin)Q在java的世界解耦是一件大事,看到下面q有?contribute_to_class'q个Ҏ(gu)的特D处理,django为啥不弄的解耦点呢。而且同样是包装成OptionQ一个是在BaseModel里面弄(那个Meta的包装)(j)Q一个在add_to_classҎ(gu)里面弄,实在有点不优雅,可能q没?jin)解太多Q不知道他的深度用意吧?/p>

4. Meta的集成,Option的这个类提供l承Ҏ(gu)

5. 取得applabelQ就是把model的名字分割取到数W二个,我很喜欢-2q样的设?/p>

6. get_modelҎ(gu)取得~存里面的东ѝ?/p>

7. 把所有的class attr拿出来搞一遍,一般的属性就setattr弄回M(jin)Q要是这个属性有contribute_to_classq个callable属性,那就执行之(Admin的处理完全也可以q样Q其实我们常用的objects是用这个方法弄的)(j)

8. 每个Field调用自己的contribute_to_classҎ(gu)来进行特D的处理

9. q入~存Q,暂且叫缓存吧Q里面的东西大家看看很简?文g?/django/django/db/models/loading.py 里面q是有很多内容的

10.看注释说的很清楚?jin),我们一定要在缓存里面拿model?/p>

 

其中需要指出的是,new_class._prepare() q个Ҏ(gu)Q简单列出片D:(x)


    def _prepare(cls):
        # Creates some methods once self._meta has been populated.
        opts = cls._meta
        opts._prepare(cls)

        Q.Q.

        dispatcher.send(signal=signals.class_prepared, sender=cls)

中间省略?jin)一些代码,不是我没看懂的就是没意思的Q关键要看这个dispatcher呀。这里是监听者模式,dispatcher.send(signal=signals.class_prepared, sender=cls)放松?jin)一个包含特定信L(fng)事gQ让监听的h可以做相应的处理。这L(fng)信号q有很多U,我们可以很简单的截获信号Q处理相应的内容。也许?zhn)q记得,在我们创建db的时候,?x)提C创Z个超U用P其实是用这个方法来弄的?/p>

那我Z么要把这个单独拿出来说呢Q因为监听这个事件的Z是别人,?objects"Q!Q在文g/django/django/db/models/manager.py的开头就有这L(fng)代码Q?/p>


def ensure_default_manager(sender):
    cls = sender
    if not hasattr(cls, '_default_manager'):
        # Create the default manager, if needed.
        try:
            cls._meta.get_field('objects')
            raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % cls.__name__
        except FieldDoesNotExist:
            pass
        cls.add_to_class('objects', Manager())

dispatcher.connect(ensure_default_manager, signal=signals.class_prepared)


定义?jin)一个callableQ然后监听signals.class_prepared信号Q呵呵,q上?jin)吧Q只要Class准备好了(jin)Q就调用q个Ҏ(gu)。简单判断有没有_default_manager'属性和meta里面的objects后,开始插入objects。cls.add_to_class('objects', Manager()) 很熟(zhn)吧Q前面讲q不多说?jin)?/p>

PSQ写到这里不由得感叹Qؓ(f)啥同h往(xin)Class里面加入东东Q要搞这么多的花样呢Q我以前也写q一个Rails配置加蝲q程?a href="http://www.aygfsteel.com/sshwsfc/archive/2006/11/20/82401.html" target="_blank">分析文档Q虽然一个简单的加蝲配置把所有动态语a玩个遍,但是q也太不规范?jin)吧Q可能不q么玩就不算“动?#8221;语言?jin)吧Q哈哈?/p>

 

l于Model的Class造好?jin),怿大家以后造自qClass也能玩出更多的花栗那么可以开始下一步了(jin)。我到老家后再写吧Q打讲讲神奇的objectsQ也是ManagerQ其实就是玩QuerySet。。那里有很多的__xxx__Ҏ(gu)Q很好很强大



差沙 2008-02-02 17:32 发表评论
]]>
վ֩ģ壺 | | | | | | | Ҿ| | ء| ɽ| Դ| | ۽| | Т| | ԫ| | | ӻ| | | żҸ| Ϫ| Ӻ| | | ĩ| ƾ| ػ| | ˫| | | | | ά| Ϫ| | |