Bas Jansen
Bas Jansen

Reputation: 3343

Combining two queries from different application/models to display them on a single overview page

I have only recently started working with Django and was wondering how one would go around to combine two queries from different application/models and display them in a given overview page. I will display some non-functional pseudo-code below to illustrate what I am trying to do:

Index.html

Note that I added two seperate context_object_names here just to illustrate what I am trying to do (latest_news and latest_enzyme)

{% extends 'base.html' %}

{% block body %}

<div id="docs-content">
  <div class="section" id="s-module-django.db.models.fields">
    <div class="page-header text-primary">
      <h3 class="info-header-blue-publication-small">Overview</h3>
    </div>
    <div>
      <h3 class="info-header-blue-publication-tiny">Latest news:</h3>
    </div>
    {% if latest_news %}
      {{ latest_news.news_text }}
    {% else %}
      <p>No recent news.</p>
    {% endif %}

    <div>
      <h3 class="info-header-blue-publication-tiny">Latest enzyme:</h3>
    </div>
    {% if latest_enzyme %}
      <ul>
        <li><a href="{% url 'gts:detail' latest_enzyme.id %}">{{ latest_enzyme.barcode  }}</a></li>
      </ul>
    {% else %}
      <p>No enzymes are available.</p>
    {% endif %}

  </div>
</div>

{% endblock %}

Views.py

Note that this contains some commented lines that illustrate the method that I was trying but did not get working, as well as two seperate get_querysets to illustrate my intent.

from django.shortcuts import render from django.http import
HttpResponse from django.views import generic

from gts.models import Enzymes 
from news.models import News

# Create your views here.

class IndexView(generic.ListView):
    template_name = 'overview/index.html'

    #context_object_name = 'latest_enzyme_news'
    #def get_queryset(self):
    #    latest_enzyme = Enzymes.objects.order_by('-pub_date')[0]
    #    latest_news = News.objects.order_by('-pub_date')[0]
    #    return (latest_enzyme, latest_news)

    context_object_name = 'latest_enzyme'
    def get_queryset(self):
        return Enzymes.objects.order_by('-pub_date')[0]

    context_object_name = 'latest_news'
    def get_queryset(self):
        return News.objects.order_by('-pub_date')[0]

I have looked at similar questions, where they tried to combine multiple queries from multiple models of the same application (e.g. Display objects from different models at the same page according to their published date) but I would appreciate any hint or tip on what would be the 'best practice' for the situation that I described as I would wish to combine queries from different applications more often.

Upvotes: 0

Views: 50

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599470

You don't want a ListView here at all. You're not listing things; you're just getting two separate items.

Rather, use a standard TemplateView and define get_context_data to return the specific items you want.

class IndexView(generic.TemplateView):
    template_name = 'overview/index.html'

    def get_context_data(self):
        latest_enzyme = Enzymes.objects.order_by('-pub_date')[0]
        latest_news = News.objects.order_by('-pub_date')[0]
        return {'latest_enzyme': latest_enzyme, 'latest_news': latest_news}

(Note also, you could just as easily use a function-based view for this, since you are not really getting any value from the class.)

Upvotes: 2

Related Questions