Why did the lower built in filter not work in Django template 2.2? - django

Using Django v2.2 built-in filters for templates.
my template looks like this:
{% load i18n %}{% blocktrans with site_name=current_site.organization.name site_domain=current_site.name %}Hello from {{ site_name }}!
You're receiving this e-mail because your email is subscribed to receiving notification when a Quotation is Pending PO Release.
{{ quote_type }}
{{ quote_type|lower }}
- Quotation: {{ display_quotation_number }}
- PO Date: {{ po_date_display }} (New)
{% endblocktrans %}
{% blocktrans with site_name=current_site.organization.name site_domain=current_site.name %}Thank you for using {{ site_name }}!
{{ site_domain }}{% endblocktrans %}
I can say with certainty that {{ quote_type }} definitely prints something out. {{ quote_type|lower }} prints nothing.
What did I do wrong?
I was certain that the filter is builtin; see https://docs.djangoproject.com/en/2.2/ref/templates/builtins/#lower
UPdate
This is my current workard and it works
extra_context = self.lower_quote_type(extra_context)
quotation.email_people(
recipient_list=recipient_list,
extra_context=extra_context,
)
def lower_quote_type(self, extra_context):
# #makeAnIssue temp workard for #1334 but try to permanently fix it elegantly
if "quote_type" in extra_context:
extra_context["quote_type"] = extra_context["quote_type"].lower()
return extra_context
Then this works
{% load i18n %}{% blocktrans with site_name=current_site.organization.name site_domain=current_site.name %}Hello from {{ site_name }}!
You're receiving this e-mail because your email is subscribed to receiving notification when a Quotation is Pending PO Release.
{{ quote_type }} # this correctly shows up as lower case
- Quotation: {{ display_quotation_number }}
- PO Date: {{ po_date_display }} (New)
{% endblocktrans %}
{% blocktrans with site_name=current_site.organization.name site_domain=current_site.name %}Thank you for using {{ site_name }}!
{{ site_domain }}{% endblocktrans %}

Related

filtering dependency-track vulnerabilities notification

I have a dependency-track server that sends notifications to email for all new vulnerabilities.
I would like to send notifications only for critical vulnerabilities.
In the pebble templates, I would like to have something like this:
{% if subject.vulnerability.severity == "CRITICAL" %}
// send notifications
{% else %}
// do not send any notification
{% endif %}
Any idea?
I tried to use the template below, but it continues to send empty notifications also for those vulnerabilities with severity High, Medium and Minor.
In the else statement I should have something that invalidates the template.
{% if notification.group == "NEW_VULNERABILITY" %}
{% if subject.vulnerability.severity == "CRITICAL" %}
{{ notification.title }}
--------------------------------------------------------------------------------
Vulnerability ID: {{ subject.vulnerability.vulnId }}
Severity: {{ subject.vulnerability.severity }}
Source: {{ subject.vulnerability.source }}
Component: {{ subject.component.toString }}
Component URL: {{ baseUrl }}/component/?uuid={{ subject.component.uuid }}
Project: {{ subject.component.project.name }}
Version: {{ subject.component.project.version }}
Description: {{ subject.component.project.description }}
Project URL: {{ baseUrl }}/projects/{{ subject.component.project.uuid }}
{% if notification.subject.affectedProjects|length > 1%}
--------------------------------------------------------------------------------
Other affected projects:
{% for affectedProject in notification.subject.affectedProjects %}
{% if not (affectedProject.uuid == subject.component.project.uuid) %}
Project:[{{affectedProject.name}} : {{ affectedProject.version }}]
Project URL:{{ baseUrl }}/project/{{ affectedProject.uuid }}
{% endif %}
{% endfor %}
{% endif %}
--------------------------------------------------------------------------------
{{ notification.content }}
--------------------------------------------------------------------------------
{{ timestamp }}
{% endif %}
{% endif %}

how to customize sent emails in djoser?

