我希望我的Django自定义模型字段在模型实例上设置属性。
我确定这不是这样的,但这是一个例子:
class MyField(models.Field):
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
super(MyField, self).__init__(*args, **kwargs)
model_instance = ????
setattr(model_instance, "extra_attribute", "It's working!")
class MyModel(models.Model):
my_field = MyField()
model_instance = MyModel.objects.get(pk=123)
print model_instance.extra_attribute # output: "It's working!"
Django的ForeignKey模型字段正在做类似的事情,所以有可能:P 我认为ForeignKey字段正在使用contrib_to_class方法。
答案 0 :(得分:1)
您可以创建一个将替换该字段的特殊Proxy类。获取或设置字段值时,可以使用“obj”属性访问模型实例。见这个例子:
class ObjectField(models.PositiveSmallIntegerField):
class ObjectProxy:
def __init__(self, field):
self.field = field
def __get__(self, obj, model):
if obj is None:
return self.field # this is required for initializing model field
value = obj.__dict__[self.field.name] # get actual field value
# ... here you can do something with value and model instance ("obj")
return value
def __set__(self, obj, value):
# same here
obj.__dict__[self.field.name] = value
def contribute_to_class(self, cls, name):
super().contribute_to_class(cls, name)
# set up our proxy instead of usual field
setattr(cls, name, ObjectField.ObjectProxy(self))
答案 1 :(得分:0)
对不起,您无法访问Field
对象内的模型实例。 Django的ForeignKey
通过单独的foo_id
和name
字段来完成attname
项,但foo_id = 123
的实际设置与所有其他模型字段deep in the QuerySet code,不与字段类交互。
从概念上讲,你要做的是一个坏主意 - 远距离行动。如果添加特定字段可能会导致不相关的模型功能中的错误,例如,如果另一个字段的属性期望被覆盖,该怎么办?至少可以说,调试很困难。我不知道你的基本目标是什么,但它应该在模型代码中完成,而不是在字段类中完成。
这里有一个ModelField
可以做你想要的事情:
https://gist.github.com/1987190
实际上已经很老了(就像1.0之前的版本,现在不记得了),不得不把它弄脏了 - 我不确定它是否仍然有用。但它绝对可行,希望这能给你一个想法。
答案 2 :(得分:-1)
init 。因此,您可以将属性添加到模型类中(例如,使用'add_to_class'http://www.alrond.com/en/2008/may/03/monkey-patching-in-django/)。要将属性添加到实例,您应该覆盖实例的 init (但我认为这不是您的情况)。
答案 3 :(得分:-3)
怎么样
model_instance = SomeExtraModel.objects.get(pk=1456)
用有意义的东西取代1456