Django: Refer to an url name in a template and passing parameter - django

I know you can refer to a urlname in a template so that you don't need to hardcode your url links in your templates whenever you want to change them.
For example in a template, I use:
The link
My problem is, if I want to pass a more complex parameter to be used in the url regex. In my case, I want to pass a concatenation of two strings separated by an "_". Those strings come from Python objects and I don't get how to do that. Let's say for example, those strings are the firstname and lastname of a user.
I tried:
The link
And others tricks but none worked.
Can someone help?

Simply, you don't.
You either adjust your url to have two capture groups (which would also require a slight change to the view)
url(r'(?P<first_name>\w+)_(?P<last_name>\w+)/$', view_name, name='url_name')
{% url 'urlname' user.firstname user.lastname %}
Or you just find a different url that suffices.

Please have a look at this thread. The good answer for you, assuming you're using posititionnal arguments :
The link
Assuming your url conf is like so :
url(r'^urlname/(?P<parameter>(catching regexp))$',...)

Related

Jinja Expression In Statement

I am wanting to include dynamic variables inside of an if statement.
{% elif request.path == "/order/**{{city}}**" %}
I have a database I can refer to, to get the city names I need out depending on the url but am having a hard time sending that info in through this if statement.
(Everything works dynamically up until this point)
Solutions?
Backtrack a bit and just make the condition in the views.py then pass a boolean in the context which saves you the trouble of this complicated notation which contains far too many special symbols to be worth the headache
In the views.py
city = City.objects.get(city_slug=city_slug)
my_city = "https://www.wesbsite.com/order/{}".format(city)
was my solution to including dynamic variables in the url
found at
How to add variable to URL?
I overcomplicated it but Blye pointed in the right direction, telling me to do so in the views.py as opposed to directly in the html file.

Django pass known exact string as a url parameter

I have two urls in dispatcher pointing the same view
path('posts/top/', posts, name='top'),
path('posts/new/', posts, name='new'),
I want view start as follows:
def posts(request, ordering):
...
I guess, to pass top and new as a parameter it should be something like:
path('posts/<ordering:top>/', posts, name='top'),
path('posts/<ordering:new>/', posts, name='new'),
But it gives me:
django.core.exceptions.ImproperlyConfigured: URL route 'posts/<ordering:top>/' uses invalid converter 'ordering'.
So, as a work around I use this, but it looks a little bit dirty:
path('posts/top/', posts, name='top', kwargs={'order': 'top'}),
path('posts/new/', posts, name='new', kwargs={'order': 'top'}),
What is the right way to do it?
You've misunderstood the way path converters work. The first element is the type, which here is str, and the second is the parameter name to use when calling the view. At this point you don't constrain the permissible values themselves. So your path would be:
path('posts/<str:ordering>/', posts, name='posts')
and when you come to reverse you would pass in the relevant parameter:
{% url 'posts' ordering='top' %}
If you really want to ensure that people can only pass those two values, you can either check it programmatically in the view, or you can use re_path to use regex in your path:
re_path(r'^posts/(?P<ordering>top|new)/$', posts, name='posts')

How to create a WordPress like URL naming convention in Django?

I'm a newbie in Django and in WordPress if you create a Post called "hello world" then the URL by default will be like
wordpress.com/2012/07/05/hello-world/
and if you create another post with the same name it will be
wordpress.com/2012/07/05/hello-world-2/
I want to achieve the same in Django and I was thinking to create a sample urlconf like this
(r'^articles/(\d{4})/(\d{2})/(?P<name>\w+)', 'article.views.article_detail')
and in the views break down the name and iterate through all the items and match the name.
But the problem with will be that I won't be able to reference posts dynamically. For e.g. if I was to link the a hello world post I would need to find out how many posts with the same name exist already and then append the additional number to it which is inefficient.
So what's the best way to do this in Django?
See the documentation for Django's {{ url }} template tag. It lets you pass it a view name and parameters, and automatically generates the correct URL for you.
You can take care of appending numbers to each post's name in the function that generates its slug - you could have a look at django-autoslug

Django Generic object_list pagination. Adding instead of replacing arguments

