2011-07-03 12 views
8

HTML入力テキストボックスに書かれたテキストでDjango(admin.py)のデータをフィルタリングしたいと思います。私は彼らがいる都市によって企業をフィルタリングする必要があり、すべての都市のリストが長すぎます。フィルターのすべての都市のリストを1つのテキスト入力で置き換えたいと思います。私はここに似たような http://djangosnippets.org/snippets/2429/を見つけましたが、2つの問題があります。DjangoのHTML入力テキストボックスadmin.pyフィルタ

  1. 私のニーズに合わせてコードを変更するdifficuiltあるので、著者は(+コメント)、models.pyを掲載しませんでした
  2. 使用するクラスUserFieldFilterSpecがあるが(RelatedFilterSpec):都市のリストはcomapnyと同じクラスにあるので、RelatedFilterSpecの代わりにAllValuesFilterSpecを使用する必要があります(ファイルdjango/contrib/admin/filterspecs.pyの詳細を参照)。外部キー(ManyToMany関係)によって会社に参照するが、何らかの理由でこのようにしなければならない)
代わりに、リストOD都市の 1. 1つのテキストを表示:models.pyの

重要な部分はここでも、私がする必要admin.py

class CatalogAdmin(admin.ModelAdmin): 
    form = CatalogForm 
    list_display = ('title','city') 
    list_filter = ['city',] 

からこの

class Company(models.Model): 
    title = models.CharField(max_length=150,blank=False) 
    city = models.CharField(max_length=50,blank=True) 

と何かのようになりますDjangoフィルタで入力します 2.都市入力を入力した後、都道府県別にデータをフィルタリングします(いくつかの送信ボタンやjavascriptを使用してフィルタリング要求を送信できます)

すべての投稿のためによろしくお願いします。

答えて

2

実際にあなたの質問ではありませんが、Django-Selectablesの完璧な解決策のように聞こえます。都市のリストから選択したエントリを持つAJAXのCharFieldフォームを追加するだけで十分です。上記のリンクに記載されているサンプルをご覧ください。

+0

これは私が探していたものを本当にはありません。私の問題は、作業中のテキスト入力フィルタを表示することです。オートコンプリート機能がいいですし、後で追加したいと思います。とにかく、あなたの応答に感謝します。 – Jazzuell

+0

私はこれを自分で考えました。私はfilterspecs.pyで自分のフィルタを作成しました(私はそれが厄介な方法であることを知っています)。この方法を試してみると、フィルタを登録する際に注意が必要です。システムフィルターの前にフィルターを登録する必要があります。 models.pyよりも、それが属する属性にフィルタを割り当てる必要があります。 フィルタでは、私はパラメータがどこにあるurlを変更するものを使用しました。ある都市によるフィルタリングはcity = Pragueによって行われますが、フィルタのリストでフィルタリングする場合は、city__in = Prague、Wien、Dublinを使用します。これを行う方法(クエリ、AJAX、..)はもっと良い方法がたくさんありますが、私はただ学んでいます。 – Jazzuell

12

誰かがまだこれを必要とする場合。それはテンプレートではほとんどハックしませんが、jの部分なしで実装されています。

filters.py

from django.contrib.admin import ListFilter 

class SingleTextInputFilter(ListFilter): 
    """ 
    renders filter form with text input and submit button 
    """ 
    parameter_name = None 
    template = "admin/textinput_filter.html" 

    def __init__(self, request, params, model, model_admin): 
     super(SingleTextInputFilter, self).__init__(
      request, params, model, model_admin) 
     if self.parameter_name is None: 
      raise ImproperlyConfigured(
       "The list filter '%s' does not specify " 
       "a 'parameter_name'." % self.__class__.__name__) 

     if self.parameter_name in params: 
      value = params.pop(self.parameter_name) 
      self.used_parameters[self.parameter_name] = value 

    def value(self): 
     """ 
     Returns the value (in string format) provided in the request's 
     query string for this filter, if any. If the value wasn't provided then 
     returns None. 
     """ 
     return self.used_parameters.get(self.parameter_name, None) 

    def has_output(self): 
     return True 

    def expected_parameters(self): 
     """ 
     Returns the list of parameter names that are expected from the 
     request's query string and that will be used by this filter. 
     """ 
     return [self.parameter_name] 


    def choices(self, cl): 
     all_choice = { 
      'selected': self.value() is None, 
      'query_string': cl.get_query_string({}, [self.parameter_name]), 
      'display': _('All'), 
     } 
     return ({ 
      'get_query': cl.params, 
      'current_value': self.value(), 
      'all_choice': all_choice, 
      'parameter_name': self.parameter_name 
     },) 

textinput_filter.html

{% load i18n %} 
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3> 

