Django allauth - Template include in base.html causes RecursionError - django

I am using allauth to handle all my authentication. Using that app each piece of authentication functionality is given its own template. However, I want to include the registration form in all other templates. i.e. the registration form is present in /account/login/, /account/password/change ... etc...
I decided to achieve that by including signup.html in base.html which is extended in all other templates. Like this:
base.html
...
<h4 class="card-title text-center">Register</h4>
{% include "account/signup.html" %}
...
account/base.html
{% extends "base.html" %}
account/signup.html
{% extends "account/base.html" %}
{% load i18n %}
<p>{% blocktrans %}Already have an account? Then please sign in.{% endblocktrans %}</p>
{% for message in messages %}
<span style="color:red;">{{ message }}</span>
{% endfor %}
<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
{% csrf_token %}
{% for field in form %}
<div id="input-group">
{{ field }}
</div>
{% endfor %}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<div class="card-footer text-center">
<input type="submit" class="btn" value='{% trans "Get started" %}'>
</div>
</form>
account/login.html
{% extends "account/base.html" %}
{% load static %}
{% load i18n %}
{% load account socialaccount %}
{% get_providers as socialaccount_providers %}
{% block general_notice_modal %}
{% endblock general_notice_modal %}
{% block login-modal %}
...
This code causes the following error, which only occurs when I add the {% include %} tag in base.html

I think the code below:
{% include "account/signup.html" %}
should be in "account/base.html" not in "base.html".
You have an error because your "base.html" call "account/signup.html" and your "account/signup.html" call "account/base.html" who call himself "base.html". You have a loop.

Related

CSRF verification failed. Request aborted. Even with {% crsf_token %}

I'm getting CSRF verification failed. Request aborted. after I try signing in, even though I've provided the {% csrf_token %} template tag.
templates/registration/login.html
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="card">
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-success"><i class="fas fa-sign-in-alt"></i> Login</button>
<input type="hidden" name="next" value="{{ next }}" />
</form>
{# Assumes you setup the password_reset view in your URLconf #}
<p>Lost password?</p>
</div>
</div>
{% endblock content %}

Why does template inheritance in Django not show error?

I'm not seeing an error when template inheritance seems to fail. I don't see content from the child template but I don't see a 'TemplateNotFound' error. If I change the path to the parent template to 'notthefilename.html' I still don't see an error. Is there a way to make template inheritance fail noisily? I have no idea why this is not working even though I have a similar inheritance in a adjacent folder that is working as expected.
generic_create.html The text 'hello2' is rendering.
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div style= "padding-top: 30px">
<form method="post">{% csrf_token %}
{% if model_name == 'TransactionsTable' %}
<div>
{% block transactions_create %}
hello2
{% endblock transactions_create %}
</div>
{% else %}
{{ form |crispy }}
{% endif %}
<div id="container">
<input type="submit" class="btn btn-default" value="Save">
Cancel
<div>
</form>
</div>
{% endblock content %}
transactions_create.html - The content 'Hello1' is not rendering
{% extends "generic_create.html" %}
{% load static %}
{% block transactions_create %}
Hello1
{% endblock transactions_create %}
Thanks to #Daniel Roseman's comment I realized I was performing the inheritance backwards. I was also over-complicating things. Using the include tag I was able to perform the sort of inheritance I was hoping to achieve very easily.
generic_create.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div style= "padding-top: 30px">
<form method="post">{% csrf_token %}
{% if model_name == 'TransactionsTable' %}
<div>
{% include "transactions_create.html" %} #NOTE: Here I removed the block and added 'include'.
</div>
{% else %}
{{ form |crispy }}
{% endif %}
<div id="container">
<input type="submit" class="btn btn-default" value="Save">
Cancel
<div>
</form>
</div>
{% endblock content %}
transactions_create.html
Hello1 #removed all of the extend and 'block' code. 'include' just renders the html directly.
That's it! 'include' really simplified things.

Invalid filter add_class using django-widget-tweaks

I am creating form view using django-widget-tweaks following this tutorial.
When I tried to implement add_class filter, I got following error.
Invalid filter: 'add_class'
Does anyone know how to solve this error?
html page
{% extends "base.html" %}
(% load widget_tweaks %}
{% block content %}
<form method="post" enctype="multipart/form-data">
<h4 style="margin-top: 0">Project Upload</h4>
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{hidden}}
{% endfor %}
{% for field in form.visible_fields %}
<div class="form-group">
<label for="{{field.id_for_label}}">{{field.label}}</label>
{{field|add_class:"form-control"}}
</div>
{% endfor %}
<button type="submit">Upload</button>
</form>
{% endblock %}
form.py
class DocumentForm(forms.ModelForm):
class Meta:
model=html
fields=['project','version','diff','program','location']
You can check this-out here
{% load widget_tweaks %}
<!-- add 2 extra css classes to field element -->
{{ form.title|add_class:"css_class_1 css_class_2" }}
Try this :
{% render_field field|add_class:"form-group"%}

