[Answer]-How to organize queries depending on previous queries?

1👍

✅

Example

app/models.py

from django.db import models

class Entry(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)
    views = models.IntegerField()

    def __str__(self):
        return self.title

app/urls.py (if you want to try this example, don’t forget to include app.urls in project.url)

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

app/views.py

from django.shortcuts import render
from .models import Entry

def index(request):
    # fields in which we want to order query
    ordering_fields = ['pub_date', 'views', 'title']

    # order_query is field names with dots between them
    order_query = request.GET.get('o')

    # ordering is something like ['views', 'tile']
    ordering = []
    if order_query:
        ordering = [x for x in order_query.split('.') if x in ordering_fields]
    entries = Entry.objects.order_by(*ordering)

    # look at index.html to understand, what query_strings is for
    query_strings = {}
    for field in ordering_fields:
        if field in ordering:
            # remove field
            idx = ordering.index(field)
            query_strings[field] = '.'.join(ordering[:idx]+ordering[idx+1:])
        else:
            # add fieild
            query_strings[field] = '.'.join(ordering + [field])

    return render(request, 'app/index.html', {
        'entries': entries,
        'query_strings': query_strings,
        'ordering': ordering
    })

app/templates/app/index.html

<!doctype html>
<head>
  <meta charset="utf-8">
  <title>Entries</title>
  <style>
  table {
    border: 1px solid #333;
  }
  td, th {
    border: 1px solid #333;
    padding: 5px 10px
  }
  </style>
</head>
<body>
  <p><a href="{% url 'index' %}">Index</a></p>
  <p>
    Sort by:
    <a href="?o={{ query_strings.title }}">Title</a>{% if 'title' in ordering %}*{% endif %} |
    <a href="?o={{ query_strings.views }}">Views</a>{% if 'views' in ordering %}*{% endif %} |
    <a href="?o={{ query_strings.pub_date }}">Pub date</a>{% if 'pub_date' in ordering %}*{% endif %}
  </p>
  <table>
    <thead>
      <tr>
        <th>Title</th>
        <th>Views</th>
        <th>Pub date</th>
      </tr>
    </thead>
    <tbody>
    {% for entry in entries %}
      <tr>
        <td>{{ entry.title }}</td>
        <td>{{ entry.views }}</td>
        <td>{{ entry.pub_date }}</td>
      </tr>
    {% endfor %}
    </tbody>
  </table>
</body>

URLs for ordering are like these: ?o=title, ?o=pub_date.views or ?o=views.title.pub_date.

In last case result is ordered by views, then by title, then by pub_date. Link for Title is ?o=views.pub_date, for Views is ?o=views.title and for Pub date is o?=views.title.

Leave a comment