관련된 모든 Django 모델 개체 가져 오기


88

개체를 가리키는 ForeignKey가있는 모든 모델 개체의 목록을 얻으려면 어떻게해야합니까? (DELETE CASCADE 전에 Django 관리자의 삭제 확인 페이지와 같은 것).

나는 데이터베이스에서 중복 객체를 병합하는 일반적인 방법을 생각해 내고 있습니다. 기본적으로 객체 "B"에 대한 ForeignKeys 포인트가있는 모든 객체가 "A"객체를 가리 키도록 업데이트되어 중요한 항목을 잃지 않고 "B"를 삭제할 수 있습니다.

당신의 도움을 주셔서 감사합니다!


1
Django 스 니펫 은 확실히 확인할 가치가 있습니다!
Nick Merrill 2014

나는 똑같은 것을 직접 구현하려고 노력하고 있습니다. 솔루션을 공유 하시겠습니까? set특히 관련 개체가 A를 가리키는 방법은 무엇입니까?
유진 2015-12-20

답변:


84

장고 <= 1.7

이렇게하면 모든 관련 개체의 속성 이름이 제공됩니다.

links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]

그런 다음 다음과 같이 모든 관련 개체를 가져올 수 있습니다.

for link in links:
    objects = getattr(a, link).all()
    for object in objects:
        # do something with related object instance

내 모델 중 하나에 일종의 "관찰자 패턴"을 구현할 수 있도록이 문제를 파악하는 데 시간을 보냈습니다. 도움이 되었기를 바랍니다.

Django 1.8 이상

사용 _meta.get_fields(): https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields ( _get_fields()또한 소스의 반대 참조 )


7
all()부분은 실패합니다 OneToOneField. 어떻게 든 감지해야합니다.
augustomen

2
ManyToMany 연결을 표시하지 않으며 더 이상 사용되지 않습니다. 그것이로 대체하는 것이 좋습니다 1.8 이상 장고 _meta.get_fields(): docs.djangoproject.com/en/1.10/ref/models/meta/... (참조 reverse_get_fields()또한 소스)
int_ua

1
@int_ua 편집 해 주셔서 감사합니다! 이 해결 방법이 Django와 호환되는 한 계속해서 유지된다는 것에 놀랐습니다.
강도는 17:53 :

4
_meta.get_fields()팁 에 따라 , 이것은 저에게 해결책의 일부였습니다. links = [field.get_accessor_name() for field in obj._meta.get_fields() if issubclass(type(field), ForeignObjectRel)](주어진 from django.db.models.fields.related import ForeignObjectRel)
driftcatcher

20

@digitalPBK가 가까웠습니다 ... 여기에 Django 관리자에서 삭제하는 동안 관련 개체를 표시하는 데 사용되는 Django의 내장 항목을 사용하여 찾고있는 항목이 있습니다.

from django.contrib.admin.utils import NestedObjects
collector = NestedObjects(using="default") #database name
collector.collect([objective]) #list of objects. single one won't do
print(collector.data)

이를 통해 Django 관리자가 표시하는 항목 (삭제할 관련 개체)을 만들 수 있습니다.


FWICT 이것은 제대로 작동하지 않습니다. 삭제 기준을 의미하지 않는 관계를 따르는 것으로 보이지만 이유는 모르겠습니다.
Catskul 2015 년

1
나입니까, 아니면 Collector(1 행에서 가져온) 사용하지 않습니까?
djvg

7

이것을 시도하십시오.

class A(models.Model):
    def get_foreign_fields(self):
      return [getattr(self, f.name) for f in self._meta.fields if type(f) == models.fields.related.ForeignKey]

ManyToMany도 잊지 마세요
theannouncer

6

다음은 django가 모든 관련 객체를 가져 오는 데 사용하는 것입니다.

from django.db.models.deletion import Collector
collector = Collector(using="default")
collector.collect([a])

print collector.data

1
계단식으로 보이지 않습니다. 전체 차이점을 알기 위해이 특정 부분에 대한 충분한 테스트를 수행하지 않았지만 계단식에 대한 내 대답을 참조하십시오.
IMFletcher

6

links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]

그런 다음 다음과 같이 모든 관련 개체를 가져올 수 있습니다.

for link in links:
    objects = getattr(a, link.name).all()
    for object in objects:
        # do something with related object instance

Django 1.10 공식 문서에서 :

MyModel._meta.get_all_related_objects ()는 다음과 같이됩니다.

[
    f for f in MyModel._meta.get_fields()
    if (f.one_to_many or f.one_to_one)
    and f.auto_created and not f.concrete
]

따라서 승인 된 예를 사용하여 다음을 사용합니다.

links = [
            f for f in MyModel._meta.get_fields()
            if (f.one_to_many or f.one_to_one)
            and f.auto_created and not f.concrete
        ]

for link in links:
    objects = getattr(a, link.name).all()
    for object in objects:
        # do something with related object instance

다만 당신의 대답은 조금 수정합니다 python for link in links: objects = getattr(a, link.name).all() for object in objects:
남 Ngo의

5
for link in links:
    objects = getattr(a, link).all()

관련 세트에 대해 작동하지만 ForeignKey에는 작동하지 않습니다. RelatedManager는 동적으로 생성되므로 isinstance ()를 수행하는 것보다 클래스 이름을 보는 것이 더 쉽습니다.

objOrMgr = getattr(a, link)
 if objOrMgr.__class__.__name__ ==  'RelatedManager':
      objects = objOrMgr.all()
 else:
      objects = [ objOrMgr ]
 for object in objects:
      # Do Stuff

4

Django 1.9
get_all_related_objects ()는 더 이상 사용되지 않습니다.

#Example: 
user = User.objects.get(id=1)
print(user._meta.get_fields())

참고 : RemovedInDjango110Warning : 'get_all_related_objects는 더 이상 사용되지 않는 비공식 API입니다. 'get_fields ()'로 대체 할 수 있습니다.


get_fields는 관련 개체를 반환하지 않습니다.
iankit

Django 1.8에서도 역 연결을 반환합니다. docs.djangoproject.com/en/1.8/_modules/django/db/models/options/…
int_ua

2

다음은 관련 모델의 필드 목록 (이름 만)을 가져 오는 또 다른 방법입니다.

def get_related_model_fields(model):
    fields=[]
    related_models = model._meta.get_all_related_objects()
    for r in related_models:
        fields.extend(r.opts.get_all_field_names())
    return fields

2

불행히도 user._meta.get_fields ()는 사용자가 접근 할 수있는 관계 만 반환하지만, related_name = '+'를 사용하는 관련 객체가있을 수 있습니다. 이 경우 user._meta.get_fields ()는 관계를 반환하지 않습니다. 따라서 개체를 병합하는 일반적이고 강력한 방법이 필요한 경우 위에서 언급 한 Collector를 사용하는 것이 좋습니다.

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