django 1.6 - how do I insert a class-bassed view into a template as an {% include %}

My current template structure has a home.html that extends from a base.html. That home.html file also has its own {% include %} tags that pull in from other templates (contact forms, etc).
The problem I am having is that when I use the {% include %} tag on a class based view, nothing gets rendered in my template. I can still go to the url of the class based view and it renders just fine there.
In this case frontpabe/contact.html is a typical function based view, while frontpage/skills_list.html is a class based view.
home.html:
<div class="col-lg-4">
{% block contact %}
{% include 'frontpage/contact.html' %}
{% endblock %}
{% block skills %}
{% include 'frontpage/skills_list.html' %}
{% endblock %}
</div>
contact.html:
{% block contact %}
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<input type="text" name="subject" placeholder="I want a free estimate...">
<p></p>
<input type="text" name="email" placeholder="email address (optional)">
<p></p>
<textarea name="message" placeholder="here are some things I need..."></textarea>
<br />
<input type="submit" value="Submit">
</form>
{% endblock %}
skills_list.html:
{% block skills %}
{% for item in skills_list %}
<h3 style='background-color:yellow;'> {{ item.skills }} </h3>
{% endfor %}
{% endblock %}
Your problem won't have anything to do with whether it's a function-based view or a class-based view--the {% include %} tag merely includes the template itself--it doesn't call the view. It's literally as if you just copied + pasted the text of the contact or skills templates into your front page template.
Without seeing the rest of your code, I can't be 100% sure, but a likely place for your problem is that the view class or function for your homepage doesn't have a variable skills_list or, if it does, that it is empty. So your skills_list.html template is being used, it's just rendering the results of looping over an empty list (a quick check would be to add a tiny bit of static text, like "HELLO?" to skills_list.html outside of your {% for ... %}; if you see that, you're definitely rendering the template.
If it is a missing skills_list variable, it's almost certainly because of the misunderstanding about views/templates. You're probably defining that template in the CBV associates with skills_list.html template--but, again, the {% include %} tag doesn't call your view; it just includes the raw template itself.
Extends and include are different and should not be used together. If you are going to define blocks then have the children template extend the parent and override the blocks- no includes necessary:
home.html:
<div class="col-lg-4">
{% block contact %}
{% endblock %}
{% block skills %}
{% endblock %}
</div>
contact.html:
{% extends 'home.html' %}
{% block contact %}
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<input type="text" name="subject" placeholder="I want a free estimate...">
<p></p>
<input type="text" name="email" placeholder="email address (optional)">
<p></p>
<textarea name="message" placeholder="here are some things I need..."></textarea>
<br />
<input type="submit" value="Submit">
</form>
{% endblock %}
skills_list.html:
{% extends 'home.html' %}
{% block skills %}
{% for item in skills_list %}
<h3 style='background-color:yellow;'> {{ item.skills }} </h3>
{% endfor %}
{% endblock %}
Alternatively, you could use includes:
home.html:
<div class="col-lg-4">
{% include 'frontpage/contact.html' %}
{% include 'frontpage/skills_list.html' %}
</div>
contact.html:
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<input type="text" name="subject" placeholder="I want a free estimate...">
<p></p>
<input type="text" name="email" placeholder="email address (optional)">
<p></p>
<textarea name="message" placeholder="here are some things I need..."></textarea>
<br />
<input type="submit" value="Submit">
</form>
skills_list.html:
{% for item in skills_list %}
<h3 style='background-color:yellow;'> {{ item.skills }} </h3>
{% endfor %}

