I just want to slice a string on django in two parts, passing a caracter like "|"
Example: 2007-007134|10003L
Part 1: 2007-007134
Part 2: 10003L
I tried somethings but without success
Someone can help me?
Create a custom template tag. They are basically python code which you can execute from inside the html templates (when using defult Django templating engine).
You can read more about them here:
https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/
https://www.codementor.io/#hiteshgarg14/creating-custom-template-tags-in-django-application-58wvmqm5f
I solved according Maciej Rogosz recommended:
Custom Template Tag
First: I created the folder templatetags inside of my app, after that create a empty ini.py and finally created my custom_tag.py:
from django import template
register = template.Library()
#register.filter(name='split1')
def split1(value, key):
return value.split(key)[1]
#register.filter(name='split2')
def split2(value, key):
return value.split(key)[0]
In my tamplate I have to load the template tags
{% load custom_tags %}
And call my custom_tags: split1, split2
{{ instance.mat_code|split1:"|" }}
{{ instance.mat_code|split2:"|" }}
That is it, python + django = Magic
Tks to everyone for your help
Ref1: https://www.w3schools.com/python/ref_string_split.asp
Ref2: https://www.codementor.io/#hiteshgarg14/creating-custom-template-tags-in-django-application-58wvmqm5f
Related
I have page_obj in a template which was returned from a ListView view. Now, I wanted to create links to several pages before and after the current page. Therefore, I wanted to slice page_obj.paginator.page_range this way: page_obj.paginator.page_range[page_obj.number-3:page_obj.number+4]. This works in django shell but for some reason when I did it a template, there is a Template Syntax Error, Could not parse the remainder: '[page_obj.number-3:page_obj.number+4]' from 'page_obj.paginator.page_range[page_obj.number-3:page_obj.number+4]'. Is there a workaround for this case?
P.S. I know I can do it using the whole page_obj.paginator.page_range and then using if statements to check if a page is in the required range, but I thought it's a bit inefficient.
As stated in my comment Django Template Language does not include normal python syntax. The reason for this is Django aims to separate the logic and design of the website. If there is need to perform somewhat complicated logic you either need to use template tags or filters.
For your need either an inclusion tag would work or a simple filter that would take the page_range and return a sliced version of it. A template filter here would not be very useful considering we can only pass one argument to it, meaning it would not be very customizable. Let's assume that your pagination would look very similar or perhaps you would pass the template you use to the tag.
Firstly you need to create a templatetags sub-package in your app and then in that you would add files (e.g. pagination_tags.py) which would contain your tags. The layout would be something like:
your_app/
__init__.py
models.py
templatetags/
__init__.py
pagination_tags.py
views.py
Now in your file pagination_tags.py you want to write your tags. As a reference you may read the howto on Custom template tags and filters in the documentation.
Firstly we declare register which is an instance of template.Library. After which we would write our template tags / filters. We will use an inclusion_tag:
from django import template
register = template.Library()
#register.inclusion_tag('pagination_tag.html')
def show_pagination(page_obj, **kwargs):
left = kwargs.get('left', 3)
right = kwargs.get('right', 4)
pages_iter = page_obj.paginator.page_range[page_obj.number - left:page_obj.number + right]
template = kwargs.get('template', 'default_pagination_template.html')
return {**kwargs, 'page_obj': page_obj, 'pages_iter': pages_iter, 'template': template}
Now we will have a simple template named pagination_tag.html that will simply extend the template name either passed as a keyword argument or default_pagination_template.html:
{% extends template %}
Now in default_pagination_template.html or any other template we can use all the variables in the dictionary that our function show_pagination returns:
{% for page_num in pages_iter %}
Display page links here, etc.
{% endfor %}
You can modify this implementation as per your needs. I will also leave the design and implementation of default_pagination_template.html upto you.
Now in your template where you want to use this, first we will load these tags. Then we will use them:
{% load pagination_tags %}
...
{% show_pagination page_obj left=5 right=6 template="some_custom_template.html" %}
I want to check if my list of objects contains an object with a certain attribute value in Django template tags. As we know it is represented in Python like:
any(x.name == "t2" for x in l)
So, is there some tags to express this in template tags something like:
{% if any x.atype == "Other" for x in list %}
{% endif %}
or something else do that?
There is no build-in tag for this, but you can create your own: add templatetags python directory to your project app where you plan to use tag. Then add file called tags.py and insert code listed below (example):
from django import template
register = template.Library()
#register.simple_tag(name=any)
def any_of_following(objects, value):
return any([item for item in objects if item == value])
Then you can use this tag in template as following:
{% any your_objects value_to_check %}
You can read more about simple_tags in Django docs
Lets assume a ConactAdmin for showing a ConactModel:
class ContactAdmin(admin.ModelAdmin):
change_form_template = "admin/contact_change.html"
def my_custom_fnc():
return "Test"
Now I want to access my_custom_fnc() in an view html my contact_change template like <p>{{my_custom_fnc()}}</p>
Is there a list of properties which I can access in my own template? I couldn't find it in the documentation.
The current modeladmin instance is available in the context as adminform.model_admin so this should work (nb : no parens - this is the Django template language, not Python) :
<p>{{ adminform.model_admin.my_custom_fnc }}</p>
This being said, depending on what my_custom_func is supposed to do, there might be better solutions...
NB : to find out what you have in a template context, you can use the {% debug %} template tag. Also, Django is OSS so you can just read the source code (which is what I did here).
I have some macros defined that are called from several templates.
For example, the Product page has a Review section that uses the macros defined in 'helpers/review.jinja2' to print each review. The 'helpers/review.jinja2' file has this two macros:
{% macro render_review(request,review) -%}
{% macro render_review_comment(request,comment) -%}
When someone submits a new review, via ajax, I want to return the rendered review in order to append the content to the Review section.
Right now, I have an intermediate template 'review/review.jinja2' that looks like this:
{% import 'helpers/review.jinja2' as review_helper %}
{{ review_helper.render_review(request,review) }}
This template is rendered from the view:
#view_config(route_name='review.add_review', renderer='review/review.jinja2')
def add_review(request):
return dict(review=my_new_review)
But I hope there is a better way to do this. So, is it possible to render a macro defined in a template?
Thanks
The solution can actually be found in another one of Armin's projects - Flask implements a get_template_attribute method (see here for the source of the method). This points us at Jinja2's Template class, more specifically, the Template class' module attribute.
I don't know if Pyramid's default renderer for Jinja2 exposes that functionality for you, but it should be possible to create and register a custom renderer if the default one does not let you do something like this (entirely theoretical):
#view_config(route_name='review.add_review',
renderer='helpers/review.jinja2:render_review')
def add_review(request):
return dict(review=my_new_review)
This method was suggested elsewhere, it helped me:
#app.route("/test")
def test_view():
t = app.jinja_env.get_template('macros.html')
mod = t.make_module({'request': request})
return mod.my_macro()
Render Jinja2 macro without bothering what's in the rest of the template
How can I create a widget on the site, such as login forms, dynamic menu (items taken from the database), site statistics?
I know that you can render a template that will extend out of a base template. And in the base template you can create these widgets.
But I do not know how to move the logic from the base template to my code. For example, the selection data for the block. Such actions certainly can be done in the template, but it would be a poor method in my opinion.
Sorry for my bad English. If you can not understand, I'll try to rephrase.
You would use a python library called WTForms. It helps you write code for creating forms and other widgets backed by database which you can render using jinja2 templates.
class YourForm(Form):
your_field1 = TextField()
....
your_fieldn = SubmitField()
#app.route('/')
def view():
form=YourForm()
return render_template('your.html', form=form)
In your.html
<form >
{{ form.your_field1 }}
....
{{ form.your_fieldn }}
</form>
Check out this flask pattern for form validation and rendering to know more about it.
Edit: To create global variables available to all templates,there are two ways:
You can use global dict of jinja environment.
This is the code:
app.jinja_env.globals.update({'variable':1})
You can use ContextProcessor. Code:
#app.context_processor
def inject_variable():
return dict(variable=1)
Now you can access variable in any template of your app.