2017-09-24 91 views
0

我有一個模型Jar,它有一個crate屬性 - 一個ForeignKey到一個Crate模型。 Crate模型具有capacity屬性(它可以容納的罐子的數量)和jars屬性(它當前擁有的罐子的數量),它是這一行: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

隨着Python開發鬆弛服務器上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的解決方案類似,但我猜他們並不擔心沒有參與者的情況。我在這個問題上給出了接受的答案,因爲如果我原來看到它,我可能不必發表這個問題。