I build React&Django project and use Djoser for registration and auth. I want to customize sent email content on Gmail. Where should I change it?
In your django directory create an app or in existing app <my_app>
create a file
email.py
then in <my_app> directory create template folder like:
templates/<my_app>/
within the directory <my_app> create two html files:
ActivateEmail.html
ConfirmationEmail.html
Then in ActivationEmail.html add this code below:
{% load i18n %}
{% block subject %}
{% blocktrans %}Account activation on {{ site_name }}{% endblocktrans %}
{% endblock subject %}
{% block text_body %}
{% blocktrans %}You're receiving this email because you need to finish activation process on {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page to activate account:" %}
{{ protocol }}://{{ domain }}/{{ url|safe }}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endblock text_body %}
{% block html_body %}
<p>{% blocktrans %}You're receiving this email because you need to finish activation process on {{ site_name }}.{% endblocktrans %}</p>
<p>{% trans "Please go to the following page to activate account:" %}</p>
<p>{{ protocol }}://{{ domain }}/{{ url|safe }}</p>
<p>{% trans "Thanks for using our site!" %}</p>
<p>{% blocktrans %}The {{ site_name }} team{% endblocktrans %}</p>
{% endblock html_body %}
And in your ConfirmationEmail.html add this code:
{% load i18n %}
{% block subject %}
{% blocktrans %}{{ site_name }} - Your account has been successfully created and activated!{% endblocktrans %}
{% endblock %}
{% block text_body %}
{% trans "Your account has been created and is ready to use!" %}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endblock text_body %}
{% block html_body %}
<p>{% trans "Your account has been created and is ready to use!" %}</p>
<p>{% trans "Thanks for using our site!" %}</p>
<p>{% blocktrans %}The {{ site_name }} team{% endblocktrans %}</p>
{% endblock html_body %}
Then email.py within your app <my_app> add this code below:
from djoser import email
from djoser import utils
from djoser.conf import settings
from django.contrib.auth.tokens import default_token_generator
class ActivationEmail(email.ActivationEmail):
template_name = '<my_app>/ActivationEmail.html'
def get_context_data(self):
# ActivationEmail can be deleted
context = super().get_context_data()
user = context.get("user")
context["uid"] = utils.encode_uid(user.pk)
context["token"] = default_token_generator.make_token(user)
context["url"] = settings.ACTIVATION_URL.format(**context)
return context
class ConfirmationEmail(email.ConfirmationEmail):
template_name = '<my_app>/ConfirmationEmail.html'
then EDIT
ActivationEmail.html
ConfirmationEmail.html
however you LIKE.
Then the last step is to add The classes in email.py to replace the default templates
in activation/confirmation email.
The defaults are as in docs: djoser docs
Then in Djoser settings in settings.py file:
DJOSER = {
'USER_CREATE_PASSWORD_RETYPE': True,
'SEND_CONFIRMATION_EMAIL': True,
'SEND_ACTIVATION_EMAIL': True,
'ACTIVATION_URL': 'activate/{uid}/{token}',
'HIDE_USERS': True,
'SERIALIZERS': {
'user': 'myapp.serializers.UserCreateSerializer',
'user_create': 'myapp.serializers.UserCreateSerializer',
'current_user': 'myapp.serializers.UserSerializer',
},
(...)
}
Add this:
DJOSER = {
'USER_CREATE_PASSWORD_RETYPE': True,
'SEND_CONFIRMATION_EMAIL': True,
'SEND_ACTIVATION_EMAIL': True,
'ACTIVATION_URL': 'activate/{uid}/{token}',
'HIDE_USERS': True,
'SERIALIZERS': {
'user': 'myapp.serializers.UserCreateSerializer',
'user_create': 'myapp.serializers.UserCreateSerializer',
'current_user': 'myapp.serializers.UserSerializer',
},
'EMAIL': {
'activation': 'myapp.email.ActivationEmail',
'confirmation': 'myapp.email.ConfirmationEmail',
},
(...)
}
Then send Email activation instead of sending default template for user in his/her email, it'll send the ActivationEmail.html template for them
Note that the Djoser uses the django-template-mail for its activation email template.

