这是我在models.py中提出的解决方案:
from django.db import models
@classmethod
def model_field_exists(cls, field):
try:
cls._meta.get_field(field)
return True
except models.FieldDoesNotExist:
return False
models.Model.field_exists = model_field_exists
Run Code Online (Sandbox Code Playgroud)
并使用它像:
Post.field_exists('title') # > True or False
Run Code Online (Sandbox Code Playgroud)
问题来自外键,我的Post模型属于一个类别,此检查有效:
Post.field_exists('category') # > True
Run Code Online (Sandbox Code Playgroud)
但是这个没有:
Post.field_exists('category_id') # > False
Run Code Online (Sandbox Code Playgroud)
这是db中的实际字段名称,我需要像这样检查它.我怎么能在django做到这一点?
Pho*_*beB 10
hasattr(cls,field)在所有情况下都不起作用,例如使用mixins的情况.安全测试是:
try:
model._meta.get_field(field)
.. do stuff here
except FieldDoesNotExist:
pass
Run Code Online (Sandbox Code Playgroud)
要么
field = None
try:
field = model._meta.get_field(field)
except FieldDoesNotExist:
pass
if field:
.. do stuff here
Run Code Online (Sandbox Code Playgroud)
如果该字段不存在,您可以使用getattr返回默认值.如下所示
getattr(table, field, False)
Run Code Online (Sandbox Code Playgroud)
但这个没有:
Post.field_exists('category_id') # > False
这是 db 中的实际字段名称,我需要像这样检查它。我怎样才能在 Django 中做到这一点?
除了_id部分之外的所有情况都在另一个答案中得到了充分的回答。为了处理 _id 情况,除了该答案之外,您基本上还需要一个特殊的条件来适当地处理这些情况。类似这样的东西:
if field_name.endswith('_id'):
try:
field = model._meta.get_field(field_name.strip('_id'))
except FieldDoesNotExist:
return False
if not f.is_relation:
return False
return True
Run Code Online (Sandbox Code Playgroud)
需要进行额外的检查以确保字段减号_id返回外键,而不是其他类型的字段恰好具有相同的名称,这意味着name_id模型上的字段无效。
您的“category_id”字段是https://docs.djangoproject.com/en/1.10/ref/models/meta/术语中的隐藏字段。get_field 无法检索它。
也许遍历所有字段并检查它们的名称;get_fields 可以返回隐藏字段:
for field in cls._meta.get_fields(include_hidden=True):
if field.name == field:
return True
return False
Run Code Online (Sandbox Code Playgroud)
如果您需要关心 db_column 更改为默认值的字段,您也可以测试 field.db_column (但如果未明确设置,则未设置)。
小智 2
为什么需要这个?对象关系映射器的想法是让类来描述/定义数据库。因此,如果您想测试模型的类型,您应该isinstance像这样使用:
if isinstance(model, Post):
# model is a Post, Post has a publish()
model.publish()
elif isinstance(model, Comment):
# model is a Comment, Comment has a foo()
model.foo()
Run Code Online (Sandbox Code Playgroud)
您的模型定义定义了您的架构。不应该有理由必须测试字段是否存在。如果有,您可能没有遵循通过使用setattr?分配字段的最佳实践。