2017-11-22 9 views
0

에서 새 쿼리하지 않고 모든 레코드를 위젯에 데이터를 얻기 나는 2 개 모델 제품과 카테고리가 - 카테고리데이터베이스

class Category(models.Model): 
    parent = models.ForeignKey('self', blank=True, null=True, verbose_name='parent category', on_delete=models.CASCADE) 

class Product(models.Model): 
    categories = models.ManyToManyField(Category) 
    name = models.CharField(max_length=255) 

및 제품 작성 양식 ManyToMany 관계 제품 카테고리와 자체 외래 키를 :

class ProductModelForm(ModelForm): 

     class Meta: 
      model = Product 
      fields = ['categories', 'name', 'short_description', 'description'] 
      widgets = { 
       'categories': MyWidget, 
      } 

기본적으로 ManyToMany는 ModelMultipleChoiceField가되고 SelectMultiple 위젯에 해당합니다.

SelectMultiple을 상속 한 새로운 위젯을 만들고 있습니다.

내 문제는 기본적으로 모든 위젯에서 Django는 모델에서 def __str__ 내에 정의 된 값만 레코드에서 전송한다는 것입니다. 선택의 경우 pk.

(None, [{'name': 'categories', 'value': 7, 'label': 'Category 2', 'selected': True, 'index': '1', 'attrs': {'selected': True}, 'type': 'select', 'template_name': 'django/forms/widgets/select_option.html'}] 

위젯에는 부모 값과 같은 기타 정보가 있어야합니다.

물론 다른 쿼리를 만들고 데이터베이스에서 데이터를 가져올 수는 있지만 이는 내가 수행 한 쿼리와 장고가 수행 한 쿼리가 각각 2 개씩 있다는 것을 의미합니다.

Django가 __str__에 정의 된 것 대신 위젯에 모든 레코드 데이터를 보내도록하는 방법이 있습니까?

변경 __str__은 다른 장소와 관리자에서도 사용되기 때문에 옵션이 아닙니다. 아주 쉬운 일이 아닙니다

답변

1

하십시오 ModelChoiceField (및 ModelMultipleChoiceField)가 디폴트로하는 queryset 매개 변수를 모델의 default_manager (Category.objects.all()). 위젯 용 choicesModelChoiceIterator을 사용하여 생성되면 쿼리 세트가 소비됩니다. 실제로는 쿼리 세트의 각 객체에 대해 객체의 idlabel의 2 튜플을 반환합니다.

데이터베이스에 쿼리가 하나만 있는지 확인하려면 ModelMultipleChoiceField의 서브 클래스를 사용하여 ModelChoiceIterator의 하위 클래스를 사용하여 필요한 매개 변수로 3 튜플 (또는 그 이상)을 반환해야합니다. 그런 다음 __init__() 메서드를 하위 클래스 ChoiceWidget (귀하의 경우 SelectMultiple)으로 두 튜플을 다시 두 튜플로 분할하여 self.choices에 할당하고 다른 값을 위젯 속성 (self.attrs)으로 설정하여 사용자가 사용할 수 있도록하십시오. 주형.

특히 캐싱 메커니즘을 잘 사용하면 Category.objects.all() 번을 두 번 수행하면 실제로 캐스팅되지 않을 것입니다.

+0

ModelMultipleChoiceField를 서브 클래 싱하는 것에 대해 생각했지만 ManytoMany (fields_for_model mehod 사용)가 "코어"또는 다른 부분에 영향을주지 않고 기본 필드를 변경하기 위해 덮어 쓸 수있는 방법을 모르는 경우 "호출"됩니다. – user3541631

+0

글쎄, 양식에서 사용할 양식 필드를 재정의 (https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/#overriding-the-default-fields) 할 수 있습니다. 그냥 추가하십시오. 폼의 맨 위에있는'categories = MyOwnModelMultipleChoiceField (queryset = Category.objects.all())'. – dirkgroten

+0

하지만 다시 한 번 정직하게 말하면, 장고의 내부 동작을 이해하는 것은 좋은 운동이지만, 나는 이렇게하지 않을 것이다 :-) 좋은 캐싱을 추가하면 이것에 대해 걱정할 필요가 없다. – dirkgroten