Django Template changing html attribute based on slug and current request - python

When I tried to iterate through a list of post titles to create links in a django template the urls never match the requested path (matching the current web page should alter the formatting on the page for that list item). When I try and change things, Django spits out a 404 error which doesn't let me diagnose the problem or it "works" but not as expected.
the relevant url patterns (in blog app within project):
path('', views.index, name='blog_index'),
path('<slug:post>', views.blog_post, name='entries')
the relevant views functions (in blog app within project):
ef index(request):
try:
return render(request, 'blog/index.html', {'posts':blog_posts.keys})
except:
raise Http404()
def blog_post(request, post):
try:
return render(request, 'blog/post.html', {
'post_title':post,
'post_content':blog_posts[],
'posts':blog_posts.keys
})
except:
raise Http404()
the navigation template:
<ul>
{% for post in posts %}
{% url "blog:entries" "{{post}}" as blog_entry %}
<li><a href="/blog/{{post}}" {% if request.path == blog_entry %} class="active"{% endif %}>
<span class="item">{{post}}</span>
</a></li>
{% endfor %}
</ul>
I suspect the {% url "blog:entries" "{{post}}" as blog_entry %} in the template is not resolving correctly as when I replace the href with {% blog_entry %} it causes a 404 error.
I have tried hard coding it in, I have tried different ways of writing the url, I have tried changing the syntax (in case I am doing it incorrectly. I have checked the page source when I have run tests. I have never been able to get the class attribute to be "active" when on the matching page.
EDIT: The links all go to the correct pages, however the IF logic in the template does not work. i.e. None of the changes I have tried make result in reques.path == blog_entry resolving as True.
Also the above code snippets are part of an App within a project and I have included more of the views.py and urls.py file. Currently I have the "blog posts" stored in a dictionary at the top of views.py for testing.

Try this:
<ul>
{% for post in posts %}
{% url "blog:entries" post=post as blog_entry %}
<li><a href="/blog/{{post}}" {% if request.path == blog_entry %} class="active"{% endif %}>
<span class="item">{{post}}</span>
</a></li>
{% endfor %}
</ul>

Related

page not found in django?

i am new to django. this is the error i keep getting when i try to visit node.name page.
page not found Request URL: http://127.0.0.1:8000/Category//
urls.py
Category/<category_id>/ [name='productlisting']
index.html
{% load mptt_tags %}
<ul class="root">
{% recursetree listing %}
<li>
{{ node.name }}
</li>
{% endrecursetree %}
</ul>
urls.py
path('Category/<category_id>/',views.productlisting, name='productlisting'),
path('Category/<category_id>/product/<product_id>/',views.details, name='details'),
thanks in advance.
First you have an extra ending / in the endpoint you are trying to hit.
This is not how we name urls in anchor tag. Please refer here on how to name url and how to use it in template
so basically idea is that you would name url in urls.py in following manner:
path('Category/<int:category_id>/',views.productlisting,name='productlisting'),
then you would use this url name in template as:
{{ node.name }}

django NoReverseMatch at / TypeError - missing required positional arguments

path('administration/delete-post/', administration_views.delete_upload, name='delete_upload'),
path('administration/delete-post/<slug:post_slug>', administration_views.delete_upload, name='delete_upload'),
For some reason, when I added delete class, I had to add two url patterns.
When I comment out the first path, It gives me an error of
Reverse for 'NoReverseMatch at /administration/
delete_upload' with no arguments not found. 1 pattern(s) tried: ['administration/delete\\-post/(?P<post_slug>[-a-zA-Z0-9_]+)$']
I even stated the slugs on html.
{% for post in posts %}
Delete Upload
{% endif %}
With two same url patterns, it worked fine somehow, but now I want to add a confirmation page, and it's causing an error again.
views.py
def delete_upload(request, post_slug):
post = get_object_or_404(VideoPost, slug=post_slug)
if request.method == "POST":
post.delete()
context = {
"post": post
}
return render(request, "administration/confirm_delete.html", context)
confirm_delete.html
{% block content %}
<form action="." method="POST">{% csrf_token %}
<h1>Are you sure you want to delete</h1>
<p>{{post.title}}</p>
Cancel<input type="submit" value="Confirm">
</form>
{% endblock %}
error
TypeError at /administration/delete-post/
delete_upload() missing 1 required positional argument: 'post_slug'
It directs me to confirm_delete page correctly with the slugs on url, but when I click confirm, the slug is gone on the url and it's causing the error it seems.
I see the problem, but I can't fix it... please help.
Thank you for any helps
Remove path('administration/delete-post/', in your urls.py file
In your HTML template pass your post.slug along with the url namespace
{% for post in posts %}
Delete Upload
{% endif %}
You are using url template tag incorrectly. In html you need replace
Delete Upload
with
Delete Upload

How to render data to a {% included a.html %} template in Django

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!
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.
I finally solved the issue by Creating custom context processor.https://www.youtube.com/watch?v=QTgkGBjjVYM

django get context from external app in main template

I have integrated djangocms blog in my project. In homepage sidebar i want to display latest blog posts. Problem is, my homepage is django-cms page and i can't get blog post objects. urls.py:
urlpatterns = i18n_patterns('',
url(r'^admin/', include(admin.site.urls)),
.....
url(r'djangocms_blog/', include('djangocms_blog.urls', namespace='djangocms_blog')),
url(r'^', include('cms.urls')),
)
Somehow here in main.html i should be able to get blog records:
{% extends "base.html" %}
<nav class="secondary-menu">
<ul class="nav">
<!-- i need display them here -->
</ul>
</nav>
Is there any elegant way to do this?
Use either an assignment_tag or an inclusion_tag:
Templatetag
# templatetags/blog_tags.py
from django import template
from djangocms_blog.models import Post
register = template.Library()
#register.assignment_tag()
def latest_posts_as(limit=5):
return Post.objects.order_by('-date_published')[0:limit]
#register.inclusion_tag('latest_posts.html', takes_context=True)
def latest_posts_inline(context, limit=5):
qs = Post.objects.order_by('-date_published')[0:limit]
context.update({'posts': qs})
return context
Snippet for inclusion tag
<!-- latest_posts.html -->
{% for post in posts %}
<p>{{ post }}</p>
{% endfor %}
Your home/whatever template
<!-- your_template.html -->
{% load blog_tags %}
<div>
<!-- using assignment_tag -->
{% latest_posts_as limit=20 as posts %}
{% for post in posts %}
<p>{{ post }}</p>
{% endfor %}
<!-- using inclusion_tag -->
{% latest_posts_inline limit=10 %}
</div>
The limit is optional - but could be handy :)
Came up with other solution. Created new django-cms plugin:
class BlogLatestEntriesPluginNav(BlogLatestEntriesPlugin):
name = _('Navigition latest blog entries')
render_template = 'latest_entries_nav.html'
plugin_pool.register_plugin(BlogLatestEntriesPluginNav)
where BlogLatestEntriesPlugin is plugin from djangocms_blog app. And created new template 'latest_entries_nav.html'. Then in main.html
<ul class="nav">
{% placeholder "left_sidebar" %}
</ul>
created placeholder and added that plugin.

django csrf error on HttpResponseRedirect

I know some people are going to think this is a duplicate, but I have spent all afternoon on Stack Overflow looking for the answer..
I have a page with a list of items, with, for each of them, a button which I would like to trigger a small update in the database. I don't know if this has any bearing, but the html file containing the button is included:
{% include "accueil/impasse.html" with l=l only %}
the file "impasse.html" itself is:
<a {% if l.impasse %} class="impasse" {% endif %} href="{% url "index" %}lecon/{{l.numero}}"> {{l.numero}} : {{l.titre}} </a>
{% if l.impasse %}
{% include "accueil/boutonDesImpasse.html" %}
{% else %}
{% include "accueil/boutonImpasse.html" %}
{% endif %}
and the file "accueil/boutonImpasse" which is the one that triggers the error is:
<form action="{% url "index" %}lecon/{{l.numero}}/impasse" method="post">
{% csrf_token %}
<div class="form-actions">
<button type="submit" class="btn btn-primary">Je fais l'impasse sur cette leçon</button>
</div>
</form>
The corresponding view is:
#login_required()
def impasse(request,numero):
id = numeroAId(numero)
if id==None:
return HttpResponse("Erreur, cette leçon n'existe pas.")
else:
imp = Impasse(user=request.user,lecon=id)
imp.save()
return HttpResponseRedirect('/lecon',context_instance=RequestContext(context))
Now, at this point, I have a CSRF error (in the else branch). I know that many people with the same type of error were advised to use render_to_response with the corresponding template, but I can't, because the view "lecon" associated with the url "lecon" does complicated things before throwing the page, so what I really want is to load the view "lecon". Note that after I get the error, if I try again the url that failed, it loads as wanted. What should I do?
This has nothing to do with render_to_response, or the redirect.
You are specifically excluding the csrf token variable from the context of the excluded templates by using "only" in the include tag. Don't do that.
(And HttpResponseRedirect doesn't take a context_instance parameter, so no idea what you are doing there.)

Categories