我定义了一个(最终)继承自 models.Model
的 User
类。我想获取为此模型定义的所有字段的列表。例如,phone_number = CharField(max_length=20)
。基本上,我想检索从 Field
类继承的任何内容。
我想我可以利用 inspect.getmembers(model)
来检索这些,但它返回的列表不包含任何这些字段。看起来 Django 已经掌握了这个类并添加了它所有的魔法属性并剥离了实际定义的内容。那么......我怎样才能得到这些领域?他们可能具有为自己的内部目的检索它们的功能?
Django 1.8 及更高版本:
您应该使用 get_fields()
:
[f.name for f in MyModel._meta.get_fields()]
get_all_field_names()
方法是 deprecated starting from Django 1.8 and will be removed in 1.10。
上面链接的文档页面提供了一个完全向后兼容的 get_all_field_names()
实现,但对于大多数目的,前面的示例应该可以正常工作。
1.8 之前的 Django 版本:
model._meta.get_all_field_names()
这应该够了吧。
这需要一个实际的模型实例。如果您只有 django.db.models.Model
的子类,那么您应该调用 myproject.myapp.models.MyModel._meta.get_all_field_names()
由于大多数答案都已过时,我将尝试在 Django 2.2 Here posts-您的应用程序(帖子、博客、商店等)上更新您
1) 来自模型 链接:https://docs.djangoproject.com/en/stable/ref/models/meta/
from posts.model import BlogPost
all_fields = BlogPost._meta.fields
#or
all_fields = BlogPost._meta.get_fields()
注意:
all_fields=BlogPost._meta.get_fields()
还会得到一些关系,例如:不能在视图中显示。就我而言:
Organisation._meta.fields
(<django.db.models.fields.AutoField: id>, <django.db.models.fields.DateField: created>...
和
Organisation._meta.get_fields()
(<ManyToOneRel: crm.activity>, <django.db.models.fields.AutoField: id>, <django.db.models.fields.DateField: created>...
2) 从实例
from posts.model import BlogPost
bp = BlogPost()
all_fields = bp._meta.fields
3) 从父模型
假设我们将 Post 作为父模型,并且您希望查看列表中的所有字段,并在编辑模式下将父字段设置为只读。
from django.contrib import admin
from posts.model import BlogPost
@admin.register(BlogPost)
class BlogPost(admin.ModelAdmin):
all_fields = [f.name for f in Organisation._meta.fields]
parent_fields = BlogPost.get_deferred_fields(BlogPost)
list_display = all_fields
read_only = parent_fields
clean_field_names = [str(h).split('.')[2].replace("_", " ").title() for h in all_fields]
all_fields = bp._meta.fields
这里提到的 get_all_related_fields()
方法是 deprecated in 1.8。从现在开始是get_fields()
。
>> from django.contrib.auth.models import User
>> User._meta.get_fields()
我发现将此添加到 django 模型非常有帮助:
def __iter__(self):
for field_name in self._meta.get_all_field_names():
value = getattr(self, field_name, None)
yield (field_name, value)
这让您可以:
for field, val in object:
print field, val
django.db.models.fields.related.RelatedObjectDoesNotExist: CustomModel has no custom_attribute.
ForeignKey
对我来说很好。虽然,默默地捕获所有异常是一种反模式。更好地捕捉 AttributeError
,或者至少记录一些异常被默默吞下。
self._meta.get_all_field_names()
已被折旧和删除。您可以使用 for field in self._meta.get_fields()
之类的内容,然后使用 yield (field.name, field.value_from_object(self))
这可以解决问题。我只在 Django 1.7 中测试它。
your_fields = YourModel._meta.local_fields
your_field_names = [f.name for f in your_fields]
Model._meta.local_fields
不包含多对多字段。您应该使用 Model._meta.local_many_to_many
获取它们。
目前尚不清楚您是否有类的实例或类本身并尝试检索字段,但无论哪种方式,请考虑以下代码
使用实例
instance = User.objects.get(username="foo")
instance.__dict__ # returns a dictionary with all fields and their values
instance.__dict__.keys() # returns a dictionary with all fields
list(instance.__dict__.keys()) # returns list with all fields
使用类
User._meta.__dict__.get("fields") # returns the fields
# to get the field names consider looping over the fields and calling __str__()
for field in User._meta.__dict__.get("fields"):
field.__str__() # e.g. 'auth.User.id'
def __iter__(self):
field_names = [f.name for f in self._meta.fields]
for field_name in field_names:
value = getattr(self, field_name, None)
yield (field_name, value)
这在 django==1.11.8
对我有用
MyModel._meta.get_all_field_names()
在 Django 1.10 中被弃用几个版本并删除。
这是向后兼容的建议 from the docs:
from itertools import chain
list(set(chain.from_iterable(
(field.name, field.attname) if hasattr(field, 'attname') else (field.name,)
for field in MyModel._meta.get_fields()
# For complete backwards compatibility, you may want to exclude
# GenericForeignKey from the results.
if not (field.many_to_one and field.related_model is None)
)))
补充一下,我正在使用 self 对象,这对我有用:
[f.name for f in self.model._meta.get_fields()]
至少对于 Django 1.9.9——我目前使用的版本——,请注意 .get_fields()
实际上也将任何外部模型“考虑”为一个字段,这可能是有问题的。假设你有:
class Parent(models.Model):
id = UUIDField(primary_key=True)
class Child(models.Model):
parent = models.ForeignKey(Parent)
它遵循
>>> map(lambda field:field.name, Parent._model._meta.get_fields())
['id', 'child']
同时,如@Rockallite 所示
>>> map(lambda field:field.name, Parent._model._meta.local_fields)
['id']
所以在我找到这篇文章之前,我成功地找到了这个工作。
Model._meta.fields
它的工作原理与
Model._meta.get_fields()
我不确定结果有什么不同,如果有的话。我运行了这个循环并得到了相同的输出。
for field in Model._meta.fields:
print(field.name)
其他人未提及的细节:
[f.name for f in MyModel._meta.get_fields()]
得到,例如
['id', 'name', 'occupation']
和
[f.get_attname() for f in MyModel._meta.get_fields()]
得到
['id', 'name', 'occupation_id']
如果
reg = MyModel.objects.first()
然后
reg.occupation
得到,例如
<Occupation: Dev>
和
reg.occupation_id
得到
1
有时我们也需要 db 列:
def get_db_field_names(instance):
your_fields = instance._meta.local_fields
db_field_names=[f.name+'_id' if f.related_model is not None else f.name for f in your_fields]
model_field_names = [f.name for f in your_fields]
return db_field_names,model_field_names
调用方法获取字段:
db_field_names,model_field_names=get_db_field_names(Mymodel)
结合给定线程的多个答案(谢谢!)并提出以下通用解决方案:
class ReadOnlyBaseModelAdmin(ModelAdmin):
def has_add_permission(self, request):
return request.user.is_superuser
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
def get_readonly_fields(self, request, obj=None):
return [f.name for f in self.model._meta.get_fields()]
为什么不直接使用它:
manage.py inspectdb
示例输出:
class GuardianUserobjectpermission(models.Model):
id = models.IntegerField(primary_key=True) # AutoField?
object_pk = models.CharField(max_length=255)
content_type = models.ForeignKey(DjangoContentType, models.DO_NOTHING)
permission = models.ForeignKey(AuthPermission, models.DO_NOTHING)
user = models.ForeignKey(CustomUsers, models.DO_NOTHING)
class Meta:
managed = False
db_table = 'guardian_userobjectpermission'
unique_together = (('user', 'permission', 'object_pk'),)
model._meta.fields
中可用,并且它们的名称似乎可以通过field.name
检索。我只是希望这是检索此信息的最稳定方法:)django.db.models.Model
上的实际公共方法调用,那就太酷了。我会深入研究,看看我能找到什么_meta
属性来做是唯一的方法...另外查看 ManyToMany 字段的_meta.many_to_many
!