Django 3: Badly formed URL in password_reset_email.html

I have a Django 3.0.7 app using the default template for sending password reset emails.
For some of our users, the link to reset is badly formed, e.g.:
https://foo.bar/accounts/reset/McU4Mw/5no-9cd52590f0943503=
fa3a/
/>
While it should be:
https://foo.bar/accounts/reset/McU4Mw/5no-9cd52590f0943503fa3a/
This second one is whats actually being sent. But, as I said, some users are receiving the first one.
I assume some of my users' email clients are wrecking the text, but what could I do?
I've considered adding a plaintext url to the email, but it's already plaintext.
EDIT: This is a solution I came up with, and it works. Can anyone think of a reason not to do this?
urls.py
...
path('accounts/reset/<uidb64>/<token>/<str:extra_chars>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('accounts/reset/<uidb64>/<token>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
...
EDIT:
Here's the default template:
/site-packages/django/contrib/admin/templates/registration/password_reset_email.html
{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
{% trans 'Your username, in case you’ve forgotten:' %} {{ user.get_username }}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}

how to properly generate html for django modelform

I need to place div around group of form fields in django template.
Easiest way would be to do is
MyForm().as_table()
copypaste that and enclose group of fields with appropriate div. Only problem is that this approach fails when there are errors in form validation because {{ form.fieldname.errors }} isn't mentioned anywhere.
Any better ideas or readymade tools that would save me from doing this by hand every time?
here is answer if anyone needs it
def generate_object_template(object):
from string import Template
for field in object._meta.fields:
t = Template(""" <label>{{ form.$fieldname.label }}{% if form.$fieldname.is_required %}*{% endif %}</label>
{{ form.$fieldname }}
{% if form.$fieldname.errors %} {{ form.$fieldname.errors }}{% endif %}""").substitute(fieldname=field.attname)
print t
When you have to customize a form in Django you can do as follow
...
<label>{{ form.myfield.label }}{% if form.myfield.is_required %}*{% endif %}</label>
{{ form.myfield }}
{% if form.myfield.errors %} {{ form.myfield.errors }}{% endif %}
<label>{{ form.myfield3.label }}{% if form.myfield3.is_required %}*{% endif %}</label>
{{ form.myfield3 }}
{% if form.myfield3.errors %} {{ form.myfield3.errors }}{% endif %}
<label>{{ form.myfield2.label }}{% if form.myfield2.is_required %}*{% endif %}</label>
{{ form.myfield2 }}
{% if form.myfield2.errors %} {{ form.myfield2.errors }}{% endif %}
...
With this kind of set up you can customize your form adding div where you want and still keep the validation on.
See http://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template

Django form template

If there were field.errors in django, how to to add css class to {{ field }}, example at bottom
{% for field in form %}
{{ field }}
{% if field.errors %}{{ field.errors }}{% endif %}
{% endfor %}
Aiming for {{ field }} input type that would have "class=error" when ever there was an error
<input class="error">
You can add the class to a wrapper around the field. Django also does this by itself when defining classes in forms.py or views.py
{% for field in form %}
<p {% if field.errors %}class="error"{% endif %}
{{ field }}
</p>
{% if field.errors %}{{ field.errors }}{% endif %}
{% endfor %}
Unfortunately this seems to be the only way.
Even when Django adds the classes itselt, it prefers to add them to a wrapper of some sort.
http://docs.djangoproject.com/en/dev/ref/forms/api/#more-granular-output
Scroll down to read about the new thing in 1.2 about adding css classes.
Using this, you can just use form.as_p (or whatever suits you) as the elements will have all the classes as you define them.
Hope this was a little bit of help.
You can use widget_tweaks api to do that.
Instead of rendering a form with
{{ form.field }}
You should use:
{% load widget_tweaks %}
{% render_field form.field class="error" %}