django inclusion_tag - django

I'm trying to create inclusion tag and place it on the page but it's not work.
My views.py:
from django.shortcuts import render_to_response, redirect
from django import template
register = template.Library()
#register.inclusion_tag('weather.html')
def weather():
return {'city': 'angola'}
def home(request):
return render_to_response('index.html')
index.html
<title> TITLE </title>
Hi everyone!
{% weather %}
weather.html
weather is fine in {{city}}
Django debug page says that "Invalid block tag: 'weather'" so I guess I put declaration of inclusion_tag in wrong place? Where I need to put it to get it work?

Template tags need to go in a module in your app's templatetags directory. See the code layout section of the custom template tag docs for full details.
You then have to load your tag library in the template before you use your tag.
{% load my_tags %}
{% weather %}

Related

Django - add link with custom admin page href

In my Django project, I have created a custom admin page for an app via the get_urls() method. I'd like to add a link to the app's main model index view that will take users to this custom page - however, I'm having some trouble creating this link element correctly and I don't seem to be able to piece together the right way to do it - I'm just left with a Reverse for 'export' not found. 'export' is not a valid view function or pattern name. error.
I've set up the admin for the app like so:
# my_project/observations/admin.py
from django.template.response import TemplateResponse
from django.urls import path
class ObservationAdmin(SimpleHistoryAdmin, SoftDeletionModelAdmin):
change_list_template = 'export_link.html'
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('export/', self.admin_site.admin_view(self.export_view), name='export')
]
return custom_urls + urls
def export_view(self, request):
context = dict(
self.admin_site.each_context(request),
)
return TemplateResponse(request, 'export.html', context)
and the two templates that are referenced:
# my_project/observations/templates/export.html
{% extends "admin/base_site.html" %}
{% block content %}
<div>
Some custom content
</div>
{% endblock %}
# my_project/observations/templates/export_link.html
{% extends 'admin/change_list.html' %}
{% block object-tools-items %}
<li>
Export
</li>
{{ block.super }}
{% endblock %}
Navigating directly to http://localhost:8000/admin/observations/observation/export/ works perfectly, I see the custom content page exactly as I want it... so the issue I'm striking is with the link template - I get the Reverse... error when I navigate to the model index page.
Perhaps the argument I'm passing to url is incorrect, or I need to register that URL elsewhere - but I don't quite know. The other examples of link elements like this that I've been able to find don't reference URLs created via the admin class' get_urls() method - so any guidance on this would be greatly appreciated.
Thanks very much, let me know if there's any other info that I can provide to help sort this out.
I think the problems is in missing namespace in your export_link.html template. Instead of:
Export
try:
Export

django-cms getting the page context in an application hook

Consider this cms_app.py
from django.utils.translation import ugettext_lazy as _
from cms.app_base import CMSApp
from cms.apphook_pool import apphook_pool
class FooHook(CMSApp):
name = _("FooHook Plugin")
urls = ["foo.urls"]
apphook_pool.register(FooHook)
The foo app, has a views model which contains to default django views, ListView and DetailView.. These have their default templates, inheriting from a base.html, these are foo_list.html and foo_detail.html..
The documentation is completely unclear how to get, for example the cms page's sidebar content or page context variable at all, within those templates..
Feincms has the {% fragment %} template tag for this purpose, how can one achieve this in django-cms?
To access the page you can use {{ request.current_page }}
To use the plugin system in your templates use {% static_placeholder my_name %} instead of the {% placeholder %} tags.
It is always preferable to use the static_placeholders in apphooks as you do not know what template and what placeholders the page actually has.

Problems implementing a Django Custom Template Tag

