Django url get request with parameter - django

I have following HTML file
<!DOCTYPE html>
<body>
{% for champion in champions %}
{{champion}}
{% endfor %}
</body>
</html>
And these are my URLS
urlpatterns = patterns('', url(r'^select_champion/$', views.select_champion, name='select_champion'),
url(r'^guide_form/(?P<champion>\w+)/$', views.guide_form, name='guide_form'),
url(r'^create_guide/$', views.create_guide, name='create_guide'),
url(r'^get_guide/(?P<id>\d+)/$', views.get_guide, name='get_guide'),
url(r'^guide_list/(?P<champion>\w+)/$', views.get_guide_list, name='get_guide_list'),
)
When I try to select a champion I get following Error:
Reverse for 'guide_form' with arguments '()' and keyword arguments
'{}' not found. 1 pattern(s) tried:
['guides/guide_form/(?P\w+)/$']
When I change this line
{{champion}}
To this
{{champion}}
I don't get an Error but the wrong URL is called of course. I want to select a champion and want the champ to be delivered per url so a guide can be written about him in the guide form.
Do you have any suggestion on how to solve my problem?

Almost there, you need:
{{ champion }}
Your url pattern has a keyword argument champion, and the value is the template variable {{ champion }}. The url tag understands the template context, so you don't need {{ }} around the variable; instead pass it in directly as an argument to the url tag.

It should be like this
<!DOCTYPE html>
<body>
{% for champion in champions %}
{{champion}}
{% endfor %}
</body>
</html>

Related

Flask Python HTML

I'm trying to render my home HTML file to my main flask python project, but when I run it, it gives this error "jinja2.exceptions.TemplateSyntaxError: unexpected '%'" could somebody help? It will be a pleasure. Currently using PyCharm IDE for this project.
<html>
<head>
<title></title>
</head>
<body>
{{% for post in posts %}}
<h1>{{post.title}}</h1>
<p>By {{post.author}} on {{post.date_posted}}</p>
<p>By {{post.content}}</p>
{{%end for%}}
</body>
When doing conditional statements, it must be enclosed with the following syntax:
{% if true %}
When passing variables to the template, you use the double braces:
<span>MyVar has the value: {{ myvar }}</span>
Another thing to note is that the end for should be endfor
Flask syntax is like {% code %}... not {{% code %}}({{}} just for vars to template) and is {% endfor %} instead of: {{%end for%}}.

Django templates - can you pass arguments to template tags *args style?

