How does {% load url from future %} and namespaces work in Django? - python

Can someone show me an example (plus a small explanation) of how {% load url from future %} and namespace concept works?
I'm new in python and django and i need to learn how not to make hardcoded urls and also how to use other functions like reverse().
Here is an example of what i'm trying to do:
urls.py
urlpatterns = patterns('',
"""
This one is what i did first but works with hardcoded url inside
top-navigator.html:
url(r'^books/$', 'books.views.book_index'),
The next one is what i'm trying to do:
(but of course is not correct)
"""
url(r'^books/$', include('books.views.book_index', namespace='books')),
)
top-navigator.html
when i'm trying to run the server is shows the error:
Caught ImportError while rendering: No module named book_index
{% load url from future %}
<div class="navbar-inner">
<ul class="nav">
<li class="active">Home</li>
<li>Books</li>
<li>Authors</li>
<li>Publishers</li>
<li>Contact</li>
</ul>
</div>
What can i do in order do to something similar for all the links?
Thanks in advance.

To use namespaces and the include statement, you must import another urls.py file with patterns in it.
You can't just include a view as you've done here.
Change your code to
{% url 'book_index' %}"
url(r'^books/$', 'books.views.book_index', name='books'))
Or to use namespaces for illustration purposes:
more_patterns = patterns('',
url(r'^$', 'book.views.book_index', name='book_index')),
)
urlpatterns = patterns('',
url(r'^books/', include(more_patterns, namespace='books')),
#^^^^^^^ note you would normally use a string that points
# to a python file containing urls.
)
{% url 'books:book_index' %} will now resolve.

Related

The usage of {% url ...%} vs {{ ... }} in Django templates

