2017-09-24 5 views
0

ForeignKey ~ Crate 모델의 Jar 속성은 crate입니다. Crate 모델에는 속성 (보유 할 수있는 jar 수)과 jars 속성 (현재 보유한 jar 수)이 있습니다.이 행은 return self.jar_set.filter(is_active=True).count()입니다.관리 작업을위한 중간 페이지의 동적 드롭 다운

여러 개의 병을 새 상자로 옮기는 관리 작업이 있습니다. 중간 페이지를 사용하여 대상 크레이트를 선택합니다. 현재 모든 상자가 드롭 다운 목록에 있지만 나열된 상자를 선택한 병의 수만큼 공간이있는 상자로 제한하려고합니다. 방법?

여기 admin.py에서 관리 작업입니다 :

class MoveMultipleJarsForm(forms.Form): 
    # This needs to somehow be restricted to those crates that have room 
    dest = forms.ModelChoiceField(queryset=Crate.objects.all().order_by('number')) 

def move_multiple_jars(self, request, queryset): 
    form = None 

    if 'apply' in request.POST: 
     form = self.MoveMultipleJarsForm(request.POST) 

     if form.is_valid(): 
      dest = form.cleaned_data['dest'] 

      count = 0 
      for jar in queryset: 
       jar.crate = dest 
       jar.save() 
       count += 1 

      plural = '' 
      if count != 1: 
       plural = 's' 

      self.message_user(request, "Successfully moved %d jar%s to %s" % (count, plural, dest)) 
      return HttpResponseRedirect(request.get_full_path()) 
    if not form: 
     form = self.MoveMultipleJarsForm() 

    return render(request, 'admin/move_multiple_jars.djhtml', { 
     'jars': queryset, 
     'move_multiple_jars_form': form, 
     }) 

move_multiple_jars.short_description = "Move multiple jars to new crate" 

답변

0

파이썬 개발자 여유 서버 laidibug의 도움으로, 나는 해결책을 마련 할 수 있었다.

class MoveMultipleJarsForm(forms.Form): 
    dest = forms.ModelChoiceField(Crate.objects.none()) 

    def __init__(self, *args, **kwargs): 
     count = kwargs.pop('count') 
     super().__init__(*args, **kwargs) 
     self.fields['dest'].queryset = Crate.objects.annotate(room=F('capacity')-Sum(Case(When(jar__is_active=True, then=1), default=0), output_field=IntegerField())).filter(room__gte=count).order_by('number') 


def move_multiple_jars(self, request, queryset): 
    form = None 

    if 'apply' in request.POST: 
     form = self.MoveMultipleJarsForm(request.POST) 

     if form.is_valid(): 
      dest = form.cleaned_data['dest'] 

      count = 0 
      for jar in queryset: 
       jar.crate = dest 
       jar.save() 
       count += 1 

      plural = '' 
      if count != 1: 
       plural = 's' 

      self.message_user(request, "Successfully moved %d jar%s to %s" % (count, plural, dest)) 
      return HttpResponseRedirect(request.get_full_path()) 
    if not form: 
     form = self.MoveMultipleJarsForm(count=queryset.count()) 

    return render(request, 'admin/move_multiple_jars.djhtml', { 
     'jars': queryset, 
     'move_multiple_jars_form': form, 
     }) 

move_multiple_jars.short_description = "Move multiple jars to new crate" 

용액 첫 걸음은 대상 상자의리스트를 변경할 수있는 초기 값과의 검색어에 병의 수를 전달하는 클래스 형태를 수정하는 것이다. 나는 SubqueryOuterRef으로 90 %의 해결책을 가졌지 만 활성 병이없는 상자는 처리 할 수 ​​없었습니다. 이 질문에 대답을 받아 들였습니다. How to filter objects for count annotation in Django? 이상하게도 내 90 % 솔루션은 Django 1.11에 대한 솔루션과 비슷하지만 참가자가없는 경우는 걱정하지 않았다고 생각합니다. 나는 그 질문에서 받아 들여진 대답을 또 하나의 득표로주었습니다. 원래 그것을 본다면 나는이 질문을 게시 할 필요가 없었기 때문입니다.