1

I have a rank.html which is a publicly sharing template for many other templates through {% include rank.html %} method.

This template will display the 48 hours hot news base on the click number.

Here is the view.py:

def rank(self, request):
    hot_news_48h = h_mostViewed(48, News, '-pv')

   return render(request, "rank.html", {
        'hot_news_48h': hot_news_48h,})

h_mostViewed(48, News, '-pv') is a function,that can fetch most viewed(clicked) post within 48 hours.It works.

Here is the rank.html:

<ul>
    {% for hot_view in hot_news_48h %}
 <li>
    <a href="{% url 'news:news_detail' hot_view.pk %}" >
      <img src="{{ MEDIA_URL }}{{ hot_view.image }}" >
    </a>

    <a href="{% url 'news:news_detail' hot_view.pk %}">
      <h6>{{ hot_view.title }}</h6>
     </a>
</div>
</li>
  {% endfor %}
</ul>

Here is the url.py:

path('hot_news', views.rank, name="hot_news")

The problem is,I can only get the html ,but can't receive the data.

But if I give up {% include rank.html %} method and insert the rank.html's code directly inside each template which need this function, I can get the data. Take new_detail.html template as an example:

Here is the view.py:

def newsDetailView(request, news_pk):
    news = get_object_or_404(News, id=news_pk)
    all_comments = NewsComments.objects.filter(news=news)
    news.comment_nums = all_comments.count()
    news.save()
    News.objects.filter(id=news_pk).update(pv=F('pv') + 1)

    hot_news_48h = h_mostViewed(48, News, '-pv')

    relative_news = News.objects.filter(tag__id__in=news.tag.all()).exclude(id=news_pk)[:6]

    return render(request, "news_detail.html", {
        'news': news,
        'all_comments': all_comments,
        'hot_news_48h': hot_news_48h,

        'relative_news': relative_news
    })

Here is the urls.py:

path('-<int:news_pk>', views.newsDetailView, name="news_detail"),

So above,I directly inserted rank.html's code into new_detail.html and it works I can get the data.

My question is what should I do or correct,so that I can get the data in {% include rank.html %} method. Because {% include rank.html %} is simple and flexible.I don't want to repeat the same code in several same template.

Thank you so much for your patience!

William
  • 3,724
  • 9
  • 43
  • 76
  • You should use a custom template tag - an [inclusion tag](https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/#inclusion-tags) that renders the rank template with the context it needs. – Daniel Roseman Aug 17 '18 at 16:29
  • Thank you so much for reply.Could you give me more detail? – William Aug 17 '18 at 16:31

2 Answers2

1

How about this: - Create a folder "templatetags" in your application and add a file "news_tags.py" or name it what you want. Then you can define the tags you need:

from django.template import Library
from your_app.models import your_model

register = Library()

@register.inclusion_tag('your_app/your_template.html')
def hot_news(num, order):
    objects = News.objects.order_by(order)[:num]

    result['objects'] = objects

    return result

In your templates you then do the following:

{% load news_tags %}
{% hot_news 48 '-pv' %}

Then create a template as your already did and reference it in the inclusion tag. Then it should work properly.

If you want it to work for multiple models you can have a look at this: https://docs.djangoproject.com/el/2.1/ref/applications/ The apps framework allows you to fetch models from a string input.

Herbert
  • 108
  • 7
  • 1
    Thank you so much!It looks like a very advanced method.I'll learn and try. – William Aug 18 '18 at 01:26
  • Hi friend can you help me with this question https://stackoverflow.com/questions/52159365/reverse-for-news-detail-with-arguments-not-found-1-patterns-tried ? – William Sep 04 '18 at 14:15
  • 1
    Thank you so much, now I'm doing another project ,and finally found this is the best way to do it! – William Feb 07 '21 at 07:36
0

I finally solved the issue by Creating custom context processor.https://www.youtube.com/watch?v=QTgkGBjjVYM

William
  • 3,724
  • 9
  • 43
  • 76