Django template {%url %} link formatting - python

When I use {% url %} method to create link
{% url application_name:staff:url.linkfield %}
it is producing error in the console i.e.
raise TemplateSyntaxError("Could not parse the remainder: '%s' "
django.template.exceptions.TemplateSyntaxError: Could not parse the remainder: ':staff:url.linkfield' from 'application_name:staff:url.linkfield'
This is my url.py
app_name="application_name"
urlpatterns=[
url(r"^staff/",include('application_name.staff_url', namespace='staff')),
url(r"^customer/",include('application_name.customer_url', namespace='customer')),
]
my staff_url.py
from application_name import views
app_name="staff"
urlpatterns=[
url(r"^customers/",views.customers, name='customers'),
url(r"^orders/$", views.orders, name='orders'),
url(r"^payments/$", views.payments, name='payments'),
]
my customer_url.py
from application_name import views
app_name="customer"
urlpatterns=[
url(r"^items/",views.items, name='items'),
url(r"^checkout/$", views.checkout, name='checkout'),
url(r"^make_payment/$", views.make_payment, name='make_payment'),
]
staf url would be staff/orders or staff/payments
customer urls would be customer/items or customer/checkout etc
Please what can i do
Update
{% for url in links %}
{% url.linkfield %}
{%endfor%}
That is what url.linkfield is for
Update to include view
View
staffLink=[
{'linkfield':"customers", 'name':"Customers",'slug':"staff"},
{'linkfield':"orders", 'name':"Orders",'slug':"staff"},
{'linkfield':"payments", 'name':"payments",'slug':"staff"}]
links=staffLink
request.session['links']= links
context_dict = {'links':links}
html template
{% for link in request.session.links %}
<a href="{% url application_name:staff: link.linkfield as the_url %}" class="nav-link">
{% endif %}

so this is your main url:
urlpatterns=[
url(r"^staff/",include('application_name.staff_url', namespace='staff')),
url(r"^customer/",include('application_name.customer_url', namespace='customer')),
]
you do not need an app_name for the main url.
to rewrite:
{% url application_name:staff:url.linkfield %}
would be
{% url 'staff:customers' %} or
{% url 'staff:orders' %} or
{% url 'staff:payments' %}
or the other urls
{% url 'staff:customers' %} or
{% url 'customer:checkout' %} or
{% url 'customer:make_payment' %}
if links is a result of a queryset, and you use it as context,
and linkfield is a field of that model you used to query, then
{% for url in links %}
{{ url.linkfield }}
{%endfor%}

Try please this syntax
{% url 'some-url-name' arg arg2 as the_url %}

Related

Django can't find the URL pattern

I'm new to Django and I'm making wiki website based on markdown. I am having one problem. Django can't match the path in html to urls.py. It happens when I try to open wiki entries. It gives me the following error. I have already passed the parameter to 'page', I honestly have no idea what to do.
Using the URLconf defined in wiki.urls, Django tried these URL patterns, in this order:
admin/
[name='index']
wiki/<str:page> [name='page']
search [name='search']
create [name='create']
addentry [name='add_entry']
nomatches [name='nomatches']
results [name='results']
edit/<str:page> [name='edit']
random [name='random']
The current path, { url 'page' entry }, didn't match any of these.
Please, tell me how can I fix this.
index. html:
{% extends "encyclopedia/layout.html" %}
{% block title %}
Encyclopedia
{% endblock %}
{% block body %}
<h1>All Pages</h1>
<ul>
{% for entry in entries %}
<li>{{ entry }}</li>
{% endfor %}
</ul>
{% endblock %}
urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("wiki/<str:page>", views.viewpage, name="page"),
path("search", views.search, name="search"),
path("create", views.create, name="create"),
path("addentry", views.add_entry, name="add_entry"),
path("nomatches", views.search, name="nomatches"),
path("results", views.search, name="results"),
path("edit/<str:page>", views.edit, name="edit"),
path("random", views.random, name="random")
]
part of views.py:
def index(request):
return render(request, "encyclopedia/index.html", {
"entries": util.list_entries()
})
def viewpage(request, page):
content = util.get_entry(page)
return render(request, "encyclopedia/page.html", {
"content": markdown2.markdown(content),
"title":page
})
page.html
{% extends "encyclopedia/layout.html" %}
{% block title %}
{{ title }}
{% endblock %}
{% block body %}
edit
<h1>{{ title }}</h1>
{{ content|safe }}
{% endblock %}
Since the URL for 'page' is 'wiki/<str: page>' you need to define a get_absolute_url method on your class model that contains the object in question, so do add this method in the models.py class that contains page:
def get_absolute_url(self):
return reverse('page',kwargs={str:self.str})
Then, in the template, you can refer to it as
{% object.get_absolute_url%}.