I am trying to implement some breadcrumbs in my templates.
I some view urls take one argument and others two.
url(r'^firstpage/(?P<arg_one>(option1|option2))/(?P<unique_identidfier>[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890\-_]+)/', views.MyView.as_view(), name="two_arg_view"),
url(r'^secondpage/(?P<unique_identidfier>[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890\-_]+)/', views.MySecondView.as_view(), name="one_arg_view),
I would like to pass in an array of breadcrumbs to via get_context_data, then loop over them in the template:
<div class="breadcrumbs">
{%for crumb in breadcrumbs %}
<a href="{% url crumb.url arg1 optional_arg2 %}" >{{ crumb.text }}</a> >
{% endfor %}
{{ current_page }}
</div>
Is there a way I can pass an optional number of arguments to the url template tag?
In the same way you might when calling something with *args?
What I want to do (but doesn't work) is:
<a href="{% url crumb.url *crumb.args %}" >{{ crumb.text }}</a> >
An inclusion tag will most likely do what you're looking for.
Inclusion tags can accept the current template context and you can retrieve your view values from there instead of having to manually pass them in. By including a template that contains the div, anchor tag, etc, you keep your templates simple:
{% tag_url %}
instead of having to repeat a bunch of conditional statements and loops.
I wouldn't recommend doing this sort of logic in a view, as it's not encapsulated or re-usable.

NoReverseMatch Django Postman

Why does this return a NoReverseMatch?
From django-postman:
url(r'^write/(?:(?P<recipients>[\w.#+-:]+)/)?$', 'write', name='postman_write'),
Template:
<a href='{% url postman_write recipients=object.user %}'>Send Message</a>
This does not work either..
<a href='{% url postman_write object.user %}'>Send Message</a>
Returns: Reverse for 'postman_write' with arguments '(<User: admin>,)' and keyword arguments '{}' not found. What am I missing to construct this url properly? Thanks!
you are passing a user object in url tag. You need to pass the username.
{% url postman_write recipients=object.user.username %}
Also make sure you have included the postman urls in your main urls.py file.
Try:
{% url postman_write object.user.username %}

How to render menu with one active item with DRY?

I would like to render a constructions like:
<a href='/home'>Home</a>
<span class='active'>Community</span>
<a href='/about'>About</a>
Where Community is selected menu item. I have menu with same options for several templates but I would not like to create combinations for each template:
<!-- for Home template-->
<span class='active'>Home</span>
<a href='/comminuty'>Community</a>
<a href='/about'>About</a>
...
<!-- for Community template-->
<a href='/home'>Home</a>
<span class='active'>Community</span>
<a href='/about'>About</a>
...
<!-- for About template-->
<a href='/home'>Home</a>
<a href='/community'>Community</a>
<span class='active'>About</span>
We have permanent list of menu items, so, it can be more effective way - to create only one generalized structure of menu then render menu with required option for template.
For example it could be a tag that allows to do that.
Figured out another way to do it, elegant enough thanks to this answer : https://stackoverflow.com/a/17614086/34871
Given an url pattern such as:
url(r'^some-url', "myapp.myview", name='my_view_name'),
my_view_name is available to the template through request ( remember you need to use a RequestContext - which is implicit when using render_to_response )
Then menu items may look like :
<li class="{% if request.resolver_match.url_name == "my_view_name" %}active{% endif %}">Shortcut1</li>
<li class="{% if request.resolver_match.url_name == "my_view_name2" %}active{% endif %}">Shortcut2</li>
etc.
This way, the url can change and it still works if url parameters vary, and you don't need to keep a list of menu items elsewhere.
Using template tag
You can simply use the following template tag:
# path/to/templatetags/mytags.py
import re
from django import template
try:
from django.urls import reverse, NoReverseMatch
except ImportError:
from django.core.urlresolvers import reverse, NoReverseMatch
register = template.Library()
#register.simple_tag(takes_context=True)
def active(context, pattern_or_urlname):
try:
pattern = '^' + reverse(pattern_or_urlname)
except NoReverseMatch:
pattern = pattern_or_urlname
path = context['request'].path
if re.search(pattern, path):
return 'active'
return ''
So, in you your template:
{% load mytags %}
<nav><ul>
<li class="nav-home {% active 'url-name' %}">Home</li>
<li class="nav-blog {% active '^/regex/' %}">Blog</li>
</ul></nav>
Using only HTML & CSS
There is another approach, using only HTML & CSS, that you can use in any framework or static sites.
Considering you have a navigation menu like this one:
<nav><ul>
<li class="nav-home">Home</li>
<li class="nav-blog">Blog</li>
<li class="nav-contact">Contact</li>
</ul></nav>
Create some base templates, one for each session of your site, as for example:
home.html
base_blog.html
base_contact.html
All these templates extending base.html with a block "section", as for example:
...
<body id="{% block section %}section-generic{% endblock %}">
...
Then, taking the base_blog.html as example, you must have the following:
{% extends "base.html" %}
{% block section %}section-blog{% endblock %}
Now it is easy to define the actived menu item using CSS only:
#section-home .nav-home,
#section-blog .nav-blog,
#section-contact .nav-contact { background-color: #ccc; }
I found easy and elegant DRY solution.
It's the snippet:
http://djangosnippets.org/snippets/2421/
**Placed in templates/includes/tabs.html**
<ul class="tab-menu">
<li class="{% if active_tab == 'tab1' %} active{% endif %}">Tab 1</li>
<li class="{% if active_tab == 'tab2' %} active{% endif %}">Tab 2</li>
<li class="{% if active_tab == 'tab3' %} active{% endif %}">Tab 3</li>
</ul>
**Placed in your page template**
{% include "includes/tabs.html" with active_tab='tab1' %}
You could make a context variable links with the name, URL and whether it's an active item:
{% for name, url, active in links %}
{% if active %}
<span class='active'>{{ name }}</span>
{% else %}
<a href='{{ url }}'>{{ name }}</a>
{% endif %}
{% endfor %}
If this menu is present on all pages, you could use a context processor:
def menu_links(request):
links = []
# write code here to construct links
return { 'links': links }
Then, in your settings file, add that function to TEMPLATE_CONTEXT_PROCESSORS as follows: path.to.where.that.function.is.located.menu_links. This means the function menu_links will be called for every template and that means the variable links is available in each template.
I have come up with a way to utilize block tags within menu-containing parent template to achieve something like this.
base.html - the parent template:
Home
About
Contact
{% block content %}{% endblock %}
about.html - template for a specific page:
{% extends "base.html" %}
{% block menu_about_class %}active{% endblock %}
{% block content %}
About page content...
{% endblock %}
As you can see, the thing that varies between different page templates is the name of the block containing active. contact.html would make use of menu_contact_class, and so on.
One benefit of this approach is that you can have multiple subpages with the same active menu item. For example, an about page might have subpages giving information about each team members of a company. It could make sense to have the About menu item stay active for each of these subpages.
Here ist my solution:
{% url 'module:list' as list_url %}
{% url 'module:create' as create_url %}
<ul>
<li>List Page</li>
<li>Creation Page</li>
</ul>
Assuming the nav item is a link with the same URL as the current page, you could just use JavaScript. Here's an annotated method that I use to add a class="active" to a li in a navigation menu with class="nav":
// Get the path name (the part directly after the URL) and append a trailing slash
// For example, 'http://www.example.com/subpage1/sub-subpage/'
// would become '/subpage1/'
var pathName = '/' + window.location.pathname.split('/')[1];
if ( pathName != '/' ) { pathName = pathName + '/'; }
// Form the rest of the URL, so that we now have 'http://www.example.com/subpage1/'
// This returns a top-level nav item
var url = window.location.protocol + '//' +
window.location.host +
pathName;
console.log(url);
// Add an 'active' class to the navigation list item that contains this url
var $links = document.querySelectorAll('.nav a');
$link = Array.prototype.filter.call( $links, function(el) {
return el.href === url;
})[0];
$link.parentNode.className += ' active';
This method means you can simply pop it into your base template once and forget about it. No repetition, and no manual specification of the page URL in each template.
One caveat: this obviously only works if the url found matches a navigation link href. It would additionally be possible to specify a couple of special use cases in the JS, or target a different parent element as needed.
Here's a runnable example (keep in mind, snippets run on StackSnippets):
// Get the path name (the part directly after the URL) and append a trailing slash
// For example, 'http://www.example.com/subpage1/sub-subpage/'
// would become '/subpage1/'
var pathName = '/' + window.location.pathname.split('/')[1];
if ( pathName != '/' ) { pathName = pathName + '/'; }
// Form the rest of the URL, so that we now have 'http://www.example.com/subpage1/'
// This returns a top-level nav item
var url = window.location.protocol + '//' +
window.location.host +
pathName;
console.log(url);
// Add an 'active' class to the navigation list item that contains this url
var $links = document.querySelectorAll('.nav a');
$link = Array.prototype.filter.call( $links, function(el) {
return el.href === url;
})[0];
$link.parentNode.className += ' active';
li {
display: inline-block;
margin: 0 10px;
}
a {
color: black;
text-decoration: none;
}
.active a {
color: red;
}
<ul class="nav">
<li>
Example Link
</li>
<li>
This Snippet
</li>
<li>
Google
</li>
<li>
StackOverflow
</li>
</ul>
I ran into this challenge today with how to dynamically activate a "category" in a sidebar. The categories have slugs which are from the DB.
I solved it by checking to see category slug was in the current path. The slugs are unique (standard practice) so I think this should work without any conflicts.
{% if category.slug in request.path %}active{% endif %}
Full example code of the loop to get the categories and activate the current one.
{% for category in categories %}
<a class="list-group-item {% if category.slug in request.path %}active{% endif %}" href="{% url 'help:category_index' category.slug %}">
<span class="badge">{{ category.article_set.count }}</span>
{{ category.title }}
</a>
{% endfor %}
Based on #vincent's answer, there is an easier way to do this without messing up with django url patterns.
The current request path can be checked against the rendered menu item path, and if they match then this is the active item.
In the following example I use django-mptt to render the menu but one can replace node.path with each menu item path.
<li class="{% if node.path == request.path %}active{% endif %}">
node.title
</li>
I am using an easier and pure CSS solution. It has its limitations, of which I know and can live with, but it avoids clumsy CSS class selectors, like this:
index
Because a space character before active is missing the class selector gets called itemactive instead of item active and this isn't exactly too difficult to get wrong like that.
For me this pure CSS solution works much better:
a.item /* all menu items are of this class */
{
color: black;
text-decoration: none;
}
a.item[href~="{{ request.path }}"] /* just the one which is selected matches */
{
color: red;
text-decoration: underline;
}
Notice: This even works if the URL has additional path components, because then href also matches partially. That could eventually cause 'collisions' with more than one match, but often enough it just works, because on well structured websites a "subdirectory" of an URL usually is a child of the selected menu item.
I personally find the simplest way is to create blocks for each link like so:
# base.py
...
<a href="{% url 'home:index' %}" class={% block tab1_active %}{% endblock %}>
...
<a href="{% url 'home:form' %}" class={% block tab2_active %}{% endblock %}>
...
And then in each relative template declare that link as "active" e.g.:
tab1 template:
{% block tab1_active %}"active"{% endblock %}
tab2 template:
{% block tab2_active %}"active"{% endblock %}
Simply use template tags
# app/templatetags/cores.py
from django import template
from django.shortcuts import reverse
register = template.Library()
#register.simple_tag
def active(request, url, classname):
if request.path == reverse(url):
return classname
return ""
Do like this in your template
{% load cores %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example</title>
</head>
<body>
<div>
myUrl
</div>
</body>
</html>
Have fun 😎

build website for mobile and pc with django

I am trying to develop a website for mobile and pc browser with django.
and I am trying to figure out a best structure of the views and templates.
there is what I have tried:
1) use different url ( like http://example.com/mobile/ and http://example.com/ OR
http://example.com/?c=mobile ) to distinguish mobile and pc, and map them to different view which set different templates.
2) in the view set different template according to USER_CLIENT
3) use a wrapper layer of the view, the actual view just return the data to the wrapper, the wrapper set the different template.
Is there a common way to handle this in django? any suggestions and comments?
Use Django's "sites" framework for a mobile version at http://m.example.com.
I would recommended solution 3; using a decorator to inspect the clients User Agent and returning à different template in case of a mobile agent.
Have the decorator take two arguments: the normal template, and the mobile template.
From your view, return a dict The decorator may pass to the rendering function as context. There is a decorator called 'render_to' that does this very well, Google for it.
To deal with the use case where users want the full version, even when browsing from a mobile device, you may use a redirecting view that sets a cookie your decorator may check for.
best practice: use minidetector to add the extra info to the request, then use django's built in request context to pass it to your templates like so.
from django.shortcuts import render_to_response
from django.template import RequestContext
def my_view_on_mobile_and_desktop(request)
.....
render_to_response('regular_template.html',
{'my vars to template':vars},
context_instance=RequestContext(request))
then in your template you are able to introduce stuff like:
<html>
<head>
{% block head %}
<title>blah</title>
{% if request.mobile %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-mobile.css">
{% else %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-desktop.css">
{% endif %}
</head>
<body>
<div id="navigation">
{% include "_navigation.html" %}
</div>
{% if not request.mobile %}
<div id="sidebar">
<p> sidebar content not fit for mobile </p>
</div>
{% endif %>
<div id="content">
<article>
{% if not request.mobile %}
<aside>
<p> aside content </p>
</aside>
{% endif %}
<p> article content </p>
</aricle>
</div>
</body>
</html>