Satchmo Template form.username Not Popping Up

registration/login.html edited
{% load i18n %}
<div id="Login">
{% if form.non_field_errors %}
<p class="error">
{% for err in form.non_field_errors %}{{ err }}
{% if not forloop.last %}<br/>{% endif %}
{% endfor %}
</p>
{% endif %}
<form method="post" action=".">{% csrf_token %}
<table>
<tr><td><label for="id_username">{% trans 'USERNAME' %}:</label></td><td>{{ form.username }}</td></tr>
{% if form.username.errors %}<tr><td class="error" colspan="2">***{{ form.username.errors|join:", " }}</td></tr>{% endif %}
<tr><td><label for="id_password">{% trans 'PASSWORD' %}:</label></td><td>{{ form.password }}</td></tr>
{% if form.password.errors %}<tr><td class="error" colspan="2">***{{ form.password.errors|join:", " }}</td></tr>{% endif %}
</table>
<input type="submit" value="{% trans 'sign in' %}" />
{% url registration_register as registration_register %}
{% if registration_register %}
<span>{% trans "register" %}</span>
{% endif %}
<input type="hidden" name="next"
{% if next %}
value={{ next }} />
{% else %}
{% url satchmo_account_info as accounturl %}
{% if accounturl %} value="{% url satchmo_account_info %}" /> {% endif %}
{% endif %}
</form>
{% comment %} We jump through hoops with the urls so it doesn't bomb with django's built in unit tests.{% endcomment %}
{% url auth_password_reset as auth_password_reset %}
{% if auth_password_reset %}
<p>{% trans "If you do not remember your password, please" %}
{% trans "click here to have it reset." %}</p>
{% endif %}
</div>
Why does the form.username and form.password input box not show up? I had to remove the block tag {% extends shop/base.html %}. Did that cause the input field to disappear?
What I did was removed the {% block content %}{% endblock %} and used {% include "registration/login.html" %} in the base.html template. I wanted the login section to appear at the top left corner instead of having to click "Login" for the login field located in the {% block content %}.
registration/login.html original file
{% extends "shop/base.html" %}
{% load i18n %}
{% block navbar %}
<li class="first">{% trans "Home" %}</li>
{% endblock %}
{% block content %}
{% if form.non_field_errors %}
<p class="error">{% for err in form.non_field_errors %}{{ err }}{% if not forloop.last %}<br/>{% endif %}
{% endfor %}</p>
{% endif %}
<form method="post" action=".">{% csrf_token %}
<table>
<tr><td><label for="id_username">{% trans 'Email address' %}:</label></td><td>{{ form.username }}</td></tr>
{% if form.username.errors %}<tr><td class="error" colspan="2">***{{ form.username.errors|join:", " }}</td></tr>{% endif %}
<tr><td><label for="id_password">{% trans 'Password' %}:</label></td><td>{{ form.password }}</td></tr>
{% if form.password.errors %}<tr><td class="error" colspan="2">***{{ form.password.errors|join:", " }}</td></tr>{% endif %}
</table>
<input type="submit" value="{% trans 'Login' %}" />
<input type="hidden" name="next"
{% if next %}
value={{ next }} />
{% else %}
{% url satchmo_account_info as accounturl %}
{% if accounturl %} value="{% url satchmo_account_info %}" /> {% endif %}
{% endif %}
</form>
{% comment %} We jump through hoops with the urls so it doesn't bomb with django's built in unit tests.{% endcomment %}
{% url registration_register as registration_register %}
{% url auth_password_reset as auth_password_reset %}
{% if registration_register %}
<p>{% trans "If you do not have an account, please" %} {% trans "click here" %}.</p>
{% endif %}
{% if auth_password_reset %}
<p>{% trans "If you do not remember your password, please" %} {% trans "click here to have it reset." %}</p>
{% endif %}
{% endblock %}
shop/base.html
<div id="sidebar-primary">{# rightnav #}
{% block sidebar-primary %}
<h3>{% trans "Quick Links" %}</h3>
{% url satchmo_product_recently_added as recenturl %}
{% if recenturl %}{% trans "Recently Added" %}{% endif %}
{% url satchmo_product_best_selling as popularurl %}
{% if popularurl %}<br/>{% trans "Best Sellers" %}<br/>{% endif %}
{% url satchmo_category_index as category_index %}
{% if category_index %} {% trans "Category Index" %}<br /> {% endif %}
{% url satchmo_quick_order as quick_order %}
{% if quick_order %}{% trans "Quick Order" %} {% endif %}
{% plugin_point "sidebar_links" %}
<h3>{% trans "Account Information" %}</h3>
{% if user.is_staff %}
{% trans "Admin" %}<br/>
{% endif %}
{% if user.is_authenticated %}
{% url satchmo_account_info as accounturl %}
{% if accounturl %}{% trans "Account Details" %}<br/>{% endif %}
{% trans "Log out" %}<br/>
{% else %}
<!-- I REMOVE REPLACED THE LINK BELOW WITH {% include "registration/login.html" %} -->
{% trans "Log in" %}<br/>
{% endif %}
{% url satchmo_cart as carturl %}
{% if carturl %}{% trans "Cart" %}{% endif %}
{% if not cart.is_empty %}
({{ cart_count|normalize_decimal }} - {% if sale %}{{ cart|discount_cart_total:sale|currency }}{% else %}{{cart.total|currency}}{% endif%}) <br/>
{% url satchmo_checkout-step1 as checkouturl %}
{% if checkouturl %}{% trans "Check out" %}{% endif %}
{% endif %}
{% plugin_point "shop_sidebar_actions" %}
{% url satchmo_contact as contact_url %}
{% if contact_url %}<p>{% trans "Contact Us" %}</p>{% endif %}
{% satchmo_language_selection_form %}
{% block sidebar-primary-bottom %}
{% plugin_point "shop_sidebar_primary" %}
{% endblock %}
{% endblock sidebar-primary %}
</div>
I tried a {% include "registration/copy_login.html" %} and changed the content around a little. I also used <form action="{% url auth_login %}. When I click submit with login/pass filled out, it takes me to /accounts/login/ where I have to enter the login data again.
This is my copy_login.html:
# copy_login.html
...
<tr><td><label for="id_username">{% trans "Username" %}</label></td><td><input type="text" name="id_username" id="id_username" /></td></tr>
<tr><td><label for="id_password">{% trans "Password" %}</label></td><td><input type="text" name="id_password" id="id_password" /></td></tr>
...
If your template extends another template, then only the code it has in {% block %}...{% endblock %} is supposed to "show up".
Say i have this base.html template:
<html>
<body>
{% block body %}
{% endblock %}
</body>
</html>
Then, in such a login.html template:
{% extends 'base.html' %}
this won't show up because it's not in a block
{% block body %}
this will "show up"
{% endblock %}
Read up about template inheritance
Answer specific only to user's code
The first problem is that you probably tried to include the modified shortened registration/login.html into the main template, but you hide it into comment:
<!-- I REMOVE REPLACED THE LINK BELOW WITH {% include "registration/login.html" %} -->
Uncomment it to see the result.
The original template registration/login.html is used by the view accounts.views.emaillogin and used by URL /accounts/login/ which is redirected if you go to any page that requires login. You broke it, but you want to display a bigger form in the centre of page in this case, not only the small in the corner. You also do not want display there errors related to other forms on the page. Isn't it? Do not break the purpose of the original template.
General answer
I recommend first to copy paste important parts of login template registration/login.html to your smaller template that you include somewhere. Do it so that you not include error messages etc. in the small template, only the minimum. If the login fails the usual big login page with messages will be displayed. You need to change action="." to
<form method="post" action="{% url auth_login %}?next={{ request.path }}">
Note: The name auth_login is defined in satchmo_store/accounts/urls.py by:
(r'^login/$', 'emaillogin', {'template_name': 'registration/login.html'}, 'auth_login'),
Finally you can make it DRY (Do not Repeat Yourself) but it's not worth the effort for you, while the templates will be very different.
[Edited] 1) Included small fix from comments. 2) Modified to be easier for others.