{#i for item, to be short in names#} 
{% with choices.0 as i %} 
<ul> 
    <li> 
     <form method="get"> 
      <input type="search" name="{{ i.parameter_name }}" value="{{ i.current_value|default_if_none:"" }}"/> 

      {#create hidden inputs to preserve values from other filters and search field#} 
      {% for k, v in i.get_query.items %} 
       {% if not k == i.parameter_name %} 
        <input type="hidden" name="{{ k }}" value="{{ v }}"> 
       {% endif %} 
      {% endfor %} 
      <input type="submit" value="{% trans 'apply' %}"> 
     </form> 
    </li> 

    {#show "All" link to reset current filter#} 
    <li{% if i.all_choice.selected %} class="selected"{% endif %}> 
     <a href="{{ i.all_choice.query_string|iriencode }}"> 
      {{ i.all_choice.display }} 
     </a> 
    </li> 
</ul> 
{% endwith %} 

は、その後、あなたのモデル

フィルタを使用する準備に応じて次のようになります。

+1

このコードスニペットをありがとう!あなたはちょうど私に数時間の仕事を救った。あなたの例では小さなエラーが1つあります: 'CatalogCityFilter.queryset'コールはクエリーセットを返さなければなりません。 – devsnd

+0

@devsndこのコードはあなたのケースで例外を発生させますか? new_qsがNoneでない場合 new_qs = filter_spec.queryset(リクエスト、QS) : QS = new_qs https://github.com/django/django/ self.filter_specsでFILTER_SPECため :私はDjangoのソースからわかるようにblob/master/django/contrib/admin/views/main.py#L325 フィルタが返ってきた場合は何も起こりません。 –

+0

例外はありませんが、 'filter'がフィルタを適用したクエリセットの新しいコピーを返すので、クエリセットを返す前に動作しませんでした。 – devsnd

0

私はジャンゴ1.10、1.11を実行しているとFieldListFilter 『r_black「Djangoはそのフィルタフィールドから継承しなければなら文句れたため、S solutionは完全にフィットしませんでした』。

FieldListFilterから継承するフィルタの単純な変更は、Djangoが不平を言い、同時に各フィールドに新しいクラスを指定する必要はありませんでした。

class SingleTextInputFilter(admin.FieldListFilter): 
    """ 
    renders filter form with text input and submit button 
    """ 

    parameter_name = None 
    template = "admin/textinput_filter.html" 

    def __init__(self, field, request, params, model, model_admin, field_path): 
     super().__init__(field, request, params, model, model_admin, field_path) 
     if self.parameter_name is None: 
      self.parameter_name = self.field.name 

     if self.parameter_name in params: 
      value = params.pop(self.parameter_name) 
      self.used_parameters[self.parameter_name] = value 

    def queryset(self, request, queryset): 
     if self.value(): 
      return queryset.filter(imei__icontains=self.value()) 

    def value(self): 
     """ 
     Returns the value (in string format) provided in the request's 
     query string for this filter, if any. If the value wasn't provided then 
     returns None. 
     """ 
     return self.used_parameters.get(self.parameter_name, None) 

    def has_output(self): 
     return True 

    def expected_parameters(self): 
     """ 
     Returns the list of parameter names that are expected from the 
     request's query string and that will be used by this filter. 
     """ 
     return [self.parameter_name] 

    def choices(self, cl): 
     all_choice = { 
      'selected': self.value() is None, 
      'query_string': cl.get_query_string({}, [self.parameter_name]), 
      'display': _('All'), 
     } 
     return ({ 
      'get_query': cl.params, 
      'current_value': self.value(), 
      'all_choice': all_choice, 
      'parameter_name': self.parameter_name 
     },) 

テンプレート/ admin/textinput_filter。HTML(変わらず):

{% load i18n %} 
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3> 

{#i for item, to be short in names#} 
{% with choices.0 as i %} 
<ul> 
    <li> 
     <form method="get"> 
      <input type="search" name="{{ i.parameter_name }}" value="{{ i.current_value|default_if_none:"" }}"/> 

      {#create hidden inputs to preserve values from other filters and search field#} 
      {% for k, v in i.get_query.items %} 
       {% if not k == i.parameter_name %} 
        <input type="hidden" name="{{ k }}" value="{{ v }}"> 
       {% endif %} 
      {% endfor %} 
      <input type="submit" value="{% trans 'apply' %}"> 
     </form> 
    </li> 

    {#show "All" link to reset current filter#} 
    <li{% if i.all_choice.selected %} class="selected"{% endif %}> 
     <a href="{{ i.all_choice.query_string|iriencode }}"> 
      {{ i.all_choice.display }} 
     </a> 
    </li> 
</ul> 
{% endwith %} 

使用法:

class MyAdmin(admin.ModelAdmin): 
    list_display = [your fields] 
    list_filter = [('field 1', SingleTextInputFilter), ('field 2', SingleTextInputFilter), further fields] 
関連する問題