2011-07-03 20 views
8

मैं HTML इनपुट पाठ बॉक्स में लिखा पाठ के साथ Django (admin.py) में डेटा फ़िल्टर करना चाहते हैं। मुझे शहर द्वारा कंपनियों को फ़िल्टर करने की ज़रूरत है जिसमें वे हैं और सभी शहरों की सूची बहुत लंबी है। मैं फ़िल्टर में सभी शहरों की सूची को एक टेक्स्ट इनपुट द्वारा प्रतिस्थापित करना चाहता हूं। मैं इसी तरह यहां http://djangosnippets.org/snippets/2429/ कुछ पाया है लेकिन वहाँ दो समस्याएं हैं:HTML इनपुट पाठ बॉक्स

  1. लेखक models.py तैनात नहीं किया था, इसलिए यह मेरी जरूरतों (+ कोई टिप्पणी नहीं)
  2. वहाँ प्रयोग किया जाता है वर्ग UserFieldFilterSpec के लिए कोड बदलने के लिए difficuilt है (RelatedFilterSpec): लेकिन मैं (Django/योगदान/व्यवस्थापक/filterspecs.py फ़ाइल में और अधिक), क्योंकि शहरों की सूची comapny के रूप में एक ही कक्षा में कर रहे हैं (वहाँ शहरों में से वर्ग और उन्हें होना चाहिए shoud RelatedFilterSpec के बजाय AllValuesFilterSpec उपयोग करने की आवश्यकता विदेशी कुंजी (ManyToMany संबंध) से कंपनी के लिए संदर्भित है, लेकिन कुछ कारणों से यह इस तरह से किया जाना)
है

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) 

की तरह कुछ और कुछ लग रहा है, मैं की जरूरत है: 1. बजाय सूची के आयुध डिपो शहरों एक पाठ प्रदर्शित Django फ़िल्टर में इनपुट 2. उस पाठ इनपुट में शहर के निम इनपुट करने के बाद, शहर द्वारा डेटा फ़िल्टर करें (फ़िल्टरिंग के लिए अनुरोध कुछ सबमिट बटन या जावास्क्रिप्ट के माध्यम से भेजा जा सकता है)

सभी पदों के लिए धन्यवाद।

उत्तर

2

हालांकि यह वास्तव में आपका प्रश्न नहीं है, यह Django-Selectables के लिए एक आदर्श समाधान की तरह लगता है, आप केवल कुछ लाइनों के साथ एक AJAX संचालित CharField फॉर्म जोड़ सकते हैं, जिसमें शहरों की सूची से इसकी प्रविष्टियां चुनी जाएंगी। उपरोक्त लिंक में सूचीबद्ध नमूनों पर एक नज़र डालें।

+0

यह वास्तव में मैं क्या देख रहा था नहीं है। मेरी समस्या काम कर रहे पाठ इनपुट फ़िल्टर दिखाने के लिए है। स्वत: पूर्ण सुविधा अच्छी है और मैं इसे बाद में जोड़ना चाहूंगा। वैसे भी, आपकी प्रतिक्रिया के लिए धन्यवाद। – Jazzuell

+0

ठीक है मैंने इसे अपने आप पर लगाया। मैंने filterpecs.py में अपना खुद का फ़िल्टर बनाया (मुझे पता है कि यह करने का यह बुरा तरीका है)। यदि आप इसे अपने फ़िल्टर को पंजीकृत करने के बारे में सावधान रहें तो इस तरह से प्रयास करें। आपका फ़िल्टर सिस्टम फ़िल्टर से पहले पंजीकृत होना चाहिए। Models.py में से आपके फ़िल्टर को एट्रिब्यूट करने के लिए असाइन करें। फ़िल्टर में मैंने कुछ ऐसा उपयोग किया जो पोस्ट यूआरएल को बदलता है जहां पैरामीटर हैं। एक शहर द्वारा फ़िल्टरिंग शहर = प्राग द्वारा किया जाता है लेकिन यदि आप फिल्टर की सूची द्वारा फ़िल्टर करना चाहते हैं तो आप city__in = प्राग, वियन, डबलिन का उपयोग करते हैं। ऐसा करने के लिए कई अच्छे तरीके हैं (प्रश्न, AJAX, ..) लेकिन मैं बस सीख रहा हूं। – Jazzuell

12

यदि किसी को अभी भी इसकी आवश्यकता है। यह टेम्पलेट में थोड़ा हैकिश है, लेकिन जेएस के टुकड़े के बिना लागू किया गया है।

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

इस कोड स्निपेट के लिए बहुत बहुत धन्यवाद! आपने मुझे कुछ घंटों का काम बचाया। हालांकि आपके उदाहरण में एक छोटी सी त्रुटि है: 'CatalogCityFilter.queryset' कॉल को क्वेरीसेट वापस करना चाहिए। – devsnd

+0

@devsnd क्या यह कोड आपके मामले में अपवाद बढ़ाता है? self.filter_specs में filter_spec के लिए :: मैं Django स्रोतों से देख new_qs = filter_spec.queryset (अनुरोध, QS) अगर new_qs कोई भी नहीं है: qs = new_qs https://github.com/django/django/ ब्लॉब/मास्टर/डीजेंगो/contrib/admin/views/main.py # L325 अगर फिल्टर लौटाता है तो कुछ भी नहीं होता है। –

+0

कोई अपवाद नहीं है, लेकिन यह क्वेरीसेट लौटने से पहले काम नहीं करता है, क्योंकि फ़िल्टर 'फ़िल्टर' के साथ क्वेरीसेट की एक नई प्रतिलिपि देता है। – devsnd

0

मैं Django 1.10, 1.11 चल रहा हूँ और r_black FieldListFilter 'के solution पूरी तरह से फिट है क्योंकि Django शिकायत करते हुए कि फ़िल्टर फ़ील्ड से वारिस चाहिए नहीं था'।

तो 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 
     },) 

टेम्पलेट्स/व्यवस्थापक/textinput_filter।एचटीएमएल (अपरिवर्तित):

{% 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]