2013-03-21 3 views
1

새 앱을 시작할 예정이며 클래스 기반 뷰를 채택하기 위해 최선을 다하고 있습니다. Ahhh, 성장 통증. 여기서 GET 변수에서 간단한 필터를 수행하려고합니다. 존재하지 않으면 id desc로 정렬 된 모든 객체를 반환하고 싶으면 필터링하고 목록을 반환하고 싶습니다.Django에서 get()을 오버라이드하여 필터로 필터링

3038 줄의 코드를 작성하므로 일을해야합니까? 나는 get_queryset()을 재정의 (override)하려고 시도 했으므로 이제는 그것을 생각해 보았다. get_queryset()에서 self.request.GET [ 'search']를 호출해야 필터링이 가능하다. 이 작업을 수행하는 표준 방법이 있습니까?

class MyModelList(AdminPageMixin, ListView): 
    model = MyModel 
    context_object_name = 'object' 
    template_name = 'template/list.html' 

    def get(self, request, *args, **kwargs): 
     if 'search' in request.GET and len(request.GET['search']): 
      search = request.GET['search'] 
      self.object_list = MyModel.objects.filter(advertiser__name=search).orderby('-id') 
      context = self.get_context_data(object_list=self.object_list, search=search) 
     else: 
      self.object_list = MyModel.objects.all() 
      context = self.get_context_data(object_list=self.object_list).orderby('-id') 
     return self.render_to_response(context) 

    def get_context_data(self, **kwargs): 
     context = super(MyModelList, self).get_context_data(**kwargs) 
     form = MyModelForm 
     try: 
      context['search'] = kwargs['search'] 
     except KeyError: 
      pass 
     context['form'] = form 
     context['form_action'] = reverse('mymodel-add') 
     context['form_display'] = 'hide' 
     context['form_save_label'] = 'Add' 
     return context 

은 둘째로, 문제를 복잡하게하기 위해, 나는 CreateView 내가 가져 오기() 또는 get_queryset()와 get_context_data() 내 ListView에 방법을 공유 할 것 인 UpdateView 있습니다. 믹스 인이 가능할 것이라고 확신하지만 다시 표준화 된 방법을 찾고 있습니다. 제안? 다음은 ListView의 메서드를 공유하고 싶은 CreateView입니다.

class MyModelAdd(AdminPageMixin, CreateView): 
    model = MyModel 
    form_class = MyModelForm 
    context_object_name = 'object' 
    template_name = 'templates/list.html' 

    def get_success_url(self): 
     return reverse('mymodel-list') 

    def get_context_data(self, **kwargs): 
     context = super(MyModelAdd, self).get_context_data(**kwargs) 
     context['form_action'] = reverse('mymodel-add') 
     context['form_display'] = 'show' 
     context['object_list'] = MyModel.objects.all() 
     return context 

    def form_invalid(self, form): 
     form = MyModelForm(self.request.POST) 
     context = self.get_context_data() 
     context['form'] = form 
     context['form_action'] = reverse('mymodel-add') 
     context['form_display'] = 'show' 
     context['form_save_label'] = 'Add' 
     return render(self.request, 'templates/list.html', context) 
+2

CBV가 반드시 적은 수의 코드를 의미하는 것은 아닙니다. –

+3

감사합니다. @Samuele. 그걸 내 docstrings에 추가 할 것이다;) – scoopseven

+0

클래스 기반 뷰는 고통이지만 기본 클래스를보다 잘 리팩터링하는 방법을 배우면 천천히 좋아진다. – miki725

답변

3

먼저 관찰에 맞습니다. 목록을 필터링하는 데 확실히 get_queryset을 사용해야합니다. 당신이 정말로, 당신은 믹스 인을 사용하는 것보다 별도의 함수를 작성하는 더 나을 것 목록과 다른 뷰 사이의 코드를 재사용해야하는 경우,

class MyModelList(AdminPageMixin, ListView): 
    model = MyModel 
    context_object_name = 'object' 
    template_name = 'template/list.html' 

    def get_queryset(self): 
     qs = self.model.objects.all() 
     search = self.request.GET.get('search') 
     if search: 
      qs = qs.filter(advertiser__name__icontains=search) 
     qs = qs.order_by("-id") # you don't need this if you set up your ordering on the model 
     return qs 

둘째 : 나는의 라인을 따라 뭔가를 제안한다.

부채 : 양식에 form_action URL이 필요하지 않습니다. 단순히 action=""으로 설정하면 동일한 URL로 POST됩니다.

+0

고마워요! MyModelEdit에서 다르게 설정하고 같은 양식을 사용하기 때문에 form_action을 사용하고 있습니다. 편집보기에서 컨텍스트 [ 'form_action'] = reverse ('mymodel-add')를 CreateView보기 및 컨텍스트 [ 'form_action'] = reverse ('mymodel-edit')에서 다시 호출하면 동일한 HTML 파일이 다시 호출됩니다. 다시 한번 감사드립니다. – scoopseven

+0

"둘째, List와 다른보기간에 코드를 재사용해야하는 경우 mixin을 사용하는 것보다 별도의 기능을 사용하는 것이 더 좋습니다." - 이것의 좋은 예가 무엇인지 알고 있습니까? – scoopseven

+1

다음과 같이 읽으면 안됩니다 :'search : qs = qs.filter (advertiser__name__icontains = search)'? – allcaps

0

가장 좋은 방법은 'get_context_data'에서 데이터를 필터링하는 것입니다.

def get_context_data(self, **kwargs): 
    context = super(MyModelAdd, self).get_context_data(**kwargs) 
    context['form_action'] = reverse('mymodel-add') 
    context['form_display'] = 'show' 
    context['object_list'] = MyModel.objects.all(user=self.request.user)# that's will filter the user data 
    return context