获取模型字段列表?

时间:2022-06-01 11:47:50

I've defined a User class which (ultimately) inherits from models.Model. I want to get a list of all the fields defined for this model. For example, phone_number = CharField(max_length=20). Basically, I want to retrieve anything that inherits from the Field class.

我定义了一个User类,它(最终)继承自models.Model。我想要得到为这个模型定义的所有字段的列表。例如,phone_number = CharField(max_length=20)。基本上,我想检索从Field类继承的任何东西。

I thought I'd be able to retrieve these by taking advantage of inspect.getmembers(model), but the list it returns doesn't contain any of these fields. It looks like Django has already gotten a hold of the class and added all its magic attributes and stripped out what's actually been defined. So... how can I get these fields? They probably have a function for retrieving them for their own internal purposes?

我认为我可以利用inspection .getmembers(model)来检索这些字段,但是它返回的列表中没有任何字段。看起来Django已经获得了类的控制权,并添加了它所有的神奇属性,并删除了实际定义的内容。所以…如何得到这些字段?它们可能有一个函数来检索它们以供自己的内部用途?

9 个解决方案

#1


224  

For Django versions 1.8 and later:

Django版本1.8及以后:

The get_all_field_names() method is deprecated starting from Django 1.8 and will be removed in 1.10.

Django get_all_field_names()方法从已被弃用1.8和1.10将被删除。

The documentation page linked above provides a fully backwards-compatible implementation of get_all_field_names(), but for most purposes [f.name for f in MyModel._meta.get_fields()] should work just fine.

上面链接的文档页面提供了一个完全向后兼容的get_all_field_names()的实现,但是在大多数情况下(MyModel._meta.get_fields()中f的名称)应该可以正常工作。

For Django versions before 1.8:

对于Django版本,在1.8之前:

model._meta.get_all_field_names()

That should do the trick.

这就够了。

That requires an actual model instance. If all you have is a subclass of django.db.models.Model, then you should call myproject.myapp.models.MyModel._meta.get_all_field_names()

这需要一个实际的模型实例。如果您只有一个django.db.models的子类。然后应该调用myproject. app. Model. mymodel ._meta.get_all_field_names()

#2


51  

The get_all_related_fields() method mentioned herein has been deprecated in 1.8. From now on it's get_fields().

这里提到的get_all_related_fields()方法在1.8中被弃用。从现在开始,它是get_fields()。

>> from django.contrib.auth.models import User
>> User._meta.get_fields()

#3


47  

I find adding this to django models quite helpful:

我发现django添加这个模型非常有用:

def __iter__(self):
    for field_name in self._meta.get_all_field_names():
        value = getattr(self, field_name, None)
        yield (field_name, value)

This lets you do:

这可以让你:

for field, val in object:
    print field, val

#4


6  

This does the trick. I only test it in Django 1.7.

这就可以了。我只在Django 1.7测试它。

your_fields = YourModel._meta.local_fields
your_field_names = [f.name for f in your_fields]

Model._meta.local_fields does not contain many-to-many fields. You should get them using Model._meta.local_many_to_many.

Model._meta。local_fields不包含多对多领域。你应该让他们使用Model._meta.local_many_to_many。

#5


5  

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)

This worked for me in django==1.11.8

这在django==1.11.8中为我工作。

#6


4  

MyModel._meta.get_all_field_names() was deprecated several versions back and removed in Django 1.10.

MyModel._meta.get_all_field_names()是弃用几个版本,在Django 1.10删除。

Here's the backwards-compatible suggestion 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)
)))

#7


2  

It is not clear whether you have an instance of the class or the class itself and trying to retrieve the fields, but either way, consider the following code

不清楚您是否有类的实例或类本身并试图检索字段,但无论哪种方式,请考虑以下代码

Using an instance

使用一个实例

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

Using a class

使用一个类

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'

#8


1  

Just to add, I am using self object, this worked for me:

补充一下,我用的是self object,这对我有用:

[f.name for f in self.model._meta.get_fields()]

#9


1  

At least with Django 1.9.9 -- the version I'm currently using --, note that .get_fields() actually also "considers" any foreign model as a field, which may be problematic. Say you have:

至少在Django 1.9.9——我目前使用的版本,请注意,.get_fields()也认为“任何外国模型作为一个领域,这可能是有问题的。你有说:

class Parent(models.Model):
    id = UUIDField(primary_key=True)

class Child(models.Model):
    parent = models.ForeignKey(Parent)

It follows that

由此可见,

>>> map(lambda field:field.name, Parent._model._meta.get_fields())
['id', 'child']

while, as shown by @Rockallite

同时,通过@Rockallite如图所示

>>> map(lambda field:field.name, Parent._model._meta.local_fields)
['id']

#1


224  

For Django versions 1.8 and later:

Django版本1.8及以后:

The get_all_field_names() method is deprecated starting from Django 1.8 and will be removed in 1.10.

Django get_all_field_names()方法从已被弃用1.8和1.10将被删除。

The documentation page linked above provides a fully backwards-compatible implementation of get_all_field_names(), but for most purposes [f.name for f in MyModel._meta.get_fields()] should work just fine.

上面链接的文档页面提供了一个完全向后兼容的get_all_field_names()的实现,但是在大多数情况下(MyModel._meta.get_fields()中f的名称)应该可以正常工作。

For Django versions before 1.8:

对于Django版本,在1.8之前:

model._meta.get_all_field_names()

That should do the trick.

这就够了。

That requires an actual model instance. If all you have is a subclass of django.db.models.Model, then you should call myproject.myapp.models.MyModel._meta.get_all_field_names()

这需要一个实际的模型实例。如果您只有一个django.db.models的子类。然后应该调用myproject. app. Model. mymodel ._meta.get_all_field_names()

#2


51  

The get_all_related_fields() method mentioned herein has been deprecated in 1.8. From now on it's get_fields().

这里提到的get_all_related_fields()方法在1.8中被弃用。从现在开始,它是get_fields()。

>> from django.contrib.auth.models import User
>> User._meta.get_fields()

#3


47  

I find adding this to django models quite helpful:

我发现django添加这个模型非常有用:

def __iter__(self):
    for field_name in self._meta.get_all_field_names():
        value = getattr(self, field_name, None)
        yield (field_name, value)

This lets you do:

这可以让你:

for field, val in object:
    print field, val

#4


6  

This does the trick. I only test it in Django 1.7.

这就可以了。我只在Django 1.7测试它。

your_fields = YourModel._meta.local_fields
your_field_names = [f.name for f in your_fields]

Model._meta.local_fields does not contain many-to-many fields. You should get them using Model._meta.local_many_to_many.

Model._meta。local_fields不包含多对多领域。你应该让他们使用Model._meta.local_many_to_many。

#5


5  

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)

This worked for me in django==1.11.8

这在django==1.11.8中为我工作。

#6


4  

MyModel._meta.get_all_field_names() was deprecated several versions back and removed in Django 1.10.

MyModel._meta.get_all_field_names()是弃用几个版本,在Django 1.10删除。

Here's the backwards-compatible suggestion 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)
)))

#7


2  

It is not clear whether you have an instance of the class or the class itself and trying to retrieve the fields, but either way, consider the following code

不清楚您是否有类的实例或类本身并试图检索字段,但无论哪种方式,请考虑以下代码

Using an instance

使用一个实例

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

Using a class

使用一个类

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'

#8


1  

Just to add, I am using self object, this worked for me:

补充一下,我用的是self object,这对我有用:

[f.name for f in self.model._meta.get_fields()]

#9


1  

At least with Django 1.9.9 -- the version I'm currently using --, note that .get_fields() actually also "considers" any foreign model as a field, which may be problematic. Say you have:

至少在Django 1.9.9——我目前使用的版本,请注意,.get_fields()也认为“任何外国模型作为一个领域,这可能是有问题的。你有说:

class Parent(models.Model):
    id = UUIDField(primary_key=True)

class Child(models.Model):
    parent = models.ForeignKey(Parent)

It follows that

由此可见,

>>> map(lambda field:field.name, Parent._model._meta.get_fields())
['id', 'child']

while, as shown by @Rockallite

同时,通过@Rockallite如图所示

>>> map(lambda field:field.name, Parent._model._meta.local_fields)
['id']