Add template variable into URL and satisfy reverse match - django

I found a way to inject variables into the URL per Django Template: Add Variable Into URL As Parameter, but my reverse match is not working. Do I need to use re-path and use regular expressions?
Current url.py
path('student/item/drilldown/<str:type>/<int:num>/',views.StudentBehaviorListView.as_view(),name='student_item_list_drilldown'),
Original w/hard-coding:
<a href="{%url 'registration:student_item_list_drilldown' type='grade' num=6%}">
With variable injection:
{{i.grade}}th Grade
Error message:
NoReverseMatch at /registration/dashboard/
Reverse for 'student_item_list_drilldown' with no arguments not found. 1 pattern(s) tried: ['registration/student/item/drilldown/(?P<type>[^/]+)/(?P<num>[0-9]+)/\\Z']

This:
{% url 'registration:student_item_list_drilldown' %}
Will try to find path named student_item_list_drilldown before it is read as html. That's why it tries (and fails) to find <str:type> and <int:num> in {% url 'registration:student_item_list_drilldown' %}. You have to include that variables inside {% url ... %} brackets.
The best approach would be that:
{% url 'registration:student_item_list_drilldown' 'grade' i.grade %}

Related

Django URL tag: Getting a NoReverseMatch on model id even though it exists

Really tiring issue today with Django templates. I've been successfully using URL tags with no issues for a while until today. I can't figure it out for the life of me. In the code below If I do a really ugly way of storing the url as a variable and then put it in an <a> element, I get no problems and it works as normal.
{% url 'app:post' post_id=recentpost.id as the_url %}
I'm linking to {{recentpost.id }} {{the_url}}
Rendered Output of above:
I'm linking to 18 /post/18/
(I did it this way to debug what was going on--I've never had to store the url as a variable and then insert it into an <a> before.)
Now if I do it normally in a single template tag--I get a NoReverseMatch Error:
TEST
django.urls.exceptions.NoReverseMatch: Reverse for 'post' with keyword arguments '{'post_id': ''}' not found. 1 pattern(s) tried: ['post\\\\/(?P<post_id>[0-9]+)\\\\/$']
What's irritating, is that there is an identical {% url %} tag further down the template resolving the same URL but with a different post model ID, the only difference is that the variable name is "post" rather than "recentpost"
It appears in the Exception that it's passing an empty variable to 'post_id' -- or that recentpost.id = "" -- If I just print the variable the id number shows up fine or if I store it as a variable first--it works fine.
I'm at a loss. Haaaaaaalp!
EDIT:
{# This doesn't work either with same error #}
{% url 'app:post' recentpost.id %}
Url path:
path('post/<int:post_id>/', views.post, name='post')
I'm using the same context variable immediately after the <a> tag and accessing variables successfully.
Here's the views.py:
def post(request, **kwargs):
blogpost = BlogPost.objects.get(pk=kwargs['post_id'])
#Make sure we don't populate our lists below with the current requested post
blogposts = BlogPost.objects.filter(project=None).exclude(id=kwargs['post_id']).order_by('-date_created')
recentposts = BlogPost.objects.exclude(id=kwargs['post_id']).order_by('-date_created')[:5]
blogposts = blogposts[0:10]
kwargs.update({'blogpost':blogpost})
kwargs.update({'blogpost_list':blogposts})
kwargs.update({'recentposts_list':recentposts})
return HttpResponse(render_to_response('public_frontend/blogpost.html', kwargs, RequestContext(request)))
def dev_index(request, **kwargs):
blogposts = BlogPost.objects.filter(project=None).order_by('-date_created')
recentpost = blogposts[0]
blogposts = blogposts[1:10]
kwargs.update({'recentpost':recentpost})
kwargs.update({'blogpost_list':blogposts})
return HttpResponse(render_to_response('public_frontend/dev_index.html', kwargs, RequestContext(request)))
dev_index is the view that goes to the template with the error.
blog view has zero issues when an int ID is passed as an argument and works as normal
This is the problem I've narrowed:
Reverse for 'post' with keyword arguments '{'post_id': ''}' not found
recentpost.id is coming up as a blank variable--when it's not.
Works here=> {% url 'app:post' post_id=recentpost.id as the_url %}
Doesn't work here=>{% url 'app:post' post_id=recentpost.id %}
=============================================================================
RECENT EDITS:
If I surround the same tag in an arbitrary for loop--it works as expected.
{{recentpost}} <!-- prints "BlogPost Object (15)"
{{recentpost.id}} <!-- prints 15
{% for test in recentpost.name %}
{% endfor %}
Output: (*n) number of characters in title
Also I get the exact same error for both these:
{% url 'app:post' post_id='' %}
{% url 'app:post' post_id=recentpost.id %}
And when placing it in a with block:
{{recentpost}} <!-- prints "BlogPost Object (15)"
{{recentpost.id}} <!-- prints 15
{% with test=recentpost%}
{% endwith %}
Output: NoReverseMatch Error -- Reverse for 'post' with keyword arguments '{'post_id': ''}' not found.
Also works if placed between an if tag:
{% if recentpost%} {% endif %} <!-- Works with no error and returns proper url
<!-- Does not work and returns a NoReverseMatch 404 because the `recentpost` variable is `None`
It's an accurate Error--it will return a 404 error or NoReverseMatch for the url /post/ --it will only return a url if it's /post/15/ -- or any integer.
The issue seems to be with the context variable recentpost It works in a {{recentpost}} print --but as soon as I use it in the url tag, it's None--as if the template hasn't loaded the Object in time to use it in an URL tag.
ADDITIONAL EVIDENCE:
Output: NoReverseMatch: Reverse for 'post' with keyword arguments '{'post_id': 'NONE'}' not found.
This is an expected error because /post/NONE/ will return a 404 error
The actual object is None or Null and defaults to a blank space--if I override the default with |default='NONE' we can see the problem is the variable not existing in the context within that URL tag
I also tried passing a context variable test_post='15' to the template from the view and have the exact same issue.
{{test_post}} <!-- output in template is 15
but
{% url 'app:post' post_id=test_post|default='NONE' %}
Output: NoReverseMatch: Reverse for 'post' with keyword arguments '{'post_id': 'NONE'}' not found.
Variable is definitely being passed to the template--much like the others but when --ANY-- variable is pushed into a {%url%} tag without being in a for or if block, it's None e.g. even if I do:
{% url 'app:post' post_id=blogposts.0.id %} it's None
but in blogposts's For loop, the items are not None and the {%url%} tag's work fine with that loop block.

Django - how to use a template tag within a url

I have a template tag named 'string_after' that I want to use within a URL. however I cant find anywhere what the syntax would be to use the tag within a URL?
I would use the tag as such
{% string_after type.site_type 'd' %}
which I tried to put inside the url but it is just seen as another url variable instead of the function
<li> %}">{{ type.site_type }}</li>
Does anybody know the correct syntax?
Thanks
You can't embed one tag inside another like that.
What you can do is save the output of one tag as a variable and then use it in the other:
{% string_after type.site_type 'd' as string_to_use %}
Then:
{% url 'sites:site_list' 'all' string_to_use %}
This assumes that string_after is a simple_tag.

How to replace re "." in Django template url tag

I have Django url routes that looks like this:
app_name = 'courses'
urlpatterns = [
url(r'./(?P<courseid>[0-9]+)/$', views.viewcourse, name='view_course'),
url(r'./(?P<courseid>[0-9]+)/review/$', views.reviewcourse, name='review_course')
]
The "." in the regular expression will usually be replaced by a slug, e.g.:
courses/computer-science/3/
Now I need a link in my 'view course' template to take the user to the review page, i.e:
courses/computer-science/3/review/
I could do this by simply appending review to the current url:
{{ request.path }}review
However, I would rather do it the 'correct' way using a template url tag
{% url 'courses:review_course' courseid=course.pk %}
However, this produces:
courses/30/review, which of course fails.
Is it possible to generate the correct link using the {% url %} tag without having to change the "." into a name capture parameter?
Change your urls.py :
url(r'(?P<course_type>[a-z_-]+)/(?P<courseid>[0-9]+)/$', views.viewcourse, name='view_course')
Now in your view you have access to course_type in your kwargs and you can then load whatever you want (as I have no code, i'm guessing what you're doing :)).
And in your template:
{% url 'courses:review_course' courseid=course.pk course_type=something%}