Django - template not being detected

I'm using this library to handle two factor auth for a django project, but i'm having some troubles: in my site, i added a setup.html page, i set the url on my urls.py file but i keep getting this error:
In template C:\Users\Us\lib\site-packages\allauth\templates\base.html, error at line 26
Reverse for 'account_email' not found. 'account_email' is not a valid view function or pattern name.
<li>Change E-mail</li>
Which is completely weird because i'm not trying to load a file called base.html but my own setup.html file, which is located in my project's folder (the path is project-folder>templates>setup.html). This is the setup.html that i would like to load from my own templates:
{% extends 'main/header.html' %}
{% load i18n %}
{% block content %}
<h1>
{% trans "Setup Two-Factor Authentication" %}
</h1>
<h4>
{% trans 'Step 1' %}:
</h4>
<p>
{% trans 'Scan the QR code below with a token generator of your choice (for instance Google Authenticator).' %}
</p>
<img src="{{ qr_code_url }}" />
<h4>
{% trans 'Step 2' %}:
</h4>
<p>
{% trans 'Input a token generated by the app:' %}
</p>
<form method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.token.label }}: {{ form.token }}
<button type="submit">
{% trans 'Verify' %}
</button>
</form>
{% endblock %}
It looks like the module that i'm using, instead of loading MY setup.html will load something else, but i can't find a way to fix this.
Here is the view that i'm calling to handle the setup (it' the module's view):
https://github.com/percipient/django-allauth-2fa/blob/master/allauth_2fa/views.py
And here is my own urls.py, where the view that i mentioned is being called:
from django.urls import path
from . import views
from django.conf.urls import url, include
from django.conf.urls import url
from allauth_2fa import views as allauth_2fa_views
app_name = "main"
urlpatterns = [
path("setup/", allauth_2fa_views.TwoFactorSetup.as_view(), name="setup"),
path("", views.homepage, name="homepage"),
path("register/", views.register, name="register"),
path("logout/", views.logout_request, name="logout"),
path("login/", views.login_request, name="login"),
]
The TwoFactorSetup view is using a template setup.html in a folder allauth_2fa. So all you need to do is place your setup.html inside a folder with the same name: app_folder/templates/allauth_2fa/setup.html to override it.
Alternatively, subclass TwoFactorSetup and just change the template_name attribute to point to your template and use that view in your urls.py:
from allauth_2fa.views import TwoFactorSetup
class MySetup(TwoFactorSetup):
template_name = 'my_app/setup.html'

Clean url in django app. without ?page=1 pattern

I want to have my url pattern like the below pattern:
host:8000/archive/2/
I define page_kwarg in my view but I still receive: host:8000/en/2
Code form main url.py file:
url(_(r'^archive'), include('events.urls_archive', namespace='archive')),
start edit1
and link form main site to my app:
<a href="{% url 'archive:list' %}" title="{% trans 'Archive' %}">
{% trans 'Archive' %}
</a>
end edit1
start edit2
This is the url in my app urls_archive.py:
urlpatterns = [
url('^/(?P<page>\d+)/$', ArchiveListView.as_view(), name="list"),
url('^/(?P<slug>[-\w]+)/(?P<pk>\d+)$', ArchiveDetailView.as_view(), name="detail"),
]
end edit2
The code for my view:
class ArchiveListView(ListView):
model = Booking
queryset = Booking.objects.filter(period__type='archive').order_by('-date_start')
paginate_by = 80
page_kwarg = 'page'
Here is my template code:
{% if is_paginated %}
{% if page_obj.has_previous %}
<h4>Previous</h4>
{% endif %}
<span class="arrow header"><h4>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</h4></span>
{% if page_obj.has_next %}
<h4>Next</h4>
{% endif %}
{% endif %}
Please provide any help.
Thanks.
page_kwarg sets the key that the page number is passed in as. It doesn't affect how it is used in the page. For some reason, you are outputting that directly as /{{ page_obj.previous_page_number }}, which resolves to just /2. You should output it in the same format as it is passed in:
?page={{ page_obj.previous_page_number}}
Edit
If you want your page number to be specified as part of the path arguments, you should use the url tag, like any other URL:
{% url 'archive' page=page_obj.previous_page_number %}

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 template multiple url return

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' %}

Categories