2017-09-25 16 views
0

所以我有一個選擇字段的ModelForm。在這個選擇字段中有大約100個條目。在這些參賽作品中,我有很多條目,比如「科羅拉多 - 科羅拉多丹佛」,我希望列表頂部有這樣的條目,這樣所有帶有「科羅拉多組織」的參賽作品都位列榜首,否則按字典順序排序。Django連接兩個查詢集在命令

我試圖使兩個獨立的查詢集(這似乎是一個壞主意,但管理的只有100個左右的條目)。似乎有很多方法來組合這兩個查詢集,但沒有維護順序(這是重點)。我已經試過這樣:

class CreateContactForm(ModelForm): 
    ... 

    def __init__(self, *args, **kwargs): 
     super(CreateContactForm, self).__init__(*args, **kwargs) 
     p = models.ConstantContactList.objects.filter(
      name__startswith=settings.PREF_ORGANIZATION_PREFIX 
     ) 
     np = models.ConstantContactList.objects.filter(
      name__regex=r'^(?!{})'.format(settings.PREF_ORGANIZATION_PREFIX) 
     ).order_by('-name') 

     self.fields['cc_lists'].queryset = list(p) + list(np) 

這是不行的,儘管它可能,如果有一些方法來該列表轉換回查詢集,或者,如果有一種方法去各地的queryset可能?我不確定。任何人都可以提供我應該做什麼的線索?

+0

你試過_without_兩個'list' coersions?我現在無法訪問Django進行測試,但它可能只是在SQL中創建一個'UNION()'來組合兩個查詢集'p'和'np'。 – C14L

+0

@ C14L'不支持的操作數類型爲+:'QuerySet'和'QuerySet' – Anupam

回答

2

我會建議不要試圖訂購查詢集,只是處理的渲染層(模板或形式)排序。這樣,如果你想本地化你的代碼,你將不必改變你的查詢。

假設你使用forms.Select部件。您可能想要從此小組件繼承並重寫render_menu邏輯,以便自己構建並自行處理排序。您將可以訪問呈現或未呈現的選項,因此從那時起它不應成爲問題。

+0

我會研究一下,這似乎更合理。 – BrotherJack

0

好的。我想出了一個可以在這裏使用的解決方案,並且將它提供給任何有相同需求的人。

from django.forms.widgets import Select 
import re 

class CustomOrderingWidget(Select): 
    def __init__(self, priority_regex, sort='+', attrs=None): 
     super(CustomOrderingWidget, self).__init__(attrs) 
     self.regex = re.compile(priority_regex) 
     self.sort = sort 
     self.template_name = 'django/forms/widgets/select.html' 

    def render(self, name, value, attrs=None, renderer=None): 
     context = self.get_context(name, value, attrs) 
     optgroups = context.get('widget').get('optgroups') 
     firsts, others = [], [] 
     for grp in optgroups: 
      if self.regex.search(grp[1][0].get('label')): 
       firsts.append(grp) 
      else: 
       others.append(grp) 
     if self.sort == '+': 
      kfn = lambda x: x[1][0].get('label') 
      context['widget']['optgroups'] = sorted(firsts, key=kfn) +\ 
               sorted(others, key=kfn) 
     elif self.sort == '-': 
      kfn = lambda x: x[1][0].get('label') 
      context['widget']['optgroups'] =\ 
       sorted(firsts, key=kfn, reverse=True) +\ 
       sorted(others, key=kfn, reverse=True) 
     else: 
      context['widget']['optgroups'] = firsts + others 
     return self._render(self.template_name, context, renderer) 

然後你就可以將它插入這樣的的ModelForm ...

import settings # YOUR personal stuffz! 

class CreateContactForm(ModelForm): 
    ... 
    class Meta: 
     ... 
     widgets = { 
      # Just an example, make your own regex string! 
      'cc_lists': CustomOrderingWidget("^{0}".format(
       settings.PREF_ORGANIZATION_PREFIX 
      )) 
     }