33

나는 다른 개체와 다 대다 관계가있는 개체가 있습니다.
Django 관리자에서는 다중 선택 상자에 매우 긴 목록이 표시됩니다.필터 ManyToMany 장고 ​​관리에서

ManyToMany 관계를 필터링하여 고객이 선택한 도시에서만 사용할 수있는 범주 만 가져옵니다.

이것이 가능합니까? 내가 위젯을 만들어야합니까? 그렇다면 - 표준 ManyToMany 필드의 비헤이비어를 어떻게 복사합니까? filter_horizontal 함수도 필요합니다.

이 내 단순화 된 모델입니다 :

class City(models.Model): 
    name = models.CharField(max_length=200) 


class Category(models.Model): 
    name = models.CharField(max_length=200) 
    available_in = models.ManyToManyField(City) 


class Customer(models.Model): 
    name = models.CharField(max_length=200) 
    city = models.ForeignKey(City) 
    categories = models.ManyToManyField(Category) 

답변

36

좋아,이 위의 클래스를 사용하여 내 솔루션입니다. 필터를 추가하기 위해 더 많은 필터를 추가했지만 여기서 코드를 읽을 수있게하려고했습니다.

은 내가 찾던 정확히 무엇이며, 나는 여기에 내 해결책을 발견 :

class CustomerForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(CustomerForm, self).__init__(*args, **kwargs) 
     wtf = Category.objects.filter(pk=self.instance.cat_id); 
     w = self.fields['categories'].widget 
     choices = [] 
     for choice in wtf: 
      choices.append((choice.id, choice.name)) 
     w.choices = choices 


class CustomerAdmin(admin.ModelAdmin): 
    list_per_page = 100 
    ordering = ['submit_date',] # didnt have this one in the example, sorry 
    search_fields = ['name', 'city',] 
    filter_horizontal = ('categories',) 
    form = CustomerForm 

이가 "카테고리를 필터링 : http://www.slideshare.net/lincolnloop/customizing-the-django-admin#stats-bottom

내 admin.py에 다음을 추가 (50 슬라이드) "기능을 제거하지 않고 목록! (예 : 나는 여전히 내 사랑하는 filter_horizontal을 가질 수 있습니다 :))

ModelForms는 매우 강력합니다. 나는 문서/책에서 더 많이 다루지 않는다고 놀랍습니다.

+0

프로젝트에이 코드를 추가 한 후 'Available categories'필드에서 옵션을 선택한 후에도 선택한 옵션 상자 (예제에서 선택한 "선택한 범주"아래에 있음)가 비어 있음을 확인했습니다. 이것을 구현하는 데 뭔가 빠졌나요? – Silfheed

+0

리스트 이해력을 사용하여 추가 감축 : self.fields [ 'categories'] .wwget.choices = [(선택 사항. 선택 사항, 이름)] –

+2

무엇이'cat_id'입니까? – Sevenearths

0
Category.objects.filter(available_in=cityobject) 

을해야한다. 보기에는 요청시 또는 해당보기 기능의 매개 변수로 사용자가 선택한 도시가 있어야합니다.

+0

하지만 메신저 장고 관리자에 대한 이야기, 당신은 내가 표준보기를 복제해야 위의 추가 말하고 있습니까? – schmilblick

+0

아, 나는 완전히 당신의 질문 제목의 "장고 관리자"부분을 놓쳤다. 나는 이것이 올바른 접근법이라고 여전히 생각한다. 비록 내가 어디에 넣을 지, 또는 심지어 가능할 지 모르지만. – AlbertoPL

1

동일한 양식으로 고객의 도시와 카테고리를 선택 했으므로 카테고리 선택기를 선택한 도시에서 사용할 수있는 범주로 동적으로 줄이기위한 javascript가 필요합니다.

+0

javascript를 사용하여 수십만 개의 DOM 요소를 반복하고 또 다른 거대한 목록과 비교하는 데 열중하고 싶지 않습니다. 나는 자바 스크립트가 definatly 갈 길이 아니라고 말하고 싶지만, 이것은 데이터베이스에서 카테고리를 선택할 때 백엔드 끝내야한다. – schmilblick

12

나는 당신을 이해할 수있는 한 기본적으로 도시에 따른 범주에 따라 몇 가지 기준에 따라 표시된 선택 사항을 필터링하려고합니다.

limit_choices_to 속성을 사용하여 정확하게 수행 할 수 있습니다. models.ManyToManyField입니다. 그래서 limit_choices_to로,

class Customer(models.Model): 
    name = models.CharField(max_length=200) 
    city = models.ForeignKey(City) 
    categories = models.ManyToManyField(Category, limit_choices_to = {'available_in': cityId}) 

이 작동합니다 ... 같은 모델의 정의를 변경, 바로이 목적을 위해 사용할 수 있습니다.

참고 사항 : limit_choices_to은 사용자 지정 중간 테이블이있는 ManyToManyField에서 사용될 때 아무런 영향을 미치지 않습니다. 희망이 도움이됩니다.

+0

작동하는 것처럼 보입니다! 그러나 ... 그것은 내 모델을 다시 모델링해야한다는 것을 깨닫게했습니다 :) 관리자가 limit_choices_to에 대해 신경 쓰지 않는 문서에서 임 독서는 무엇입니까? – schmilblick

+0

나는 똑같은 방식으로 @sim을 설명하지만, ValueError at/admin/foo/bar/: base 10 인 int()에 대한 리터럴이 잘못되었습니다 : 'city ''. 이 필터링 방법을 구현하는 방법과 관련하여 누락 된 것이 있습니까? – nhinkle

+0

@nhinkle 값의 '도시'는 범주를 제한하려는 도시 객체의 ID를 의미한다고 가정합니다. 내 사과. 나는 그 대답을 더 명확하게 편집 할 것이다. – simplyharsh

0

Ryan이 말했듯이 사용자가 선택한 것을 기반으로 옵션을 동적으로 변경하려면 자바 스크립트가 있어야합니다. 게시 된 솔루션은 도시가 저장되고 관리자 양식이 다시로드되는 경우 작동합니다. 필터가 작동하지만 사용자가 객체를 편집하고 도시 드롭 다운을 변경하지만 카테고리의 옵션을 새로 고치지 않는 상황을 생각하면됩니다.

http://blog.philippmetzler.com/?p=52

우리가 사용하는 장고 - 스마트 선택 :

2

나는이 당신을 위해 무엇을 찾고있는 생각

http://github.com/digi604/django-smart-selects

필립

+0

예제로 답을 넓힐 수 있습니까? ? 이것은 사실 URL 전용 답변입니다. 왜 그 블로그가 그들이 뭘하고있는거야? 왜 Django-Smart-Selects를 사용합니까? – Pureferret

4

또 다른 방법은 함께 Django Admin의 formfield_for_manytomany.

class MyModelAdmin(admin.ModelAdmin): 
    def formfield_for_manytomany(self, db_field, request, **kwargs): 
     if db_field.name == "cars": 
      kwargs["queryset"] = Car.objects.filter(owner=request.user) 
     return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs) 

"cars"는 ManyToMany 필드라는 것을 고려하십시오.

자세한 내용은 this link을 확인하십시오.