永发信息网

Django什么情况

答案:1  悬赏:10  手机版
解决时间 2021-02-14 00:04
Django什么情况
最佳答案
在朋友和同事的极力推荐下最近开始看上了python,其实主要是还是因为python是2007年度语言,怎么的也要与时俱进呀.最近一路看来有些心得,希望能与大家分享,小弟其实也只接触不到一周的python,有说错的地方还望大家指出改正.

不打算从py的语法基础说起了,直接说说对django的心得:

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

偷懒了,直接拿django-admin里面的User出来了

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',)
每个属性就是一个库表的字段,定义起来非常简单明了,models里面提供了很多种类的Field类似上面的EmailField。不同的Field有不同的设置,可以看相应的原来来了解相关的设置.

在model class内部还有一个class Meta,这个Class的属性制定了这个表的一些存取策略,例如这里的ordering。MetaClass里面的属性可以用model的_meta属性取得。OK,那么这样一个model怎么就能实现对数据库表的灵活操作了呢。让我们来看看吧。

首先先分析一下/django/django/db/models/base.py这个文件,其中包含了models.Model这类的定义:

看看class定义的第一行吧,第一行就够我琢磨一阵子的了:

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

首先调用BaseModel.__new__(cls, name, bases, attrs)这个方法,回返回的值是一个class类型,然后用这个class来创建实例。其实BaseModel就是Model的元类,来制定Model这个类的最终样子。关于元类的更多信息请看这里

那么我们的目光一下转移到BaseModel这个类上,我有种直觉,Meta这个class最后可以用_meta来取就是在这里做的手脚,看一下BaseModel的定义吧,有点长:

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
简单分析一下这个代码:

1. 检查class是否为Model的子类,不是的话,不做任何处理,直接传给父类处理,也就相当于正常的处理了class,注意super在多重继承的时候应该严格使用

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

3. 这句很重要,add_to_class是Model里面的class方法,这个方法其实就是传入name和value,给Model添加class属性.看到了,原来神奇的_meta就是这么来的. 提到add_to_class方法,简单看一下它的代码:

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)
最后一句是制定这个方法是class方法,特点就是方法的第一个参数是本class,其实classmethod就是一个装饰器,在2。4之后可以使用@来简写。这里不得不提的是他对Admin的特殊处理,虽然AdminOption不是在admin模块里面的,但是这么做还是跟一个Admin的东东绑定起来了,在java的世界解耦是一件大事,看到下面还有对'contribute_to_class'这个方法的特殊处理,django为啥不弄的解耦点呢。而且同样是包装成Option,一个是在BaseModel里面弄(那个Meta的包装),一个在add_to_class方法里面弄,实在有点不优雅,可能还没了解太多,不知道他的深度用意吧。
4. Meta的集成,Option的这个类提供继承方法

5. 取得applabel,就是把model的名字分割取到数第二个,我很喜欢-2这样的设定

6. get_model方法取得缓存里面的东西。

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

8. 每个Field调用自己的contribute_to_class方法来进行特殊的处理

9. 进入缓存,,暂且叫缓存吧,里面的东西大家看看很简单 文件在 /django/django/db/models/loading.py 里面还是有很多内容的

10.看注释说的很清楚了,我们一定要在缓存里面拿model。
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
爸爸妈妈看日记算是触犯隐私权吗
中国电信(郭陆滩营业厅)地址在什么地方,想过
正宗钟鼓楼戴家老六肉饼在哪里啊,我有事要去
找不到双休的工作怎么办
中国移动(李店乡服务厅)地址有知道的么?有点
小学作文、春节快要到了、见到亲戚,你准备怎
卫生间里有两支太阳能管,怎么知道哪个是溢水
中国移动(柳树店营业厅)地址有知道的么?有点
中国移动(张广庙服务厅)怎么去啊,我要去那办
吾祖尔牛肉面馆这个地址在什么地方,我要处理
中国移动(红苏路营业厅)地址好找么,我有些事
美域美家南门怎么去啊,有知道地址的么
中国电信(红苏路专营厅)地址在哪,我要去那里
中国联通(三河尖营业厅)地址有知道的么?有点
车窗不断起雾,这个问题有什么好的解决方案?
推荐资讯
朵儿美容美体怎么去啊,我要去那办事
品玉百货地址在什么地方,想过去办事
高三还没有入团 有什么影响对未来
陈锡民是不是世界上最笨的人
玉林市金顿服装有限公司地址在哪,我要去那里
学位英语什么时候考试
上海2018最低工资标准多少
我的车停在底下车厂好久了。请问费用怎么算
淘宝上好评后怎样设置自动发送赠品下载链接
羊肉怎么吃最有营养
我和男友刚谈,他说要一起去看电影,我应该做
吃柿子感到有点涩,这是因为它含有单宁,这种
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?