例如我有这个代码:
class SomeModel(models.Model):
instance_name = models.UnknownField(max_length=255)
instance_id = models.IntegerField()
我想要将模型名称 (
SomeModel
) 和字段名称(例如 instance_name
)作为输入,并且输出将是该字段的 python 表示形式(例如:srt、int ,漂浮...)
所以会是这样的:
def find_out_the_field_python_type(model: Model, field_name: str) -> type:
# For example model = SomeModel, field_name = instance_id
# return int
return
我试过这个:
instance_id_field = SomeModel._meta.get_field('instance_id')
# Determine the Python representation of the field
python_representation = instance_id_field.get_internal_type()
print(python_representation)
# returns 'IntegerField'
但问题是它返回的不是Python表示,而是Django字段的类型。
我认为你想要的东西是不可能实现的。 源代码可用。看来 Python 类型不是元变量,而是硬编码到字段的
to_python
方法中。
模型是Python和数据库之间的接口。并非所有数据库都直接支持所有 Django 字段类型。如果不这样做,Django 会执行编码来存储和解码来初始化模型实例。
例如,这是来自上述来源的 DecimalField 的
to_python
方法:
def to_python(self, value):
if value is None:
return value
if isinstance(value, float):
return self.context.create_decimal_from_float(value)
try:
return decimal.Decimal(value)
except (decimal.InvalidOperation, TypeError, ValueError):
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)
如果您确定可以运行迭代,将合理的值输入到
to_python
方法中,直到获得成功返回。在执行此操作之前,您需要检查字段的 concrete
(True)和 is_relation
(False)以进行适当的其他处理。
instance_id_field = SomeModel._meta.get_field('instance_id')
if instance_id_field.is_relation:
# ??
if not instance.id_field.is_concrete:
# ??
for thing in (
'0', # should work for Charfield and numeric fields and Boolean
datetime.datetime( 2023,1,1), # for all date or datetime,
0.0, # for above DecimalField,
... # work through the above-linked source for other probe values!
):
try:
x = instance_id_field.to_python( thing)
return type(x)
except Exception:
pass
raise TypeError(
f'Unable to determine Python type of {instance_id_field}')
但这实在是太糟糕了。