我想在Django模型的字段中添加一些自定义字段选项,因为我正在构建一个应用程序,它将与仅遵循一般方案的模型一起使用。我们的想法是应用程序仍然可以使用新定义的模型,并且所有配置都应该直接在models.py
中进行。因此,我想传递一些选项作为关键字参数,例如定义该字段是否应显示在外部表示中。问题是只传递新的关键字参数会引发意外关键字参数的错误。到目前为止,我已经使用了类似的东西,我认为这有点难看:
class CustomCharField(models.CharField):
def __init__(self, *args, **kwargs):
self.custom_option = kwargs['custom_option']
del kwargs['custom_option']
super().__init__(*args, **kwargs)
会有更清洁的解决方案吗?
此外,我想知道这种方法是否正确,或者是否有一种不同的首选方法来编码Django中模型的外部表示,类似于Flask的marshmallow。
答案 0 :(得分:0)
无论这种方法是否正确,我的解决方案是将自定义关键字参数附加到所有Django Field
类。自定义选项可以在dict
中指定,变量名称为keys
,默认为values
。
from django.db.models import fields
# Get a dictionay of all field classes.
plain_fields = dict([(name, cls) for name, cls
in fields.__dict__.items()
if type(cls) == type and
issubclass(cls, fields.Field) and
cls != fields.Field])
def options_factory(options):
"""
Produces a class that allows defining keyword arguments as
a mixin on another class.
Args:
options (dict): Name of the keyword arguments mapped to their
default value.
"""
class OptionsMixin():
def __init__(self, *args, **kwargs):
for name, default in options.items():
self.__dict__[name] = kwargs.pop(name, default)
super().__init__(*args, **kwargs)
return OptionsMixin
# Specify custom options with default values.
customoptions = {'supercooloption': 47,
'superfluous_option': None}
CustomOptions = options_factory(customoptions)
# Iterate over the field classes and mix the CustomOptions in.
optionfields = {}
for name, cls in plain_fields.items():
optionfields[name] = type(name, (CustomOptions, cls), {})
# Update the modules __dict__ so the classes can be imported.
globals().update(optionfields)
我在optionmodels.py
中的models.py
这样的单独文件中指定了此内容,然后可以像import myapp.optionmodels as omodels
一样导入,这样可以使用自定义字段,与标准相比只需稍微改变语法Django字段。
请注意,ManyToManyField
之类的关系字段具有不同的__init__
签名,因此需要使用不同的mixin来调用super().__init__(to, *args, **kwargs)
。