Making a Django page visible only to confirmed emails - python

I'm trying to add a feature to my site where a certain part of the site can be used only by users who confirmed their email account.
I found a solution, but it's not working.
Here is what i did:
I have been suggested to add a separate model for this:
class account_emailconfirmation(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
#property
def has_verified_email(self):
return self.user.emailaddress_set.filter(verified=True,primary=True).exists()
And this is what the template looks like:
{% extends "main/header.html" %}
{% if user.account_emailconfirmation.has_verified_email %}
{% block content %}
<style>
</style>
<body>
<div> <p>Here goes a bunch of features</p> </div>
</body>
{% endblock %}
{% else %}
<p> Your email is ot confirmed </p>
{% endif %}
But it's not working, since i can see the page even without having to confirm my email.
Here is what my db looks like:
There is a table called account_emailconfirmation, then there is an index, verified, that will give 0 when the account is not verified, 1 when it is verified.
Any advice is appreciated!

Write this:
{% extends "main/header.html" %}
{% block content %}
{% if user.profile.has_verified_email %}
<style>
</style>
<body>
<div> <p>Here goes a bunch of features</p> </div>
</body>
{% else %}
<p> Your email is ot confirmed </p>
{% endif %}
{% endblock %}

You need to use the related_name attribute of the account_emailconfirmation.user one to one field
{% if user.account_emailconfirmation.has_verified_email %}
Side note, you should capitalize your classes:
class EmailConfirmation(models.Model):
I assume the account_ portion is for the app. You don't need that, you know which app the model is in.

Related

Passing a variable to include in extends in Django templates

I have the following structure of templates:
main.html
<html>
<body>
<p>
This works: {% block title %}{% endblock %}
</p>
{% include 'heading.html' with title=title %} {# but this does not work since it is not a variable #}
</body>
</html>
heading.html
<p>
{{ title }}
</p>
page.html
{% extends 'main.html' %}
{% block title %}test title{% endblock %}
How can I pass the title from page.html to heading.html? Ideally, it should be defined as a block like now, but alternatives are also welcome. I'd like to contain the solution within the templates if possible.
Clarification:
This is a minimal example, but I have multiple pages like main.html that share a larger header that has title and some other variables that I'd like defined in the child template (not necessarily as variable as long as the text is passed).
I could put the title into the view code, but this solution would just decrease the separation of displayed data from the logic.
Use a block around the include with variables, and then wrap {{ block.super }} in the with template tag.
main.html:
<html>
<body>
<p>
This works: {% block title %}{% endblock %}
</p>
{% block with_variables %}
{% include 'heading.html' %}
{% endblock %}
</body>
</html>
page.html:
{% extends 'main.html' %}
{% block title %}test title{% endblock %}
{% block with_variables %}
{% with title="variable title" %}
{{ block.super }}
{% endwith %}
{% endblock %}
You may name it {% block heading %}, or nest the whole main.html in {% block content %}.
instead of {% include %}, you might want to use custom template tags with returning html or extension like slippers
You don't need heading.html. You can use the context variable title directly; as long as you pass it to your render function in your view, e.g.:
views.py
def my_view(request):
context = {'title': 'Hello World!'}
return render(request, 'page.html', context=context)
main.html
<html>
<body>
<p>
This is my title:
{% block title %}{% endblock %}
</p>
</body>
</html>
page.html
{% extends 'main.html' %}
{% block title %}
<strong>{{title}}</strong>
{% endblock %}
If you have administrative rights to your Django installation, an easy and elegant solution would be to switch your Django's template renderer to Jinja2 instead using django-jinja as a backend.
The main advantage of Jinja2 for the needs of this question is that it supports assignment of a block to a variable through block assignments. Since Jinja2 is inspired by the Django template language, your existing templates will need few modifications, if any.
With Jinja2 as a template renderer, you can set the title variable with a block of HTML content in the child template:
page.html
{% extends 'main.html' %}
{% set title %}test title{% endset %}
The title variable will then work in the shared template:
main.html
<html>
<body>
<p>
Main template works: {{ title }}
</p>
{% include 'heading.html' %}
</body>
</html>
And it will also work in the included template:
heading.html
<p>
Included template also works: {{ title }}
</p>
Demo: https://replit.com/#blhsing/AlarmedCleverDebugmonitor
One possible solution is to split heading.html into two and add a {% block %} in-between, but this is an ugly workaround that is prone to bugs with unclosed tags.
I am searching for a better alternative.
main.html
...
{% include 'heading1.html' %} {# containing <p> #}
{% block title %}{% endblock %}
{% include 'heading2.html' %} {# containing </p> #}
...
Additionally, if white spaces are important, there has to be no new line between includes and the block.
add your title to the rendering context and it will be visible in page, main and included heading.

Django plain-text email template generates \n after template tags

Interesting issue here: I have plain-text emails sent by my Django app, with the following code:
email_context = dict()
email_context['to'] = user.display_name
email_context['new'] = user_data['new']
email_context['for_reminder'] = user_data['for_reminder']
plaintext = get_template('email/notification.txt')
text_content = plaintext.render_to_string(email_context)
html = get_template('email/notification.html')
html_content = html.render(email_context)
email = EmailMultiAlternatives(
subject='Assignments',
body=text_content,
to=[user.email],
reply_to=[settings.DEFAULT_FROM_EMAIL],
)
# email.attach_alternative(html_content, "text/html")
email.send()
the 'email/notification_base.txt' template looks like such:
Dear {{ to }},
{% if new %}
You have been assigned to the following NEW cases:
{% block new %}
{% endblock %}
{% endif %}
{% if for_reminder %}
You still have the following previously assigned cases, which need your attention:
{% block for_reminder %}
{% endblock %}
{% endif %}
Thank you for your assistance.
Sincerely,
The Team
the 'email/notification.txt' template just extends base:
{% extends 'email/notification_base.txt' %}
{% load common_tags %}
{% load common_filters %}
{% block new %}
{% for dispute in new %}
Case #: {{ dispute.case_id.no}}
Assignment date: {{ dispute.assignment_date }}
{% endfor %}
{% endblock %}
{% block for_reminder %}
{% for dispute in for_reminder %}
Case #: {{ dispute.case_id.no }}
Assignment date: {{ dispute.assignment_date }}
{% endfor %}
{% endblock %}
My problem with it is, that the email it generates and sends to the addressee, actually gets rendered with a NEWLINE in every spot where the template had {% something %} tags. This results in a very unevenly formatted email text. As an example, if both blocks were missing the email would look like:
Dear Someone,
Thank you for your assistance.
Sincerely,
The Team
Are there any ways around this problem?

Checking if a user is the author

It seems logic that any author of an article, can delete his own post. But I don't really know how to check if a user is the current author of a post.
Here is my code :
{% extends 'base.html' %}
{% block title %} Details | {{article.title}} {% endblock title %}
{% block content %}
<div class="starter-template" style="text-align: center; margin: 2% 0">
<h1>{{object.title.capitalize}}</h1>
<p>{{object.body}}</p>
<p style="font-style: italic">{{object.author}}</p>
<p>{{object.date}}</p>
{% if object.author == user.username %}
<p>
Delete
Edit
</p>
{% endif %}
</div>
{% endblock content %}
"object.author == user.username " is returning False. Why is that ?
Thanks :)
You can check like below. Please add your models to view relations.
{% object.author.user == user %}
{% if object.author == user %}

Django - The page don't load after click

i'm new in Django developing.
I'm following the tutorial about Library on MDN (https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django)
Until i follow the code all work but i'm trying implement author page by myself. Probably is very stupid issue but is one day that i'm turning around like a dog with its tail.
There is 2 page: author_list and author detail.
I set urls.py (in my project) i set view.py and crate my template.
I follow the same step of tutorial for realize book_list and book_detail but when i click on my author the page don't go to the detail of that author and stay in author_list.html.
Here the code urls.py :
path('authors/', views.AuthorListView.as_view(), name='authors'),
path('author/<int:pk>', views.AuthorDetailView.as_view(), name='author-detail'),
Here views.py:
class AuthorListView(generic.ListView):
model = Author
class AuthorDetailView(generic.ListView):
model = Author
Here author_list.html with link get_absolute_url:
{% extends "base_generic.html"%}
{% block content %}
<h1>Author list</h1>
{% if author_list %}
<ul>
{% for aut in author_list %}
<li>{{ aut.first_name }} - {{ aut.last_name }}</li>
{% endfor %}
</ul>
{% else %}
<p>There are no author.</p>
{% endif %}
{% endblock %}
Here author_detail.html:
{% extends "base_generic.html" %}
{% block content %}
<h1>Author</h1>
{% if author %}
<p><strong>Nome: </strong> {{ author }}</p>
<p><strong>Nato il : </strong> {{ author.date_of_birth }}</p>
<p><strong>Morto il : </strong> {{ author.date_of_death }}</p>
{% endif %}
{% endblock %}
Here the screenshot
Author_list.html before click url=catalog/authors/
After click url change but page not
Thank to all for help
I believe you need DetailView instead of ListView for AuthorDetailView.
Looks like a typo to me, you want generic.DetailView (instead of ListView) for the author/<int:pk> path.
I also don't think it's right to extend base_generic for the template for the detail view. But that depends exactly what is in this base template.

Flask pass data to child template

I would like to have a slightly different navbar depending on whether or not a user is signed in. Additionally, the content of dropdown menus will depend on the user that is logged in.
views.py file:
#app.route('/table')
def my_table:
return render_template("table.html",
user = user,
my_names = my_names)
A page in the application (/table):
{% extends "navbar.html" %}
{% block content %}
<html> A bunch of stuff </html>
The simplified navbar template:
{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block navbar %}
<html>
<nav class="navbar navbar-default" role="navigation">
<ul class="dropdown-menu" role="menu">
<li> Signed in as: {{ user }} </li>
<li class="divider"></li>
{% for name in my_names %}
<li> {{ name }} </li>
{% endfor %}
</html>
{% endblock %}
I would like to pass user and my_names to the navbar template. These two data change depending on who is signed in.
Am I thinking about this correctly? Is my structure ok? Should I be using something to simplify this (like Blueprints)?
(I know that I can get the user part by g.user since its global across templates)
Since you are already setting the user on g you have most of what you need already. The only thing left is to set the menu correctly.
The simplest thing to do is to use a context processor:
#app.context_processor
def provide_menu():
menu = derive_menu_from_global_user()
return {'menu': menu}
Then every template will have access to a menu variable containing a list of names that you can iterate over.

Categories

Resources