pythondjangodjango-templatesviewrender-to-response

Django pass render_to_response template in other template


this is probably a question for absolute beginners since i'm fairly new to progrmaming. I've searched for couple of hours for an adequate solution, i don't know what else to do.

Following problem. I want to have a view that displays. e.g. the 5 latest entries & 5 newest to my database (just an example)

#views.py
import core.models as coremodels

class LandingView(TemplateView):
    template_name = "base/index.html"

    def index_filtered(request):
        last_ones = coremodels.Startup.objects.all().order_by('-id')[:5]
        first_ones = coremodels.Startup.objects.all().order_by('id')[:5]
        return render_to_response("base/index.html", 
        {'last_ones': last_ones,   'first_ones' : first_ones})  

Index.html shows the HTML content but not the content of the loop

#index.html

<div class="col-md-6">
    <p> Chosen Items negative:</p>
    {% for startup in last_ones %}
        <li><p>{{ startup.title }}</p></li>
    {% endfor %}
</div>

<div class="col-md-6">
    <p> Chosen Items positive:</p>
    {% for startup in first_ones %}
       <li><p>{{ startup.title }}</p></li>
    {% endfor %}

Here my problem:

How can I get the for loop to render the specific content?

I think Django show render_to_response in template comes very close to my problem, but i don't see a valid solution there.

Thank you for your help.

Chris

-- I edited my code and problem description based on the solutions provided in this thread


Solution

  • the call render_to_response("base/showlatest.html"... renders base/showlatest.html, not index.html.

    The view responsible for rendering index.html should pass all data (last_ones and first_ones) to it.

    Once you have included the template into index.html

    {% include /base/showlatest.html %}
    

    Change the view above (or create a new one or modify the existing, changing urls.py accordingly) to pass the data to it

    return render_to_response("index.html", 
    {'last_ones': last_ones,   'first_ones' : first_ones})
    

    The concept is that the view renders a certain template (index.html), which becomes the html page returned to the client browser. That one is the template that should receive a certain context (data), so that it can include other reusable pieces (e.g. showlatest.html) and render them correctly.

    The include command just copies the content of the specified template (showlatest.html) within the present one (index.html), as if it were typed in and part of it.

    So you need to call render_to_response and pass it your data (last_ones and first_ones) in every view that is responsible for rendering a template that includes showlatest.html

    Sorry for the twisted wording, some things are easier done than explained. :)

    UPDATE

    Your last edit clarified you are using CBV's (Class Based Views).

    Then your view should be something along the line:

    class LandingView(TemplateView):
        template_name = "base/index.html"
    
        def get_context_data(self, **kwargs):
            context = super(LandingView, self).get_context_data(**kwargs)
            context['last_ones'] = coremodels.Startup.objects.all().order_by('-id')[:5]
            context['first_ones'] = coremodels.Startup.objects.all().order_by('id')[:5]
            return context
    

    Note: personally I would avoid relying on the id set by the DB to order the records.

    Instead, if you can alter the model, add a field to mark when it was created. For example

    class Startup(models.Model):
        ...
        created_on = models.DateTimeField(auto_now_add=True, editable=False)
    

    then in your view the query can become

        def get_context_data(self, **kwargs):
            context = super(LandingView, self).get_context_data(**kwargs)
            qs = coremodels.Startup.objects.all().order_by('created_on')
            context['first_ones'] = qs[:5]
            context['last_ones'] = qs[-5:]
            return context