복붙노트

[PYTHON] 장고 프록시 모델과 ForeignKey

PYTHON

장고 프록시 모델과 ForeignKey

entry.category를 CategoryProxy의 인스턴스로 만드는 방법은 무엇입니까? 자세한 내용은 코드를 참조하십시오.

class Category(models.Model): pass

class Entry(models.Model):
    category = models.ForeignKey(Category)

class EntryProxy(Entry):
    class Meta:
        proxy = True

class CategoryProxy(Category):
    class Meta:
        proxy = True

entry = EntryProxy.objects.get(pk=1)
entry.category # !!! I want CategoryProxy instance here

Category에서 CategoryProxy로 캐스팅해도 괜찮지 만 내부 상태를 제대로 복사하려면 ORM 내부에 익숙하지 않은 것입니다 ...

편집하다. 이유 : CategoryProxy에 메서드를 추가하고 그를 사용하고 싶습니다.

EntryProxy.objects.get(pk=1).category.method_at_category_proxy()

편집 2. 현재 다음과 같이 구현했습니다.

EntryProxy._meta.get_field_by_name('category')[0].rel.to = CategoryProxy

그러나 그것은 끔찍해 보입니다 ...

해결법

  1. ==============================

    1.데이터베이스를 치지 않고 모델 클래스에서 프록시 클래스로 전환하려면 다음을 수행하십시오.

    데이터베이스를 치지 않고 모델 클래스에서 프록시 클래스로 전환하려면 다음을 수행하십시오.

    class EntryProxy(Entry):
        @property
        def category(self):
            new_inst = EntryProxy()
            new_inst.__dict__ = super(EntryProxy, self).category.__dict__
            return new_inst
    

    편집 : 위의 미리보기 django 1.4 작동하지 않는 것.

    django 1.4부터는 다음과 같이 모든 값 필드를 수동으로 가져 왔습니다.

    class EntryProxy(Entry):
        @property
        def category(self):
            category = super(EntryProxy, self).category
            new_inst = EntryProxy()
            for attr in [f.attname for f in category.__class__._meta.fields] + ['_state']:
                setattr(new_inst, attr, getattr(category, attr))
            return new_inst
    

    데이터베이스를 치지 않고 쿼리 세트에서 하위 프록시 클래스로 전환하려면 다음을 수행하십시오.

    class CategoryProxy(Category):
        @property
        def entry_set(self):
            qs = super(CategoryProxy, self).entry_set
            qs.model = EntryProxy
            return qs
    
  2. ==============================

    2.이것은 장고 문제입니다 : # 10961 (사용자가 ForeignKey 필드를 사용하여 프록시 모델에서 정방향 및 역방향 관계를 무시할 수 있음)

    이것은 장고 문제입니다 : # 10961 (사용자가 ForeignKey 필드를 사용하여 프록시 모델에서 정방향 및 역방향 관계를 무시할 수 있음)

    프록시 모델을 정의한 후 문제의 필드를 재설정하여 문제를 해결할 수 있습니다.

    EntryProxy.add_to_class('category', CategoryProxy)
    
  3. ==============================

    3.이 질문에는 이미 대답이 있지만 검색 할 사람을 위해 게시하고 싶습니다.

    이 질문에는 이미 대답이 있지만 검색 할 사람을 위해 게시하고 싶습니다.

    관계가 예상대로 작동하도록 런타임시 새 필드로 모델을 패치 할 수 있습니다. 전체 예제는 여기에서 볼 수 있습니다 - https://gist.github.com/carymrobbins/8721082

    from django.db.models.fields.related import ReverseSingleRelatedObjectDescriptor
    
    def override_model_field(model, field, field_name, column_name):
        """Force override a field in a Django Model.
        Usage: override_model_field(
            MyModel, models.ForeignKey(OtherModel), 'other', 'other_id')
        :type model: django.db.models.base.ModelBase
        :type field: django.db.models.fields.Field
        :type field_name: basestring
        :type column_name: basestring
        """
        field.name = field_name
        field.attname = column_name
        for i, f in enumerate(model._meta.fields):
            if f.name == field_name:
                model._meta.fields[i] = field
                break
        else:
            raise TypeError('Model {!r} does not have a field {!r}.'
                            .format(model, field_name))
        model.add_to_class(field_name,
                           ReverseSingleRelatedObjectDescriptor(field))
    
  4. ==============================

    4.내 질문 중 하나에 대한 Joseph Spiros의 대답이 도움이 될 수 있습니다.

    내 질문 중 하나에 대한 Joseph Spiros의 대답이 도움이 될 수 있습니다.

    장고 상속 및 퍼머 링크

    프록시 모델로 어떻게 작동하는지 잘 모르겠습니다.

  5. ==============================

    5.해당 ID로 CategoryProxy를 찾는 EntryProxy의 속성 범주를 정의하십시오.

    해당 ID로 CategoryProxy를 찾는 EntryProxy의 속성 범주를 정의하십시오.

    class EntryProxy(Entry):
        @property
        def category(self):
            cid = super(EntryProxy, self).category.id
            return CategoryProxy.objects.get(id=cid)
    
        class Meta:
            proxy = True
    
  6. ==============================

    6.Bernd Petersohn의 답을 약간 수정하면 다음과 같이 나타납니다.

    Bernd Petersohn의 답을 약간 수정하면 다음과 같이 나타납니다.

    class EntryProxy(Entry):
        @property
        def category(self):
            return CategoryProxy.objects.get(id=self.category_id)
    

    이것은 데이터베이스와 함께 더 경제적이어야합니다. 개선 된 기능을 위해 처음 메서드가 호출 될 때 private 특성 (self._category)을 설정 한 다음 모든 후속 시간을 반환 할 수 있습니다.

  7. from https://stackoverflow.com/questions/3891880/django-proxy-model-and-foreignkey by cc-by-sa and MIT license