I'm trying to use this app in my project: https://github.com/s1n4/django-favorite
but it has old url syntax and I did not understand how to transform it to new url syntax.
The url that I wanna transform:
{% url favorite.views.add_or_remove target_model target_object_id %}
Its exact form in html:
<button class="btn favorite" href="{% url 'favorite.views.add_or_remove' %}" model="{{ target_model }}" id="target_{{ target_object_id }}">
I know the syntax has changed with Django 1.5 and I tried to use this version:
{% url 'favorite.views.add_or_remove' target_model target_object_id %}
It also did not work.
It says:
Reverse for 'favorite.views.add_or_remove' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
How can I fix this? Thanks.
Edit:
Its template tag can help to understand:
#register.simple_tag(takes_context=True)
def favorite_button(context, target):
user = context['request'].user
# do nothing when user isn't authenticated
if not user.is_authenticated():
return ''
target_model = '.'.join((target._meta.app_label, target._meta.object_name))
target_content_type = ContentType.objects.get_for_model(target)
target_object_id = target.id
fav_count = Favorite.objects.filter(target_content_type=target_content_type,
target_object_id=target_object_id).count()
undo = False
if user.favorite_set.filter(target_content_type=target_content_type,
target_object_id=target_object_id):
undo = True
return render_to_string('favorite/button.html',
{'target_model': target_model, 'target_object_id': target_object_id,
'fav_count': fav_count, 'undo': undo})
Since that application is in use in production (in which we used Django 1.4) I cannot patch the application to make it compatible with Django 1.5+. But there is a pull-request that I kept open for such a situation. Here it is: https://github.com/s1n4/django-favorite/pull/1 It might solve the problem.
The URL has no arguments:
url(r'^add-or-remove$', 'add_or_remove'),
and neither does that view:
def add_or_remove(request):
The URL tag in the HTML there also has no arguments:
{% url favorite.views.add_or_remove %}
To convert that to the new syntax it would be:
{% url 'favorite.views.add_or_remove' %}
After that you can use the template tag as described in the README:
{% load favorite_tags %}
{% for comment in post.comments %}
{% favorite_button comment %}
{% endfor %}
Related
As I said in the title, what would be the correct syntax to change the href of a link according to the current url the user is on?
I tried this, but it doesn't work.
{% if url == '' %} href='/cookies' {% else %} href='' {% endif %}
What would be the correct syntax to do this?
At Django 1.9 and above can use something like this
href='{% if not request.path %}/cookies{% endif %}'
You can check the current url with
href="{% if request.path == '' %}/cookies{% endif %}"
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
I'm trying to figure out if there is a way to extend a partial view into a view that already extends base.html.
Here is an example of what I'm trying to do:
my-template.html
{% extends 'base.html '%}
<div class="row">
<div class="col-xs-12">
<ul class="nav nav-tabs">
<li role="presentation" class="active">Tab1</li>
<li role="presentation">Tab2</li>
</ul>
</div>
</div>
<div>
{% block tab_content %}
{% endblock %}
</div>
partial1.html
{% extends 'my-template.html' %}
{% block tab_content %}
<h1>I'm partial 1</h1>
{% endblock %}
The my-template.html view has a url that is constructed like so:
url(r'^my-template/(?P<id>[0-9]+)/$', views.my_template_view, name='my-template')
in addition a context dict is passed into the my_template_view providing the id for the url.
I would like the for the user to click on a tab and for its corresponding partial to be rendered with a url like so:
url(r'^my-template/(?P<id>[0-9]+)/tab1/$', views.tab1_view, name='tab1-view')
but right now I'm getting a NoReverseMatch at /my-template/97/tab1/ which I'm assuming means that my tab1_view doesn't have access to the same context as the my_template_view and thus can't get the id to build the reverse of my url.
In template /partial1.html, error at line 0
Reverse for 'tab1_view' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['/my-template/(?P<id>[0-9]+)/tab1/$']
So, is there a way for me, at the very least, to pass along the context or the id so this works, or am i going about this in the entirely wrong way?
The typical way to solve this is by using the include template tag, not by extending with a new template.
Here is the Django doc describing this.
You can even use a variable to define a dynamic template name that will be included based on logic in your view.
Little more clarification here:
You can also have the URL route direct to the same view and have the "tab" optionally passed in as a second parameter as so:
url(r'^my-template/(?P<id>[0-9]+)/(?P<tab_name>\w+)/$', views.my_template_view, name='my-template')
url(r'^my-template/(?P<id>[0-9]+)/$', views.my_template_view, name='my-template')
And your view would look something like:
def my_template_view(request, id, tab_name=None):
if not tab_name:
tab_name = "tab1"
if tab_name == "tab1":
partial = "tab1.django.html"
elif tab_name == "tab2":
partial = "tab2.django.html"
return render("my-template.html", { 'partial': partial })
And on your template you would have:
{% include partial %}
Because the included template will have the same context, you will have access to any variables that were available in the original context as well.
EDIT 2020/09/04: As noted in a comment below, the above page no longer exists. I've updated the above link to the latest in the 1.11 branch, but for the latest version of Django (3.1 as of this edit) you can refer to the same doc here.
I've 2 urls pointing to the same place:
url(r'^index/$', 'proj.views.index'),
url(r'^index/show_closed/$', 'proj.views.index'),
If I use in a template file this:
{% url proj.views.index %}
it' ll return /index/show_closed
and this is OK, but how can i make {% url %} to return only /index ?
Use named patterns; giving your pattern a unique name:
url(r'^index/$', 'proj.views.index', name='index_direct'),
url(r'^index/show_closed/$', 'proj.views.index', name='index_closed'),
then refer to those names in the {% url %} tag instead of the view:
{% url 'index_direct' %}
{% url 'index_closed' %}
I want to have SEO-friendly URL,my current url in urls.py :
(ur'^company/news/(?P<news_title>.*)/(?P<news_id>\d+)/$','CompanyHub.views.getNews')
I use it in template:
{% for n in news %}
<a href="{% url CompanyHub.views.getNews n.title,n.pk %}" >{{n.description}}</a>
{% endfor %}
I use news_id to get news object with that PK .
I want to convert this url:
../company/news/tile of news,with comma/11
to:
../company/news/tile-of-news-with-comma/11
by doing some thing like this in template:
{% for n in news %}
<a href="{% url CompanyHub.views.getNews slugify(n.title),n.pk %}" >{{n.description}}</a>
{% endfor %}
I checked out these questions:
question1
question2
question3 and this article but they save an slugify field in database while I wanna generate it on demand.in addition I want to run a query by news_id.
I think this question is good,but I don't know how to use news_id to fetch my news object
This will generate the needed url:
{% for n in news %}
<a href="{% url CompanyHub.views.getNews n.title|slugify n.pk %}" >{{n.description}}</a>
{% endfor %}
The examples above save slugify_field in database, as they later search for it. Otherwise in database you'll have a normal title, and slugified title in code for searching.. No easy way to compare them. But the way you've explained is simpler. You will have this kind of view:
def news(request, slug, news_id):
news = News.objects.filter(pk=news_id)
UPDATE: To use unicode symbols in slugify, you'll need a conversion first. Look at this: How to make Django slugify work properly with Unicode strings?. It uses the Unidecode library
Then add a custom filter:
from unidecode import unidecode
from django.template.defaultfilters import slugify
def slug(value):
return slugify(unidecode(value))
register.filter('slug', slug)
then in your template use this:
{% load mytags %}
<a href="{% url CompanyHub.views.getNews n.title|slug n.pk %}
Here is an example:
{{ "影師嗎 1 2 3"|slug}}
renders as:
ying-shi-ma-1-2-3
Have you tried n.title|slugify and see if that works for you.
ref: https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#slugify
Note: although this is possible, just make sure the 'slugified' element is never used for any part of routing... (ie, purely for display only)