djangos字段实例如何在模型中工作

时间:2016-07-09 03:55:18

标签: python django python-3.x django-models

我对Django感到困惑的是模型的字段是如何工作的。

您将它们定义为类变量。

所以,这样的课程:

class Foo:
    avar = "something here"

如果您创建了两个实例。

f1 = Foo()
f2 = Foo()

你将avar设置为别的东西,这会影响Foo的两个实例。那么,django如何在实例之间保持模型字段值正确?它是否只是使用基类变量来创建表,然后在数据库中查询模型/表以返回各个实例的正确字段值?

或者,它是否在元类级别执行推迟创建,直到说出模型__init__ / __new__,然后创建字段的唯一实例?

进一步......对于像amodel = AModel.objects.get(*)这样的东西我可以看到Django如何命中数据库,然后可能返回模型类的实例,并为字段填入列值,以便您可以访问该属性正确值amodel.field。这是有道理的,但我不确定我是否了解这项工作的内部结构。

3 个答案:

答案 0 :(得分:1)

常规类变量是类的属性。它不存储在数据库中(只有model fields)。在您的情况下,avar不是模型字段。它只是一个简单的python类变量。

如果更改Foo实例上的类变量,它只会影响该实例。所有其他实例不会受到影响。证明:

class Foo:
    avar = 'Something'

a = Foo()
b = Foo()

a.avar = 'Something else'

print a.avar
> 'Something else'

print b.avar
> 'Something'

请注意,更改avar上的a不会在b上更改a.avar。另请注意,只有a本身存在,avar的更改值才会存在。此属性不存储在数据库中,如果从数据库加载新对象,它将只具有该类的默认<key>NSLocationAlwaysUsageDescription</key> <array> <string>Location is required to find out where you are</string> </array> <key>Privacy-Location Usage Description</key> <string>Location is required to find out where you are.</string>

答案 1 :(得分:1)

Django使用metaclass收集所有字段,并在var classNameString = 'MyClass'; var myObject = eval("new " + classNameString + "()"); 中收集它们。创建类后,字段不再是模型类本身的一部分:

Model._meta

某些字段类型(例如class Foo(models.Model): bar = models.CharField(max_length=255) >>> Foo.bar Traceback (most recent call last): File "<input>", line 1, in <module> Foo.bar AttributeError: type object 'Foo' has no attribute 'bar' )使用描述符,该描述符将是类属性,但这不是字段本身。

在实例化模型时,ForeignKey__init__ self._meta中的None所有字段,并指定默认值(如果您未提供任何字段默认值,通常为Foo._meta)实例。这确保了每个字段都存在一个值,该值是一个实例变量,并且它可以是任何Python对象。

所有模型方法都使用>>> class Foo(object): ... bar = 'test' ... >>> f1 = Foo() >>> f2 = Foo() >>> f1.bar = 'shadowed' >>> Foo.bar = 'changed' >>> f1.bar 'shadowed' >>> f2.bar 'changed' >>> del f1.bar >>> f1.bar 'changed' 中的信息来确定哪些属性应被视为字段,哪些属于常规属性。

另请注意,当您覆盖实例上的类变量时,实际发生的是类变量被实例变量遮蔽。如果更改类本身的变量,则任何没有实例变量的实例也会更改值。如果删除实例上的变量,该值将恢复为(当前)类变量的值:

int redSensorValue = 0; 
int greenSensorValue = 0; 
int blueSensorValue = 0; 

答案 2 :(得分:0)

这里发生了一些事情。首先,您所做的就是在Foo对象中创建一个字符串,就像任何其他python对象一样。如果您希望它是数据库中的字段,则需要使用模型中的类型。像

这样的东西
from django.db import models

class Foo(models.Model):
    avar = models.CharField(max_length=255)

稍后,如果要对模型进行一些更改,请进行更改,然后调用save()方法更新数据库中的记录。

f1.avar = "Something New"
f1.save()