Django에서 모델 필드 가져 오기


121

Django 모델이 주어지면 모든 필드를 나열하려고합니다. _meta 모델 속성을 사용하여이 작업을 수행하는 몇 가지 예를 보았지만 메타 앞의 밑줄이 _meta 속성이 개인 속성이고 직접 액세스해서는 안된다는 것을 나타내지 않습니까? ... 예를 들어 _meta의 레이아웃이 향후 변경 될 수 있고 안정적인 API가 아니기 때문입니까?

_meta는이 규칙의 예외입니까? 안정적이고 사용할 준비가 되었습니까? 아니면 액세스하는 것이 나쁜 습관으로 간주됩니까? 아니면 _meta 속성을 사용하지 않고 모델의 필드를 검사하는 함수 나 다른 방법이 있습니까? 아래는 _meta 속성을 사용하여이를 수행하는 방법을 보여주는 일부 링크 목록입니다.

어떤 조언이라도 대단히 감사합니다.

장고 객체 가져 오기 / 설정 필드

http://www.djangofoo.com/80/get-list-model-fields

장고 모델 필드를 조사하는 방법은 무엇입니까?


답변:


144

_meta비공개이지만 비교적 안정적입니다. 이를 공식화하고 문서화하고 밑줄을 제거하려는 노력이 있습니다. 1.3 또는 1.4 이전에 발생할 수 있습니다. 어쨌든 많은 사람들이 사용하고 있기 때문에 이전 버전과의 호환성을 보장하기 위해 노력할 것이라고 생각합니다.

특히 호환성이 걱정된다면 모델을 가져와 필드를 반환하는 함수를 작성하세요. 즉, 미래에 무언가 변경 될 경우 하나의 기능 만 변경하면됩니다.

def get_model_fields(model):
    return model._meta.fields

나는 이것이 Field객체 목록을 반환한다고 믿습니다 . 인스턴스에서 각 필드의 값을 가져 오려면 getattr(instance, field.name).

업데이트 : Django 기여자들은 Google Summer of Code의 일부로 _Meta 객체를 대체하는 API를 개발하고 있습니다. 참조 : -https : //groups.google.com/forum/#!topic / django
- developers
/ hD4roZq0wyk - https : //code.djangoproject.com/wiki/new_meta_api


45
또한 다 대다 필드가 필요한 경우 액세스해야한다는 사실을 알고 있어야합니다 model._meta.many_to_many.
Bernhard Vallant

1
감사합니다. 다른 사람들도 _meta를 사용하고 있다는 것을 알게되어 기쁩니다. 나는 래퍼 기능이 있다는 생각을 좋아합니다. Lazerscience, 감사합니다. many_to_many 필드를 가져 오는 좋은 방법이 있다는 것을 알아두면 좋습니다. Joe
Joe J

3
django/core/management/commands/loaddata.py_meta를 사용하여 앱, 모델 및 필드 트리를 살펴 봅니다. 따라야 할 좋은 패턴 ... 그리고 당신은 그것이 "공식적인 방법"이라고 확신 할 수 있습니다.
hobs

2
일반 외래 키를 사용하는 경우 확인해야합니다_meta.virtual_fields
andrei1089 2013 년

7
_meta이제 공식적인 지원 API (Django 1.8의 새로운 기능)
mgalgs

97

이 게시물은 꽤 오래 알고 있지만 난 그냥이 할 수있는 공공 및 공식 API가 그 같은 일을 찾고있는 누군가에게 걱정 : get_fields()get_field()

용법:

fields = model._meta.get_fields()
my_field = model._meta.get_field('my_field')

https://docs.djangoproject.com/en/1.8/ref/models/meta/


6
이것은 실제로 최신 버전의 django에 대한 정답입니다.
chhantyal 2015


3
한 가지 질문 : 이것이 "공개적이고 공식적인"경우, 왜 여전히 아래에 _meta있습니까?
krubo

9

이제 특별한 메소드가 있습니다 -get_fields ()

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

리턴되는 필드를 제어하는 ​​데 사용할 수있는 두 개의 매개 변수를 허용합니다.

  • include_parents

    기본적으로 True입니다. 부모 클래스에 정의 된 필드를 재귀 적으로 포함합니다. False로 설정하면 get_fields ()는 현재 모델에서 직접 선언 된 필드 만 검색합니다. 추상 모델 또는 프록시 클래스에서 직접 상속하는 모델의 필드는 부모가 아닌 로컬로 간주됩니다.

  • include_hidden

    기본적으로 False입니다. True로 설정하면 get_fields ()는 다른 필드의 기능을 지원하는 데 사용되는 필드를 포함합니다. 여기에는 "+"로 시작하는 related_name (예 : ManyToManyField 또는 ForeignKey)이있는 모든 필드도 포함됩니다.


