【问题标题】:How do Django models work?Django 模型是如何工作的?
【发布时间】:2012-08-13 22:19:30
【问题描述】:

所以我可以像这样创建 Django 模型:

from django.db import models

class Something(models.Model):
    title = models.TextField(max_length=200)

我可以像这样使用它:

thing = Something()
#set title
thing.title = "First thing"
#get title
thing.title

一切正常,但我想了解它是如何工作的。

title = models.TextField(max_length=200)

在上面的非 Django Python 代码中,定义了 models.TextField 类型的类变量标题,我也可以这样访问它:thing.__class__.title(link)

但是在 Django 中,当我创建Something 的实例时,我突然有了一个标题属性,我可以在其中获取/设置文本。并且无法使用thing.__class__.title 访问它所以很明显,在做 thing.title 时我不是在访问类变量“title”而是访问一些生成的属性/属性,或者?

我知道字段以 thing._meta.fields 结尾,但如何? 发生了什么以及如何?

1、Django是否在幕后创建属性“title”?

2、类变量“title”发生了什么?

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    python 非常强大,允许开发者使用 intrespection。

    django 使用了很多元类。而且models.Model似乎也使用它。见 django\db\models\base.py

    class Model(object):
        __metaclass__ = ModelBase
    

    我认为元类只是获取类属性,例如字段,并且为这些模型子类的所有新实例创建适当的变量。

    1) 是的,django 自动创建属性“title”的实例变量 2)同理,元类将字段移动到元类中...

    【讨论】:

      【解决方案2】:

      我认为 Django 文档对say on this 的要求很难超越。

      Model 类(参见 base.py)有一个 metaclass 属性,该属性将 ModelBase(也在 base.py 中)定义为用于创建新类的类。因此调用 ModelBase.new 来创建这个新的 Example 类。重要的是要意识到我们在这里创建的是类对象,而不是它的实例。换句话说,Python 正在创建最终将绑定到我们当前命名空间中的示例名称的东西。

      基本上,metaclass 定义了如何创建一个类本身。在创建期间,可以将其他属性/方法/任何东西绑定到该类。 stackoverflow answer 给出的示例,将类的所有属性大写

      # remember that `type` is actually a class like `str` and `int`
      # so you can inherit from it
      class UpperAttrMetaclass(type): 
          # __new__ is the method called before __init__
          # it's the method that creates the object and returns it
          # while __init__ just initializes the object passed as parameter
          # you rarely use __new__, except when you want to control how the object
          # is created.
          # here the created object is the class, and we want to customize it
          # so we override __new__
          # you can do some stuff in __init__ too if you wish
          # some advanced use involves overriding __call__ as well, but we won't
          # see this
          def __new__(upperattr_metaclass, future_class_name, 
                      future_class_parents, future_class_attr):
      
              attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
              uppercase_attr = dict((name.upper(), value) for name, value in attrs)
      
              return type(future_class_name, future_class_parents, uppercase_attr)
      

      以类似的方式,Django 的模型元类可以消化您已应用于该类的属性,并添加各种有用的属性以用于验证/等,包括偶数方法和其他什么。

      【讨论】:

      • 感谢 code.djangoproject.com 上的文档链接!我只是在 docs.djangoproject.com 上寻找解释
      • 所以 metacclass 可以添加属性、方法等,但它也可以删除属性/方法等,因为 CharField 类型的类变量标题已被明确删除?还是不是?
      • @Michal 当然,记住所有 python 属性都存储在__dict__ 中。通过操纵__dict__,您几乎可以做任何事情。
      猜你喜欢
      • 2018-07-06
      • 2023-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-20
      • 1970-01-01
      • 2012-12-16
      • 2011-09-24
      相关资源
      最近更新 更多