I've been practicing Djnago and for that, I was building a blog. While in the process of building it, I was faced with an error, while using the following code:
<a href="{% url 'blog_post' post.slug %}">
{{ post.title }}
</a>
While studying and doing other courses something like this would work fine. But now, it will raise this exception: NoReverseMatch.
If I use this code though, it will work just fine:
<a href="{{ post.slug }}">
{{ post.title }}
</a>
While working in different projects the first way would work fine, but this time, it doesn't.
My question is why?
Here is the code in my urls and on my views. Maybe the mistake is here, not somewhere else.
If anyone can explain why this is happening, or where I'm going wrong, it will be greatly appreciated
urls:
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.blog_index, name='blog_index'),
path('<slug:post_slug>/', views.blog_post, name='blog_post'),
]
views:
from django.shortcuts import render
from .models import Post
# Create your views here.
def blog_index(request):
posts = Post.objects.order_by('-
created').filter(published=True)
data = {
'posts': posts
}
return render(request, 'blog/post_list.html', data)
def blog_post(request, post_slug):
post = Post.objects.get(slug=post_slug)
data = {
'post': post
}
return render(request, 'blog/post_detail.html', data)
try this.your problem is that you have a namespace in your urls.py then in your href you should add that namespace('blog').
<a href="{% url 'blog:blog_post' post.slug %}">
{{ post.title }}
</a>
this
<a href="{{ post.slug }}">
{{ post.title }}
</a>
this code above was working because you are located inside the home page and when you add this(href="{{ post.slug }}" in the a tag) it will just call the current url +"/<'slug:post_slug/' and this is a valid url.but this is a very bad option.use the the first option.
to learn about this refer to this https://docs.djangoproject.com/en/3.2/topics/http/urls/#url-namespaces.
In such cases, you should use:
https://docs.djangoproject.com/en/3.2/ref/models/instances/#get-absolute-url
The less logic in the templates, the better for the application.
It is difficult to write tests on logic that is contained in templates.
You should add a method to your model:
from django.urls import reverse
class Post()
...
def get_absolute_url(self):
return reverse('blog:blog_post', kwargs={'post_slug' : self.slug})
In the reverse function you need to add an application namespace.
In your case, it's a blog.
https://docs.djangoproject.com/en/3.2/topics/http/urls/#introduction
and then in template use:
{{ post.get_absolute_url }}
From documentation:
The logic here is that if you change the URL structure of your objects, even for something small like correcting a spelling error, you don’t want to have to track down every place that the URL might be created. Specify it once, in get_absolute_url() and have all your other code call that one place.

Django context variable in the navigation bar - correct href assignment?

What is the correct assignment of context variables in the navigation bar? My Django example is:
in view.py:
from django.shortcuts import render
from django.http import HttpResponse
context_navigation = {
'Link1' : 'Blog',
'href1' : "{% url 'blog' %}", }
def index(request):
return render(request, 'app_about/index.html', context=context_navigation)
in urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.index, name='blog'),
]
in templates/base.html this does work
<a class="nav-item nav-link text-light" href="{% url 'blog' %}" > {{Link1}}</a>
this does not work (see href1 and Link1)
<a class="nav-item nav-link text-light" href="{{href1}}" > {{Link1}}</a>
In the last case a wrong url is generated, something like http://127.0.0.1:8000/blog/%7B%.
What is the correct assignment of href as a context variable href1 ? Thank you for some hints!
In the second example you insert a variable href1, which is replaced by the content (the string) {% url 'blog %} when rendered. Django trys to render this string (makes it html safe, thats where the %7B.. came from, which is just the html code for {.
Option 1: resolve url in the view
You can either resolve the url using python in the view and pass the actual url as string to the template:
views.py
from django.urls import reverse
context_navigation = {
'Link1' : 'Blog',
'href1' : reverse('blog')
}
base.html
<a class="nav-item nav-link text-light" href="{{href1}}">{{Link1}}</a>
Option 2: resolve url in the template
Or you go with the first example, where {% url 'blog %} will be interpreted and executed by the template rendering engine:
context_navigation = {
'Link1' : 'Blog'
}
base.html
<a class="nav-item nav-link text-light" href="{% url 'blog' %}">{{Link1}}</a>
Option3: view passes url (name) and template resolves it (not tested)
If you need to generate the context dynamically but want to resolve the actual urls in the template you can maybe pass the url name as variable like:
context_navigation = {
'Link1': 'Blog',
'url1': 'blog',
}
base.html
<a class="nav-item nav-link text-light" href="{% url url1 %}">{{Link1}}</a>
But I'm not sure if you can use varaibles in template tags like this (just a guess, never used it this way)
Thank you for the answer #sarbot! Let's give me my experiences with them.
Option 1 looks pretty lean and is in accordance with the django manual, so I would prefer it as the solution. Unfortunately I have to struggle with the fact that runserver does not like this approach and generates a fatal Python error. For the time beeing I do not have an explanation for that.
Option 2 is the option I started with and it works. For a clean programming style I prefere not to stay with it.
Option 3 works for me, so I do not have to say more than thank you :-)

What does href="{% url 'profile' %} mean?

Update 2
I think my confusion came because I did not account for the fact that my project django_project3 is the default project.
Update
I looked at Using {% url ??? %} in django templates but it didn't fully answer my question.
Original Post
I tried to Google my question but ended up with 1000s of pages of Python theory and no straight answer.
I have a project called Blog and in it there is a file called base.html. And it contains the line of code <a class="nav-item nav-link" href="{% url 'profile' %}">Home</a>.
But in Blogs urls.py file there is no URL pattern called profile.
Whereas in my project django_project3, in the urls.py file there is a URL pattern called profile.
Does the percentage sign get the code to look in every urls.py file?
url is a built-in template tag to avoid hard-coding.
{% %} is template render syntax

Django dynamic links

I'm new to Django so this could be a stupid question, however I'm struggling to find an answer searching Goolge. my question is as follows...
In other languages when creating links within HTML pages you have something like a buildURL(page) function that creates a dynamic link i.e.
<a herf="buildURL(pageName,queryObjects) >link</a>
This would generate the URL with parameters.
Is there a function in Django that builds URLs in the correct format i.e. generate a fully-qualified URL to a Django page with parameters?
In your templates, you never should hard write url view. Instead of this, a good practice is to named each url and reference this name in templates.
To name a url:
from django.conf.urls import patterns, url
urlpatterns = patterns('',
#...
url(r'^article/(\d+)/$', 'news.views.article', name='article_by_id'),
#...
)
To reference url in template:
<ul>
{% for article in articles %}
<li>Article {{article.name}} </li>
{% endfor %}
</ul>
Learn more in URL Distpatchar django documentation.
from what I see in the django documentation it should be
<ul>
{% for article in articles %}
<li>Article {{article.name}} </li>
{% endfor %}
</ul>
i.e. 'article_by_id' instead of article_by_id. This works for me

How does one put a link / url to the web-site's home page in Django?

In Django templates, is there a variable in the context (e.g. {{ BASE\_URL }}, {{ ROOT\_URL }}, or {{ MEDIA\_URL }} that one can use to link to the home url of a project?
I.e. if Django is running in the root of a project, the variable (let's call it R) {{ R }} in a template would be /. If the root url is a sub-folder http://host/X/ the variable {{ R }} would be /X/ (or http://host/X/).
It seems painfully simple, but I can't find an answer. :) Thank you!
You could give the URL configuration which you're using to handle the home page a name and use that:
urls.py:
from django.conf.urls.defaults import *
urlpatterns = patterns('myproject.views',
url(r'^$', 'index', name='index'),
)
Templates:
<a href="{% url index %}">...
UPDATE: Newer versions of Django require quotation marks around the name of the view:
<a href="{% url 'index' %}">...
This note in the Django Book has some tips about deploying your applications to a subdirectory:
http://www.djangobook.com/en/1.0/chapter20/#cn43
I always use something like <a href="/"> (assuming your home is at the root, of course). I seem to recall looking this up once, and couldn't find a Django variable for this path; at any rate, / seemed pretty easy, anyway.
In your admin, go to "sites" and set the domain.
Pass context_instance=RequestContext(request) to the templates in question.
Now use {{ SITE_URL }} in any of those templates and you're golden.
Chapter 10 of the Django Book has more information than you'll need regading that context processor bit.
(r'^$', 'django.views.generic.simple.redirect_to', {'url': '/home/'}),
works fine :)

Categories