Could not parse the remainder: '/{{menu.Info.page}}' from ''item'/{{menu.Info.Page}}'

<img id="page" class="abc" src="{{STATIC_URL}}page/code_251.png" style=""/>
Hitting this url like localhost:8000/app/page works fine.
If I want something from views and append that pageid with url then showing error as Couldn't parse.
From views:{{page.pageid}}
output url should be :localhost:8000/app/?pageid=xx
for this i tried with below syntax:
<img id="page" class="abc" src="{{STATIC_URL}}page/code_251.png" style=""/>
But above syntax did't worked for me.
urls.py
url(r'^(page)(?:/(?P<page_id>[0-9]+))?/$',page_ViewDetails_TemplateView.as_view(),name="page"),
May be some changes need to be done on urls.py as well.
Can someone share some idea!!
You're confused about at least two things here.
Firstly, you would never use {{ }} inside a tag. You're already in the template language context there: you have access to variables directly.
Secondly, the {% url %} tag works on urlpattern names and parameters, not literal URLs. And your page URL does not expect a querystring value for page_id: it expects it as part of the path. Your generated URL needs to be "/page/3", not "/page?page_id=3".
So your URL tag is just:
<a href="{% url 'page' page_id=page.pageid %}">

Using date in the Django url templatetag

I am trying to build a date-based URL with Django's url template tag. I have a datetime object that I can display like so:
{{block|date:"F j Y"}}
However, when I use nearly the same syntax with the url templatetag, like so:
{% url meeting block|date:"Y" %}
I get an error -- it appears that the only thing passed to url is an empty string:
... Reverse for 'meeting' with arguments '(u'',)' and arguments ...
What might I be doing wrong?
The url tag is a bit strange, and is very picky about its arguments. In particular, I don't think it evaluates any filters in its arguments.
You could try this:
{% with block|date:"Y" as blockyear %}{% url meeting blockyear %}{% endwith %}