Django : 모델 필드 목록을 얻습니까?


196

에서 User(궁극적으로) 상속 하는 클래스를 정의했습니다 models.Model. 이 모델에 대해 정의 된 모든 필드 목록을 얻고 싶습니다. 예를 들면 다음과 같습니다 phone_number = CharField(max_length=20). 기본적으로 Field클래스 에서 상속되는 것을 검색하려고합니다 .

을 활용하여 검색 할 수 있다고 생각 inspect.getmembers(model)했지만 반환되는 목록에 이러한 필드가 포함되어 있지 않습니다. Django는 이미 클래스를 보유하고 있으며 모든 마법 속성을 추가하고 실제로 정의 된 것을 제거했습니다. 그렇다면 ...이 필드를 어떻게 얻을 수 있습니까? 그들은 아마도 자신의 내부 목적을 위해 그것들을 검색하는 기능을 가지고 있습니까?


도움이 될 수도 있습니다. pypi.python.org/pypi/django-inspect-model/0.5
Paolo

답변:


46

대부분의 답변이 구식 이므로 Django 2.2 에서 업데이트하려고합니다. 여기 게시물-앱 (게시물, 블로그, 상점 등)

1) 모델 링크에서 : https://docs.djangoproject.com/en/2.2/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 Organisation._meta.fields]
    parent_fields = BlogPost.get_deferred_fields(BlogPost)

    list_display = all_fields
    read_only = parent_fields

1
이것이 올바른 것으로 가정하고 새로운 답변으로 받아들입니다. 업데이트 해 주셔서 감사합니다!
mpen

@mpen은 그것을 가장 좋은 방법 또는 가장 파이썬으로 주장하지는 않지만 아래에서 u는보기에 표시하려는 값을 가져와야하므로 HTML 테이블의 헤더는 u입니다. get_fields ()는 튜플을 반환하므로 u를 반복하여 appname.Model.field_name과 같은 값을 얻을 수 있습니다. 아래에서 두 번째 점의 값을 정리하고 필드 이름에 밑줄이 사용 된 경우를 포함합니다. 제목을 지정해야하므로 고유 한 상황마다 필요에 따라 수정하십시오. clean_field_names = [str(h).split('.')[2].replace("_", " ").title() for h in all_fields]
Alejandro Suarez

1
인스턴스 예는 다음과 같아야합니다.all_fields = bp._meta.fields
George Kettleborough

@GeorgeKettleborough 요점을 봅니다. 수업에서 직접 작동하지 않습니까? 테스트 할 예제가 없습니다. 어쨌든 예제는 인스턴스에 관한 것이므로 bp 이상이어야합니다 .__ class__
Maks

294

Django 버전 1.8 이상 :

사용해야합니다 get_fields():

[f.name for f in MyModel._meta.get_fields()]

get_all_field_names()방법은 Django 1.8부터 더 이상 사용되지 않으며 1.10에서 제거됩니다 .

위에 링크 된 문서 페이지는 이전 버전과 완벽하게 호환되는 구현을 제공 get_all_field_names()하지만 대부분의 경우 이전 예제는 제대로 작동합니다.


1.8 이전의 장고 버전 :

model._meta.get_all_field_names()

그 트릭을해야합니다.

실제 모델 인스턴스가 필요합니다. 당신이 가진 모든 것이의 서브 클래스 django.db.models.Model라면,myproject.myapp.models.MyModel._meta.get_all_field_names()


11
이름뿐만 아니라 객체도 원했습니다. 이것은 가능 model._meta.fields하지만 그들의 이름은 field.name그것 으로 검색 할 수있는 것 같습니다. 나는
이것이이

2
완전히 확실하지 않습니다. 밑줄은 내부 API임을 나타냅니다 .Django 사람들이 이것을 실제로 공개 메소드 호출로 홍보하면 멋질 것입니다 django.db.models.Model. 나는 그것을 파고 내가 무엇을 찾을 수 있는지 볼 것이다
rossipedia

2
나는 _meta속성을 통해 그것을하는 것이 유일한 방법이라고 생각합니다 ... 또한 _meta.many_to_manyManyToMany 필드를 살펴보십시오 !
Bernhard Vallant 2018 년

3
좋은 솔루션이지만이 방법에는 역방향 ForeignKey와 같은 역방향 관계 필드가 포함되며 정확하게 "필드"가 아닙니다. 실제 필드를 구별하는 방법을 아는 사람이 있습니까?
viridis

2
@rossipedia : ._meta API가 공개적이라는 사실에 주목 (이 답변이 처음 작성되었을 때 비공개로 사용 되었음
Nick S


55

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

2
ForeignKey는 어떻습니까? 이와 같은 오류가 있습니다django.db.models.fields.related.RelatedObjectDoesNotExist: CustomModel has no custom_attribute.
SAKrisT

ForeignKey나를 위해 잘 작동합니다. 그러나 모든 예외를 조용히 잡는 것은 반 패턴입니다. 잡는 것이 훨씬 낫 AttributeError거나 적어도 일부 예외가 자동으로 삼킨 것을 기록하십시오.
Sardathrion-남용에 대한

1
self._meta.get_all_field_names()감가 상각되고 제거되었습니다. for field in self._meta.get_fields()다음 과 같은 것을 사용할 수 있습니다yield (field.name, field.value_from_object(self))
MackM

13

이것은 트릭을 수행합니다. 장고 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.


10

클래스 또는 클래스 자체의 인스턴스가 있고 필드를 검색하려고하는지 확실하지 않지만 다음 방법을 고려하십시오.

인스턴스 사용

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'

10
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


8

MyModel._meta.get_all_field_names()Django 1.10 에서는 여러 버전 이 더 이상 사용되지 않고 제거 되었습니다.

다음 은 문서에서 이전 버전과 호환되는 제안 입니다 .

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)
)))

6

추가하기 위해, 나는 self object를 사용하고 있습니다.

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

5

적어도 현재 사용중인 버전 인 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']

4

따라서이 게시물을 찾기 전에이 작업이 성공적으로 완료되었습니다.

Model._meta.fields

그것은 동일하게 작동합니다

Model._meta.get_fields()

결과에 차이가 무엇인지 확실하지 않습니다. 이 루프를 실행하고 동일한 출력을 얻었습니다.

for field in Model._meta.fields:
    print(field.name)

-2

왜 그것을 사용하지 않습니까?

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'),)

1
이것은 질문에 대한 답변이 아닙니다.
Shayne
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.