9

get_fields()를 반환 tuple하고 각 요소는 Model field유형이며 문자열로 직접 사용할 수 없습니다. 따라서 field.name필드 이름을 반환합니다.

my_model_fields = [field.name for field in MyModel._meta.get_fields()]
위의 코드는 모든 필드의 이름을 conatining 목록을 반환합니다

예를

In [11]: from django.contrib.auth.models import User

In [12]: User._meta.get_fields()
Out[12]: 
(<ManyToOneRel: admin.logentry>,
 <django.db.models.fields.AutoField: id>,
 <django.db.models.fields.CharField: password>,
 <django.db.models.fields.DateTimeField: last_login>,
 <django.db.models.fields.BooleanField: is_superuser>,
 <django.db.models.fields.CharField: username>,
 <django.db.models.fields.CharField: first_name>,
 <django.db.models.fields.CharField: last_name>,
 <django.db.models.fields.EmailField: email>,
 <django.db.models.fields.BooleanField: is_staff>,
 <django.db.models.fields.BooleanField: is_active>,
 <django.db.models.fields.DateTimeField: date_joined>,
 <django.db.models.fields.related.ManyToManyField: groups>,
 <django.db.models.fields.related.ManyToManyField: user_permissions>)

In [13]: [field.name for field in User._meta.get_fields()]
Out[13]: 
['logentry',
 'id',
 'password',
 'last_login',
 'is_superuser',
 'username',
 'first_name',
 'last_name',
 'email',
 'is_staff',
 'is_active',
 'date_joined',
 'groups',
 'user_permissions']

좋은 대답입니다! 감사!
Tms91

8

이것은 모델에서 폼을 만들 때 Django 자체가 수행하는 작업입니다. _meta 속성을 사용하고 있지만 Bernhard가 언급했듯이 _meta.fields와 _meta.many_to_many를 모두 사용합니다. django.forms.models.fields_for_model을 살펴보면 다음과 같이 할 수 있습니다.

opts = model._meta
for f in sorted(opts.fields + opts.many_to_many):
    print '%s: %s' % (f.name, f)

4

_meta에 포함 된 모델 필드는 각 필드 개체의 목록으로 여러 위치에 나열됩니다. 키가 필드 이름 인 사전으로 작업하는 것이 더 쉬울 수 있습니다.

제 생각에 이것은 모델 필드 객체를 수집하고 구성하는 가장 불필요하고 표현적인 방법입니다.

def get_model_fields(model):
  fields = {}
  options = model._meta
  for field in sorted(options.concrete_fields + options.many_to_many + options.virtual_fields):
    fields[field.name] = field
  return fields

( django.forms.models.fields_for_model 의이 예제 사용법 을 참조하십시오 .)


2
코드가 수행하는 작업에 대한 간략한 설명과 함께 코드를 첨부 할 수 있습니다.
Bas van Dijk

2

이건 어때.

fields = Model._meta.fields

1
필드의 속성에 액세스하고 싶을 수도 있습니다. 또한 이전 답변에서 지적했듯이 many_to_manyvirtual_fields.
Jocke 2016-09-05

@Jocke 맞아요. 다른 속성에 액세스해야 할 수도 있습니다. 답변이 수정되었습니다.
JDE876

2

장고 문서 2.2에 따라 다음을 사용할 수 있습니다.

모든 필드를 가져 오려면 : Model._meta.get_fields()

개별 필드를 얻으려면 : Model._meta.get_field('field name')

전의. Session._meta.get_field('expire_date')


1

관리 사이트에 필요한 경우 of field name 을 반환하는 ModelAdmin.get_fields메서드 ( docs ) 도 있습니다 .liststrings

예를 들면 :

class MyModelAdmin(admin.ModelAdmin):
    # extending change_view, just as an example
    def change_view(self, request, object_id=None, form_url='', extra_context=None):
        # get the model field names
        field_names = self.get_fields(request)
        # use the field names
        ...

0

또 다른 방법은 모델에 함수를 추가하고 날짜를 재정의하려면 함수를 호출 할 수 있습니다.

class MyModel(models.Model):
    name = models.CharField(max_length=256)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    def set_created_date(self, created_date):
        field = self._meta.get_field('created')
        field.auto_now_add = False
        self.created = created_date

    def set_modified_date(self, modified_date):
        field = self._meta.get_field('modified')
        field.auto_now = False
        self.modified = modified_date

my_model = MyModel(name='test')
my_model.set_modified_date(new_date)
my_model.set_created_date(new_date)
my_model.save()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.