I need to implement a template tag that will return a string with a collection of items from an object.
I had created the following structure:
produtos/
templatetags/
__init__.py
produto_tags.py
produto_tags.py:
# -*- coding: utf-8 -*-
from django import template
from django.template import Node
from produto.models import Produto
from django.template.loader import render_to_string
register = template.Library()
#register.tag
def get_all_tags(parser, token):
args = token.split_contents()
return ProdutoTemplateNode(args[1])
class ProdutoTemplateNode(Node):
def __init__(self, produto):
self.produto = produto
def render(self, context):
list = []
produto = template.Variable(self.produto).resolve(context)
tags = produto.tags.all()
if tags:
for tag in tags:
list.append(tag.name)
return ", ".join(list)
else:
return u'Não existem tags para este produto'
Template:
{% load produto_tags %}
...
{% for produto in produtos %}
<li id="{{ produto.ordenacao }}" data-tags="{% get_all_tags produto %}">
...
</li>
{% endfor %}
</ul>
{% else %}
<p>Não existem produtos cadastrados no sistema</p>
{% endif %}
I am receiving this error:
TemplateSyntaxError at /concrete/nossos-sites.html
Invalid block tag: 'get_all_tags', expected 'empty' or 'endfor'
I read other threads where people said this error occurs if the Tag does not exist and it seems to be the case. I've been looking on the djangoproject.com documentation as well and I could not find any clue about what might be happening.
Thanks!
Template tag files need to be inside a directory called templatetags inside your app.
Follow Daniel and Ignacio's suggestions first. Also, its weird that you have {% load produto_tags %} in the top of the template but got an invalid block error: if produto_tags cannot be loaded, the error should be something like 'produto_tags is not a valid tag' blahblah. Could you please check the code and path structure you posted, again?
That was tricky, even though simple:
First, there was another 'produto_tags.py' in another folder elsewhere in the project:
project/
common/
templatetags/
produtos_tags.py
produtos/
templatetags/
produtos_tags.py
So, at first I have moved all code from produtos/templatetags/ to common/templatetags/. But when I did it Django started whining about not finding the produtos_tags from produtos. Afterwards I got the code back to produtos/templatetags/ and renamed the file to tags_produtos.py, what had worked to show the easy part that is my wrong import below:
Wrong:
from produto.models import Produto
Correct:
from produtos.models import Produto
Use {{ produto | get_all_tags }} instead.
The {% ... %} syntax is only valid for block tags such as for.
Hope that helps.

django - template tag problem using AuthenticationForm

I am trying to put a login form in every page in my web that uses django.contrib.auth.views.login. I created a templatetag in templatetags/mytags.py, where I define a function called get_login wich looks like this:
#register.inclusion_tag('registration/login.html', takes_context=True)
def get_login(context):
...
return {'formLogin': mark_safe(AuthenticationForm())}
...and in base.html:
{% load mytags %}{% get_login %}
The problem now is that the template (registration/login.html) doesnt recognize {{ formLogin.username }},{{ formLogin.password }}... and so on.
What am I missing?
mark_safe returns an instance of django.utils.safestring.SafeString, not a form, so those lookups will fail. I don't think there's anything wrong with directly returning the form (that's what all the generic views in django.contrib.auth do when populating templates, for instance). Just change your return statement to
return {'formLogin': AuthenticationForm()}
and it should work.

Form labels not rendering with Django & WTForms

I'm trying to use WTForms with Django & a MongoEngine/MongoDB database backend. The forms are outputting properly, but I can't for the life of me get the labels to show up.
Here is my template code:
{% load wtforms %}
<form>
{% for f in form %}
{{ f.label }}: {% form_field f %}<br/>
{% endfor %}
</form>
This is what I am passing in the view:
form = StrandForm()
return render_to_response('create_strand.html', locals(), context_instance = RequestContext(request))
The StrandForm class I have tried both creating from the WTForm mongoengine extension's model_form class, and from WTForm's Form class. The label exists in the view, I can print it to the console and it shows the rendered form label, but somehow it gets lost when transferring to the template. Am I doing something wrong?
Django 1.4 has a new feature: do_not_call_in_templates attribute.
If you set it on wtforms.Field class, every child class inherits and all fields will work fine in django templates.
import wtforms
wtforms.Field.do_not_call_in_templates = True
Now following code works as expected:
{% load wtforms %}
{{ f.label }}: {% form_field f %}
I encountered the same problem today. It has to do with the way WTForms is programmed so that it will work with many different templating libraries. Django 1.3 will only see f as it's HTML string even though it has other attributes.
In order to fix this you must add a template tag to retrieve the attribute.
Add the following to your projects hierarchy:
templatetags
templatetags / init.py
templatetags / templatetags
templatetags / templatetags / init.py
templatetags / templatetags / getattribute.py
Then in your settings.py file, add the following line to INSTALLED_APPS
'templatetags',
Open up getattribute.py and paste the following code:
from django import template
from django.conf import settings
register = template.Library()
#register.tag
def getattribute(parser, token):
try:
tag_name, tag_object, tag_function = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError("%r tag requires two arguments" % token.contents.split()[0])
return getattrNode(tag_object, tag_function)
class getattrNode(template.Node):
def __init__(self, tag_object, tag_function):
self.tag_object = tag_object
self.tag_function = tag_function
def render(self, context):
return getattr(context[self.tag_object], self.tag_function)()
This will allow you to use the follow code whenever you're inside a template and need an attribute that won't show up:
{% load getattribute %}
{% getattribute OBJECT ATTRIBUTE %}
In your case:
{% getattribute f label %}
Hope that helped!