Django - Custom tag not working - django

I want to pass a model to template base.html.
I read about custom tags, and tried to execute this. It is not throwing any error, but is not working too.
My code:
base.html:
{% load staticfiles %}
{% load tags %}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<ul class="dropdown-menu" role="menu">
{% for league in get_my_leagues %}
<li> ddddd {{ league.league_name }}</li>
{% endfor %}
</ul>
{% block content %}
{% endblock %}
</body>
</html>
Now, tags.py:
from django.template import Library
from login.models import League
register = Library()
#register.inclusion_tag('base.html')
def get_my_leagues():
return League.objects.all()
register.tag('get_my_leagues', get_my_leagues)

When you use {% for x in y %}, this expects that y is a context variable in your template, not a template tag.
What an inclusion tag does is that it renders a template (the one you pass as argument to the inclusion_tag decorator), and inserts the result where the inclusion tag is used.
You probably want to register get_my_leagues as a simple tag instead (or an assignment tag, if you're using Django older than 1.9), and use it like this:
{% get_my_leagues as my_leagues %}
{% for league in my_leagues %}
...
{% endfor %}

guys.
I'm here just to tell that i found a solution for my problem. I'm using Context Processors to do this job.
Thank you all for answers!

Related

About parametrizing base template page in Django

I have the following problem, there is a base template "base.html" which defines default header and body information, which will be used by other pages.
The base page contains the rendered parameter, which depends on the request time in a non trivial way.
base.html
<!DOCTYPE html>
<head>
...
{% block head_stuff %} {% endblock %}
...
</head>
<body>
...
<p>Parameter that depends on the request time</p>
...
{% block body_stuff %} {% endblock %}
...
</body>
</html>
The pages that use it look like:
a.html b.html c.html
{% extends "base.html" %}
{% block head_stuff %} ... {% endblock %}
{% block body_stuff %} ... {% endblock %}
What I'd like to do is to render a.html, b.html, c.html without passing informations about that parameter to these pages in their views or templates.
In absence of inheritance, one would call render function by passing the parameter to a context, but in this case no views are used to construct the base.html.
How can I approach this problem?
A context processor is a function that takes request as an argument and returns a dictionary. The contents of this dictionary are then appended to the context of every template. So if you had a context process or
def my_example(request):
return dict(
name="steve",
dynamic_thing=some_other_function()
)
Then the templates could access these using {{ name }} and {{ dynamic_thing }}

How to add a contact form template into another template?

I'm very new to this and I'm trying to create a simple website for a company using django 2.
I'm using this template that is a single page: https://html5up.net/astral
I want to make the contact form work but I can't manage.
I've tried putting {% block %} {% endblock %} in the HTML file but it won't render the form, {% include %} renders the html file I created but not the form. I was wondering if it is possible to make the form that is already rendered work.
Thanks!
You can use Template Inheritance to do this.
You have your "base.html" parent template which has a placeholder for the form:
<html>
...
<div ... >
{% block contact-form %}
{% endblock %}
</div>
...
</html>
And your form is in "contact.html" child template:
{% extends "base.html" %}
{% block contact-form %}
<!-- contact form content -->
{% endblock %}
Then in your url patterns direct peeps to the view that renders the child "contact.html" template.
The {% extends %} tag lets the template engine know that it must first load the parent "base.html" and then fill in the appropriate block with the child "contact.html" template's content.

Custom Template Tag Queryset Not Returning Anything

I'm trying to implement a feature that displays the 5 most recently created events. I decided to implement this with Django custom template tags (if this is not the best way, let me know). What I have so far is:
In event_search.html (among other things):
{% extends 'base.html' %}
{% load eventSearch_extras %}
<p>count: {{ recents.count }}</p>
<ul>
{% for e in recents %}
<li> {{e.title}} </li>
{% empty %}
<li> No recent events </li>
{% endfor %}
</ul>
In eventSearch_extra.py:
from django import template
from eventSearch.models import Event
register = template.Library()
#register.inclusion_tag('eventSearch/event_search.html')
def mostrecentevents():
"""Returns most 5 most recent events"""
recents = Event.objects.order_by('-created_time')[:5]
return {'recents': recents}
My issue here is that the queryset 'recents' appears to return empty to the template. 'count:' shows nothing & the for-loop defaults to 'No recent events'.
You've loaded the inclusion tag function, but not the individual tag, so the code to populate that information is never called; it's also laid out slightly oddly, so you're calling from the wrong place.
The main template calls the inclusion tag by using:
{% load eventSearch_extras %}
And you include the actual tag by calling
{{mostrecentevents}}
mostrecentevents goes off and runs the code, parses the html of event_search.html and puts it in the main template. The way your code is set out just now, you'd be calling an inclusion tag from its own HTML.
Main template > {% load inclusion_tags %} {{ actual_tag }}
As an example, I have a restaurant template. In that template is this code:
{% load restaurant_menu %} <!--main inclusion tag .py file) -->
{% menu %} <!-- the actual tag code you want to run -->
in restaurant_menu.py I have the following (additional irrelevant stuff removed):
#register.inclusion_tag('core/_menu.html', takes_context=True)
def menu(context):
filtered = context['filtered']
from core.models import MenuItem, FoodProfile, Ingredient, Recipe
if filtered:
restaurant = context['restaurant'].id
filtered_menu = #stuff here
restaurant_menu = filtered_menu
else:
restaurant_menu = MenuItem.objects.filter(restaurant__pk=context['restaurant'].id)
return {"restaurant_menu": restaurant_menu,
"number_of_menu_items": restaurant_menu.count(),
"filtered": filtered}
and the _menu.html page (underscored so I know it's a fragment) :
<ul>
{% for item in course.list %}
<li>
{{ item.number|floatformat:0 }} {{ item.name }} {{ item.description }} {{ item.price }} </li>
</li>{% endfor %}
{% endfor %}
</ul>
An inclusion tag is used to render another template. It doesn't make sense to create an inclusion tag that renders event_search.html, then call that template tag inside event_search.html itself. Note that you haven't actually used the template tag (with {% mostrecentevents %}), all you have done is load the template tag library.
It would be easier to use a simple tag instead.
#register.simple_tag
def mostrecentevents():
"""Returns most 5 most recent events"""
recents = Event.objects.order_by('-created_time')[:5]
return recents
Then in your template you can do:
{% load eventSearch_extras %}
{% mostrecentevents as recents %}
This loads the result of the template tag into the variable recents, and you can now do:
<p>count: {{ recents.count }}</p>
<ul>
{% for e in recents %}
<li> {{e.title}} </li>
{% empty %}
<li> No recent events </li>
{% endfor %}
</ul>
Note you can only use the as recents syntax with simple tags with Django 1.9+. For earlier versions, you can use an assignment tag instead.

Why is this django template tag failing to display?

I have a template tag located in catalog/templatetags/catalog_tags.py, which looks like this:
register = template.Library()
#register.inclusion_tag("tags/navigation.html")
def nav_links():
flatpage_list = FlatPage.objects.all()
return {'flatpage_list': flatpage_list }
I have a catalog.html which has {% load catalog_tags %}, to load that tag, and is followed by an inclusion tag for my navigation, {% include "tags/navigation.html" %}.
navigation.html contains the following:
{% with flatpage_list as pages %}
{% for page in pages %}
{{ page.title }}
{% endfor %}
{% endwith %}
But the list of flat_pages is not appearing in my navigation section. Why is that?
If I understand right, with your current state you have something liek this in catalog.html template:
{% load catalog_tags %}
.....
{% include "tags/navigation.html" %}
What this code does, is just renders the "tags/navigation.html" template, nothing more. So your custom template tag is not hit at all. To fix it, you should replace include with nav_links:
{% load catalog_tags %}
.....
{% nav_links %}
See Django docs for reference.
Not sure if it's just a copy paste error or not but return {'flatpage_list': flatpage_list isn't closed properly return {'flatpage_list': flatpage_list}
Also could this be something more suited for a context processor?
EDIT: After reading the other answer, I realized what you are trying to do, when you were using the {% include ... %} tag it seemed like you just wanted to populate the flatpage_list

Embedded controller views with assets

I am currently working on a symfony2 application and am using embedded controllers. My embedded controllers are like widgets which should encapsulate its own set of functionality and can be embedded anywhere and still be expected to function.
I have a controller called users online. The view it generates is simple, just a list of online users. But, I would like to add some javascript to that view so that I can use ajax to retrieve information for a user that's clicked on.
The controller basically returns a view:
return $this->render('AppBundle:Users:usersOnline.html.twig', array('somedata' => $data);
Here's the view for that controller:
{% extends partial.html.twig" %}
{% block content %}
<ul>
<li>User 1</li> (this would all be generated using 'somedata')
<li>User 2</li>
....
<ul>
{% endblock content %}
{% block scripts %}
..some javascript for interacting with this widget
{% endblock %}
This is the partial that is extended from:
{% block content %}
{% endblock content %}
{% block scripts %}{% endblock %}
Here's the main page that embeds the controller:
{% "base.html.twig" %}
{% block title %}Main{% endblock %}
{% block content %}
..some markup here
<div id="usersonline">
{% render "AppBundle:Users:usersOnline" with {'max': 4} %}
</div>
{% endblock %}
{% block scripts %}
..some javascript
{% endblock %}
This is the base that it extends:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}{% endblock %} - App</title>
...Some stylesheets
</head>
<body>
{% block content %}{% endblock %}
<script src="http://yui.yahooapis.com/3.5.0pr2/build/yui/yui-min.js"></script>
{% block scripts %}{% endblock %}
</body>
</html>
The problem I am facing now is including javascripts from the embedded controller. In my case, the view extends partial and is fully rendered as 1 unit before it is inserted into the main page. In this case, I can only put my javascript in the content block, which means I will have <script> tags within <div> tags. I would also prefer to have scripts at the end of the body for user interface performance.
How should I structure my templates (or is it even possible) so that I can render the appropriate pieces from an embedded controller's view into appropriate blocks in the template that embeds the controller? In my current template the YUI library would be loaded after the embedded controller's rendered HTML markup, so accessing using the YUI library within the embedded controller would be impossible.
I have written an extension which is essentially a token parser to deal with this. The documentation for the token parser is very sparse and the code is also mostly uncommented, so it took a bit of fiddling around to get working.
I have structured the parser so that at the beginning, you would declare something (similiar to {% use %}):
{% myparser "AppBundle:Users:usersOnline" with {'max': 4} as xyz %}
Then blocks like xyzcontent would be avaliable and then you just render them in the appropriate places using {{ block('xyzcontent') }}. It works quite well. However the following does not work:
{% set max = 4 %}
{% myparser "AppBundle:Users:usersOnline" with {'max': max} as xyz %}
I could not find a way to evaluate an expression and get its value directly within the token parser. For the most part it works fine, except for this problem.
If someone has some idea as to how to get the value of a variable within the token parser, it would be great :)
After one day of looking for a satisfying solution, I finally choose for the following approach:
Render a controller for your widget's functionality (like you are already doing);
Render templates to embed your widget's assets (controllers are not needed and will waste your performance). Ignore include if the template doesn't exist.
Use a consistent naming convention to make the widget functionality more dynamic.
Example for one widget:
{% "base.html.twig" %}
{% block title %}Main{% endblock %}
{% block content %}
..some markup here
<div id="usersonline">
{{ render(controller("AppBundle:Users:usersOnline", {'max': 4})) }}
</div>
{% endblock %}
{% block scripts %}
{{ include("AppBundle:Users:usersOnline_js.html.twig" ignore missing }}
{% endblock %}
{% block stylesheets %}
{{ include("AppBundle:Users:usersOnline_css.html.twig" ignore missing }}
{% endblock %}
(As you can see, I use the Symfony 2.2 way of including and embedding)
Or, a more dynamic way of widget rendering:
{% "base.html.twig" %}
{% block title %}Main{% endblock %}
{% block widgets %}
..some markup here
{% for widget in widgets %}
{{ render(controller(widget.controller ~ ':widget', widget.options)) }}
{% endfor %}
{% endblock %}
{% block scripts %}
{% for widget in widgets %}
{{ include(widget.controller ~ ':widget_js.html.twig' ignore missing }}
{% endfor %}
{% endblock %}
{% block stylesheets %}
{% for widget in widgets %}
{{ include(widget.controller ~ ':widget_css.html.twig' ignore missing }}
{% endfor %}
{% endblock %}
My conclusion
Rendering multiple controllers in one page, while "merging" it's templates blocks, cannot be achieved out of the box in Symfony2. Symfony2 has always been focusing on one controller for each request, which explains why multiple controllers outputs are separated and hard to combine.
I think the Symfony CMF has (or will have) a proper solution for this, because this whole widget topic is more applied in dynamic content managed websites.
Anyway, I think my way of combining embedded controllers and included templates is the best approach for Symfony 2 so far.
The alternatives, in my opinion, do have to many disadvantages:
Using multiple controllers: too heavy and not needed because assets won't need any controller.
Loading the widgets assets directly in the page: hard to maintain when changing widgets / assets.