2011-02-08 3 views
1

Как отсортировать столбец элементов Django внутри таблицы?Как отсортировать столбец элементов Django внутри таблицы?

Я замечаю, что администратор Django делает это. Как?

Любые доступные веб-ресурсы, где я могу это прочитать?

* Под «элементами Django» Я имею в виду вставных объектов шаблона, которые выглядят следующим образом:

{{ x.y }} 

ответ

1

Если вы получаете его из запроса используйте метод order_by() в представлении. Если это список, используйте метод sort() в представлении.

+0

Спасибо, что именно я искал. Это немного отдельный вопрос: для визуальных эффектов администратор затеняет заголовок и добавляет asc/desc, стрелка. Это делается в представлении или HTML/JQuery? – pythondjango

+0

Это делается в шаблоне и в представлении. –

3

Стоит иметь взгляд на исходный вид кода список изменений в Джанго администратора:

http://code.djangoproject.com/svn/django/branches/releases/1.2.X/django/contrib/admin/views/main.py

Процесс заказа примерно:

  1. нажатии на заголовок столбца в админ , это перезагружает страницу соответствующим параметром заказа в URL-адресе, доступном в запросе.GET

  2. этот заказ Параметр обрабатывается в окне списка изменений:

    self.order_field, self.order_type = self.get_ordering()

  3. QuerySet генерируется:

    self.query_set = self.get_query_set() Inparticular, следующие строки в функции: , если self.order_field: qs = qs.order_by ('% s% s'% ((self.order_type == 'desc' и '-' or ''), self.order_field))

Использование администратора django при понимании исходного кода является одним из лучших способов узнать django на мой взгляд!

0

Я создал этот класс утилиты, посмотрев, как администратор сделал все это в Django 0.96.

Он обрабатывает критерии order_by, основанные на параметрах GET, и предоставляет переменные контекста, которые будут использоваться для генерации сортировочных ссылок заголовка таблицы, которые уважают текущее поле и направление сортировки, изменяя направление, когда один и тот же заголовок сортируется снова.вид

ORDER_VAR = 'o' 
ORDER_TYPE_VAR = 'ot' 

class SortHeaders: 
    """ 
    Handles generation of an argument for the Django ORM's 
    ``order_by`` method and generation of table headers which reflect 
    the currently selected sort, based on defined table headers with 
    matching sort criteria. 

    Based in part on the Django Admin application's ``ChangeList`` 
    functionality. 
    """ 
    def __init__(self, request, headers, default_order_field=None, 
      default_order_type='asc', additional_params=None): 
     """ 
     request 
      The request currently being processed - the current sort 
      order field and type are determined based on GET 
      parameters. 

     headers 
      A list of two-tuples of header text and matching ordering 
      criteria for use with the Django ORM's ``order_by`` 
      method. A criterion of ``None`` indicates that a header 
      is not sortable. 

     default_order_field 
      The index of the header definition to be used for default 
      ordering and when an invalid or non-sortable header is 
      specified in GET parameters. If not specified, the index 
      of the first sortable header will be used. 

     default_order_type 
      The default type of ordering used - must be one of 
      ``'asc`` or ``'desc'``. 

     additional_params: 
      Query parameters which should always appear in sort links, 
      specified as a dictionary mapping parameter names to 
      values. For example, this might contain the current page 
      number if you're sorting a paginated list of items. 
     """ 
     if default_order_field is None: 
      for i, (header, query_lookup) in enumerate(headers): 
       if query_lookup is not None: 
        default_order_field = i 
        break 
     if default_order_field is None: 
      raise AttributeError('No default_order_field was specified and none of the header definitions given were sortable.') 
     if default_order_type not in ('asc', 'desc'): 
      raise AttributeError('If given, default_order_type must be one of \'asc\' or \'desc\'.') 
     if additional_params is None: additional_params = {} 

     self.header_defs = headers 
     self.additional_params = additional_params 
     self.order_field, self.order_type = default_order_field, default_order_type 

     # Determine order field and order type for the current request 
     params = dict(request.GET.items()) 
     if ORDER_VAR in params: 
      try: 
       new_order_field = int(params[ORDER_VAR]) 
       if headers[new_order_field][1] is not None: 
        self.order_field = new_order_field 
      except (IndexError, ValueError): 
       pass # Use the default 
     if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'): 
      self.order_type = params[ORDER_TYPE_VAR] 

    def headers(self): 
     """ 
     Generates dicts containing header and sort link details for 
     all defined headers. 
     """ 
     for i, (header, order_criterion) in enumerate(self.header_defs): 
      th_classes = [] 
      new_order_type = 'asc' 
      if i == self.order_field: 
       th_classes.append('sorted %sending' % self.order_type) 
       new_order_type = {'asc': 'desc', 'desc': 'asc'}[self.order_type] 
      yield { 
       'text': header, 
       'sortable': order_criterion is not None, 
       'url': self.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}), 
       'class_attr': (th_classes and ' class="%s"' % ' '.join(th_classes) or ''), 
      } 

    def get_query_string(self, params): 
     """ 
     Creates a query string from the given dictionary of 
     parameters, including any additonal parameters which should 
     always be present. 
     """ 
     params.update(self.additional_params) 
     return '?%s' % '&'.join(['%s=%s' % (param, value) \ 
            for param, value in params.items()]) 

    def get_order_by(self): 
     """ 
     Creates an ordering criterion based on the current order 
     field and order type, for use with the Django ORM's 
     ``order_by`` method. 
     """ 
     return '%s%s' % (
      self.order_type == 'desc' and '-' or '', 
      self.header_defs[self.order_field][1], 
     ) 

Пример:

from somewhere import SortHeaders 
from django.contrib.auth.models import User 
from django.shortcuts import render_to_response 

LIST_HEADERS = (
    ('Username', 'username'), 
    ('First Name', 'first_name'), 
    ('Last Name', 'last_name'), 
    ('Email', None), 
) 

def user_list(request): 
    sort_headers = SortHeaders(request, LIST_HEADERS) 
    users = User.objects.order_by(sort_headers.get_order_by()) 
    return render_to_response('users/user_list.html', { 
     'users': users, 
     'headers': list(sort_headers.headers()), 
    }) 

Образец шаблона (users/user_list.html):

{% load my_tags %} 
<table cellspacing="0"> 
<thead> 
    <tr> 
{% table_header headers %} 
    </tr> 
</thead> 
<tbody> 
    {% for user in users %}<tr class="{% cycle odd,even %}"> 
    <td><a href="{{ user.get_absolute_url }}">{{ user.username }}</a></td> 
    <td>{{ user.first_name }}</td> 
    <td>{{ user.last_name }}</td> 
    <td>{{ user.email }}</td> 
    </tr> 
    {% endfor %} 
</tbody> 
</table> 

включение Пример тега (templatetags/my_tags.py):

from django import template 

def table_header(context, headers): 
    return { 
     'headers': headers, 
    } 

register = template.Library() 
register.inclusion_tag('table_header.html', takes_context=True)(table_header) 

Пример включения тега Templ ate (table_header.html):

{% for header in headers %}<th{{ header.class_attr }}> 
    {% if header.sortable %}<a href="{{ header.url }}">{% endif %} 
    {{ header.text }} 
    {% if header.sortable %}</a>{% endif %} 
</th>{% endfor %}