I'm having some trouble with the django generic object_list function's pagination not really being "smart" enough to compensate my daftness.
I'm trying to do a url for listing with optional arguments for page number and category.
The url in urls.py looks like this:
url(r'^all/(?:(?P<category>[-\w]+)/page-(?P<urlpage>\d+))?/$',
views.listing,
),
The category and urlpage arguments are optional beacuse of the extra "(?: )?" around them and that works nicely.
views.listing is a wrapper function looking like this( i don't think this is where my problem occurs):
def listing(request,category="a-z",urlpage="1"):
extra_context_dict={}
if category=="a-z":
catqueryset=models.UserProfile.objects.all().order_by('user__username')
elif category=="z-a":
catqueryset=models.UserProfile.objects.all().order_by(-'user__username')
else:
extra_context_dict['error_message']='Unfortunately a sorting error occurred, content is listed in alphabetical order'
catqueryset=models.UserProfile.objects.all().order_by('user__username')
return object_list(
request,
queryset=catqueryset,
template_name='userlist.html',
page=urlpage,
paginate_by=10,
extra_context=extra_context_dict,
)
In my template userlist.html I have links looking like this (This is where I think the real problem lies):
{%if has_next%}
<a href=page-{{next}}>Next Page> ({{next}})</a>
{%else%}
Instead of replacing the page argument in my url the link adds another page argument to the url. The urls ends up looking like this "/all/a-z/page-1/page-2/
It's not really surprising that this is what happens, but not having page as an optional argument actually works and Django replaces the old page-part of the url.
I would prefer this DRYer (atleast I think so) solution, but can't seem to get it working.
Any tips how this could be solved with better urls.py or template tags would be very appreciated.
(also please excuse non-native english and on the fly translated code. Any feedback as to if this is a good or unwarranted Stack-overflow question is also gladly taken)
You're using relative URLs here - so it's not really anything to do with Django. You could replace your link with:
Next Page> ({{ next }})
and all would be well, except for the fact that you'd have a brittle link in your template, which would break as soon as you changed your urls.py, and it wouldn't work unless category happened to be a-z.
Instead, use Django's built-in url tag.
Next Page> ({{ next }})
To make that work, you'll have to pass your category into the extra_context_dict, which you create on the first line of your view code:
extra_context_dict = { 'category': category }
Is /all/a-z/page-1/page-2/ what appears in the source or where the link takes you to? My guess is that the string "page-2" is appended by the browser to the current URL. You should start with a URL with / in order to state a full path.
You should probably add the category into the extra_context and do:
next page ({{next}})
"Instead of replacing the page argument in my url the link adds another page argument to the url. The urls ends up looking like this "/all/a-z/page-1/page-2/"
that is because
'<a href=page-{{next}}>Next Page> ({{next}})</a>'
links to the page relative to the current url and the current url is already having /page-1/ in it.
i'm not sure how, not having page as an optional argument actually works and Django replaces the old page-part of the url
one thing i suggest is instead of defining relative url define absolute url
'Next Page> ({{ next }})'

View referenced by two urls and url tag

I am using url tag in my template for a view, that is used by two different urls. I am getting the wrong url in one place. Is there any way to force django to retrieve different url? Why it doesn't notify my, that such conflict occured and it doesn't know what to do (since python zen says, that is should refuse temptation to guess).
Code in template:
{% url djangoldap.views.FilterEntriesResponse Entry=entry.path as filter_url %}
Code in urls:
(r'^filter_entries/(?P<Entry>.*)/$',
'djangoldap.views.FilterEntriesResponse',
{'filter_template': 'filter_entries.html',
'results_template': 'filter_results.html'}),
(r'^choose_entries/(?P<Entry>.*)/$',
'djangoldap.views.FilterEntriesResponse',
{'filter_template': 'search_entries.html',
'results_template': 'search_results.html'}),
As you can see, those two urls use the same view, but with different templates. How I can force django to retrieve former url, rather than latter?
Name your URLs by adding another item to the tuple:
(r'^choose_entries/(?P<Entry>.*)/$',
'djangoldap.views.FilterEntriesResponse',
{'filter_template': 'search_entries.html',
'results_template': 'search_results.html'},
'sensibleprefix-choose_entries') # <-- this is the name
Then you can use the name in the URL tag.