Using a custom form inside django wizard - django

How would I use a custom form to display inside the session wizard so when it goes through each step it displays the html for each form inside the signup.html.
createUser.html
{% extends 'base.html' %}
{% block title %}Create User{% endblock %}
{% block content %}
<form method="POST" action='.' enctype="multipart/form-data">
{% csrf_token %}
<!-- A formwizard needs this form -->
{{ wizard.management_form }}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button>Sign up</button>
<button>Log In</button>
</form>
{% endblock %}
views.py
class UserWizard(SessionWizardView):
template_name = "registration/signup.html"
form_list = [SignUpForm]
def done(self, form_list, **kwargs):
process_data(form_list)
return redirect('home')
signup.html
{% extends 'base.html' %}
{% load i18n %}
{% block head %}
{{ wizard.form.media }}
{% endblock %}
{% block title %}Sign up{% endblock %}
{% block content %}
<h2>Sign up</h2>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form action="." method="POST" enctype="multipart/form-data">
{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
{% endif %}
<input type="submit" value="{% trans 'submit' %}"/>
</form>
{% endblock %}

Related

Validation of checkbox in Shopware 6 only working upon up and down scroll

I moved the terms and conditions consent from the original twig template so that it shows at a different position on the website. My problem is that when the consent checkbox is not checked, a warning should be shown to the user when clicking the payment button. This however only happens, when scrolling up and down on the website after clicking the finish payment button. Does anyone see my mistake?
{% sw_extends '#Storefront/storefront/page/checkout/confirm/index.html.twig' %}
{% block base_header %}
{% sw_include '#Storefront/storefront/layout/header/header-minimal.html.twig' %}
{% endblock %}
{% block base_navigation %}{% endblock %}
{% block page_checkout_main_content %}
{% block page_checkout_confirm %}
{% block page_checkout_confirm_header %}
<h1 class="confirm-main-header">
{{ "checkout.confirmHeader"|trans|sw_sanitize }}
</h1>
{% endblock %}
{% block page_checkout_confirm_alerts %}
{% block page_checkout_confirm_violations %}
{% for violation in formViolations.getViolations() %}
{% set snippetName = "error.#{violation.code}" %}
{% set fieldName = violation.propertyPath|trim('/', 'left') %}
{% sw_include '#Storefront/storefront/utilities/alert.html.twig' with {
type: "danger",
content: snippetName|trans({'%field%': fieldName})|sw_sanitize
} %}
{% endfor %}
{% endblock %}
{% endblock %}
{% block page_checkout_confirm_address %}
<div class="confirm-address">
{% sw_include '#Storefront/storefront/page/checkout/confirm/confirm-address.html.twig' %}
</div>
{% endblock %}
{% block page_checkout_confirm_payment_shipping %}
<div class="confirm-payment-shipping">
<div class="row">
{% block page_checkout_confirm_payment %}
<div class="col-sm-6 confirm-payment">
{% sw_include '#Storefront/storefront/page/checkout/confirm/confirm-payment.html.twig' %}
</div>
{% endblock %}
{% block page_checkout_confirm_shipping %}
<div class="col-sm-6 confirm-shipping">
{% sw_include '#Storefront/storefront/page/checkout/confirm/confirm-shipping.html.twig' %}
</div>
{% endblock %}
</div>
</div>
{% endblock %}
{% block page_checkout_confirm_product_table %}
<div class="confirm-product">
{% block page_checkout_confirm_table_container %}
<div class="card">
<div class="card-body">
{% block page_checkout_confirm_table_header %}
{% sw_include '#Storefront/storefront/page/checkout/confirm/confirm-product-header.html.twig' %}
{% endblock %}
{% block page_checkout_confirm_table_items %}
{% for lineItem in page.cart.lineItems %}
{% block page_checkout_confirm_table_item %}
{% sw_include '#Storefront/storefront/page/checkout/confirm/confirm-item.html.twig' %}
{% endblock %}
{% endfor %}
{% endblock %}
</div>
</div>
{% endblock %}
</div>
{% endblock %}
{% block page_checkout_confirm_tos %}
<div class="confirm-tos">
<div class="card checkout-card">
<div class="card-body">
{% block page_checkout_confirm_tos_header %}
<div class="card-title">
{{ "checkout.confirmTermsHeader"|trans|sw_sanitize }}
</div>
{% endblock %}
{% block page_checkout_confirm_revocation_notice %}
{% if config('confirm.revocationNotice') %}
<p class="revocation-notice">
{% block page_checkout_confirm_revocation_notice_link %}
<a href="{{ path('frontend.cms.page',{ id: config('core.basicInformation.revocationPage') }) }}"
{{ dataBsToggleAttr }}="modal"
title="{{ "checkout.confirmRevocationNotice"|trans|striptags }}"
data-url="{{ path('frontend.cms.page',{ id: config('core.basicInformation.revocationPage') }) }}">
{{ "checkout.confirmRevocationNotice"|trans|sw_sanitize }}
</a>
{% endblock %}
</p>
{% endif %}
{% endblock %}
{% block page_checkout_confirm_tos_control %}
<div class="{{ formCheckboxWrapperClass }}">
{% block page_checkout_confirm_tos_control_checkbox %}
<input type="checkbox"
class="checkout-confirm-tos-checkbox {{ formCheckInputClass }}{% if formViolations.getViolations('/tos') is not empty %} is-invalid{% endif %}"
required="required"
id="tos"
form="confirmOrderForm"
name="tos"/>
{% endblock %}
{% block page_checkout_confirm_tos_control_label %}
<label for="tos"
class="checkout-confirm-tos-label custom-control-label">
{{ "checkout.confirmTerms"|trans({
'%url%': path('frontend.cms.page',{ id: config('core.basicInformation.tosPage') })
})|raw }}
</label>
{% endblock %}
</div>
{% endblock %}
</div>
</div>
</div>
{% endblock %}
{% block page_checkout_confirm_hidden_line_items_information %}
{% sw_include '#Storefront/storefront/component/checkout/hidden-line-items-information.html.twig' with {
cart: page.cart,
lineItems: page.cart.lineItems
} %}
{% endblock %}
{% endblock %}
{% endblock %}
{% block page_checkout_additional %}
{% if config('core.cart.showCustomerComment') %}
<div class="checkout-additional">
{% block page_checkout_finish_customer_comment %}
<div class="card checkout-card">
<div class="card-body">
{% block page_checkout_confirm_customer_comment_header %}
<div class="card-title">
{{ "checkout.customerCommentHeader"|trans|sw_sanitize }}
</div>
{% endblock %}
{% block page_checkout_confirm_customer_comment_control %}
<div class="checkout-customer-comment-control">
{% block page_checkout_confirm_customer_comment_control_textfield_label %}
<label class="form-label" for="{{ constant('Shopware\\Core\\Checkout\\Order\\SalesChannel\\OrderService::CUSTOMER_COMMENT_KEY') }}">
{{ "checkout.customerCommentLabel"|trans|sw_sanitize }}
</label>
{% endblock %}
{% block page_checkout_confirm_customer_comment_control_textfield %}
<textarea class="form-control"
placeholder="{{ "checkout.customerCommentPlaceholder"|trans|sw_sanitize }}"
id="{{ constant('Shopware\\Core\\Checkout\\Order\\SalesChannel\\OrderService::CUSTOMER_COMMENT_KEY') }}"
form="confirmOrderForm"
name="{{ constant('Shopware\\Core\\Checkout\\Order\\SalesChannel\\OrderService::CUSTOMER_COMMENT_KEY') }}"></textarea>
{% endblock %}
</div>
{% endblock %}
</div>
</div>
{% endblock %}
</div>
{% endif %}
{% endblock %}
{% set formAddHistoryOptions = {
entries: [{
state: {},
title: 'account.ordersTitle'|trans,
url: path('frontend.account.order.page')
}]
} %}
{% block page_checkout_aside_actions %}
<div class="checkout-aside-action">
<form id="confirmOrderForm"
action="{{ path('frontend.checkout.finish.order') }}"
data-form-csrf-handler="true"
data-form-preserver="true"
data-form-submit-loader="true"
data-form-add-history="true"
data-form-add-history-options='{{ formAddHistoryOptions|json_encode }}'
method="post">
{% block page_checkout_aside_actions_csrf %}
{{ sw_csrf('frontend.checkout.finish.order') }}
{% endblock %}
{% block page_checkout_confirm_form_submit %}
{# #deprecated tag:v6.5.0 - Bootstrap v5 removes `btn-block` class, use `d-grid` wrapper instead #}
{% if feature('v6.5.0.0') %}
<div class="d-grid">
<button id="confirmFormSubmit"
class="btn btn-primary btn-lg"
form="confirmOrderForm"
{% if page.cart.errors.blockOrder %}
disabled
{% endif %}
type="submit">
{{ "checkout.confirmSubmit"|trans|sw_sanitize }}
</button>
</div>
{% else %}
<button id="confirmFormSubmit"
class="btn btn-primary btn-block btn-lg"
form="confirmOrderForm"
{% if page.cart.errors.blockOrder %}
disabled
{% endif %}
type="submit">
{{ "checkout.confirmSubmit"|trans|sw_sanitize }}
</button>
{% endif %}
{% endblock %}
</form>
</div>
{% endblock %}
{% block base_footer %}
{% sw_include '#Storefront/storefront/layout/footer/footer-minimal.html.twig' %}
{% endblock %}

Django: formset errors without li / *

I am using a formset. formset.non_form_errors are displayed exactly the way I need it. However my field specific errors in for dict in formset.errors are always displayed inlcuding the <li> tag. I tried .as_text, however that just added a * (and removed the li). But I don't need the * either.
Anyone who can help me with that?
{% if formset.total_error_count %}
{% if formset.non_form_errors %}
{% for error in formset.non_form_errors %}
<div class="alert alert-warning" role="alert">
{{ error|escape }}
</div>
{% endfor %}
{% endif %}
{% for dict in formset.errors %}
{% for error in dict.values %}
<div class="alert alert-warning" role="alert">
{{ error|escape }}
</div>
{% endfor %}
{% endfor %}
{% endif %}
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
The problem could be fixed by moving the individual errors in the form loop:
{% if formset.total_error_count %}
{% if formset.non_form_errors %}
{% for error in formset.non_form_errors %}
<div class="alert alert-warning" role="alert">
{{ error|escape }}
</div>
{% endfor %}
{% endif %}
{% endif %}
{% for form in formset %}
{% if form.quantity.errors %}
<div class="alert alert-warning" role="alert">
{% for error in form.quantity.errors %}
{{ error|escape }}
{% endfor %}
</div>
{% endif %}

MultiValueDictKeyError

I have the following code. The first works, however the second throws a "MultiValueDictKeyError". I've tweaked the code around a bit but I haven't been able to fix it. Any and all help is greatly appreciated!
Working Code:
{% extends "base.html" %}
{% block base_content %}
<link rel="stylesheet" href="/media/themes/txt/css/employee_summary/report.css" />
<form id="myForm" method="post">
{% csrf_token %}
{% for field in form %}
<div class=box>
<div class="row">
<div class="2u">
<h1>{{ field.label_tag }}:</h1>
</div>
<div class="10u">
{{ field }}
</div>
</div>
</div>
{% endfor %}
{% for formset in inlines %}
<div class=box>
{% for form in formset %}
<div class="row">
<div class="12u">
<h1>{{ form }}</h1>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
{% for formset in inlines %}
{{ formset.management_form }}
{% endfor %}
<input type="submit" value="Save Changes">
</form>
{% endblock %}
Non-Working Code:
{% extends "base.html" %}
{% block base_content %}
<link rel="stylesheet" href="/media/themes/txt/css/employee_summary/report.css" />
<div id="main-wrapper">
<div class="strongborder">
<div id="main" class="container boldtext">
<form id="myForm" method="post" class="12u">
{% csrf_token %}
{% for field in form %}
<div class="row">
<div class="2u">
<h1>{{ field.label_tag }}:</h1>
</div>
<div class="10u">
{{ field }}
</div>
</div>
{% endfor %}
{% for formset in inlines %}
{% for form in formset %}
<br>
<br>
<h1>{{ form.instance.form_name }}</h1>
{% for field in form %}
<div class="row">
{% if field.label != "Employee" and field.label != "Id" and field.label != "Delete" %}
<label class="2u">{{ field.label }}:</label>
<div class="10u">{{ field }}</div>
{% endif %}
</div>
{% endfor %}
{% endfor %}
{% endfor %}
{% for formset in inlines %}
{{ formset.management_form }}
{% endfor %}
<br>
<br>
<input type="submit" value="Save Changes">
</form>
</div>
</div>
</div>
{% endblock %}
Solved by myself: for some reason it wasn't liking the ID skip in
{% if field.label != "Employee" and field.label != "Id" and field.label != "Delete" %}
... yet it was fine with skipping the employee and delete fields.

Add unique styling to one form in a Django formset

I have a formset with four forms, and want to render the fourth one with different CSS from the others - unique color, styling, etc. Can I do this from my html page, or somewhere else?
I'm looking for something like this pseudo-code:
<form action="" method="post">{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors }}
<div>
{% for form in formset except the last form %}
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
{% endfor %}
{% endfor %}
{% for the last form in the formset %}
{% for field in form %}
{{ field.errors }}
<div class="different style">
{{ field.label_tag }}:
<p class="another different style">{{ field }}</p>
</div>
{% endfor %}
{% endfor %}
</div>
<p><input type="submit" value="Submit" /></p>
</form>
See forloop.last in documentation -
<form action="" method="post">{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors }}
<div>
{% for form in formset %}
{% if forloop.last %}
{% for field in form %}
{{ field.errors }}
<div class="different style">
{{ field.label_tag }}:
<p class="another different style">{{ field }}</p>
</div>
{% endfor %}
{% else %}
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
{% endfor %}
{% endif %}
</div>
<p><input type="submit" value="Submit" /></p>
</form>

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.