我正在尝试实现一个自定义Django字段,该字段会在DB中保留我的某个模型类的名称(例如“Cat”,“Dog”,“Restaurant”,“SuperPrivateCommercialDataPiece”等)并返回请求时的类对象:
class Cat(models.Model):
...
class SomeDataPiece(models.Model):
relatedTo = MyGloriousFieldType(null=True)
...
newPiece = SomeDataPiece()
newPiece.relatedTo = Cat
print newPiece.relatedTo # should print <class 'myproj.myapp.models.Cat'>
我真的做到了这一点。我已经分组models.Field
,设置了__metaclass__
等等:
class MyGloriousFieldType(models.Field):
description = "No description, just gloriosity."
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 40
super(BlockTypeField, self).__init__(*args, **kwargs)
def db_type(self, connection):
return 'char(40)'
def to_python(self, value):
if not value:
return None
elif inspect.isclass(value) and issubclass(value, models.Model):
return value
elif hasattr(myproj.myapp.models, value):
return getattr(myproj.myapp.models, value)
else:
raise ValidationError("Invalid model name string")
def get_db_prep_value(self, value, **kwargs):
if inspect.isclass(value) and issubclass(value, models.Model):
return value.__name__
else:
# it is actually never raised
raise ValidationError("Invalid value, Model subclass expected")
def value_to_string(self, instance):
value = self._get_val_from_obj(obj)
return self.get_prep_value(value)
在上面的代码中,它的工作方式与预期一致。我还在管理员中注册了一些包含这些字段的模型,现在我甚至可以创建这样的对象;为MyGloriousFieldType字段创建文本输入。
当我尝试使用MyGloriousFieldType字段编辑已存在的对象时,危机就开始了。首先,它使用“Cat对象”而不仅仅是“Cat”填充文本字段。其次,当我将其更改回“Cat”并单击“保存更改”时,会出现错误:
TypeError at /admin/myapp/somedatapiece/3/
unbound method prepare_database_save() must be
called with Cat instance as first argument (got
MyGloriousFieldType instance instead)
那么,我做错了什么?
答案 0 :(得分:0)
好吧,我已经明白了。问题出在Django核心内部。字段只是不能返回包含models.Field
等prepare_database_save
属性的Python对象,否则会发生错误。我解决这个问题的方法是在(MyClassObject, )
中返回元组MyClassObject
而不是to_python()
。奇怪,但我能做些什么......也许我会尝试在Django的Github页面上发布一个问题。