WTForms validate_on_submit won't execute (even with csrf_token) - forms

I use Flask-WTF and here is a snippet of my form. The login and registration routes are prepended with an url_prefix='/auth' in the users Blueprint.
class RegisterForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Sign Up')
Here's the registration route.
#users.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterForm()
print("Before form validate")
print(form.errors)
if form.validate_on_submit():
print("After form validate")
flash(f'Account created for {form.username.data}!', 'success')
return redirect(url_for('main.home'))
return render_template('auth/register.html', title='Register', form=form)
This is a minimal view of the template (with the csrf_token included). I have also tried .hidden_tag() in the template, but the result is similar.
<form method="POST" action="">
{{ form.hidden_tag() }}
<span class="bmd-form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="material-icons">account_circle</i>
</span>
</div>
{{ form.username(class="form-control form-control-lg" ~ (" is-invalid" if form.username.errors else ""), placeholder="Username...") }}
{% if form.username.errors %}
<div class="invalid-feedback">
{% for error in form.username.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% endif %}
</div>
</span>
<span class="bmd-form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="material-icons">email</i>
</span>
</div>
{{ form.email(class="form-control form-control-lg" ~ (" is-invalid" if form.email.errors else ""), placeholder="Email...") }}
{% if form.email.errors %}
<div class="invalid-feedback">
{% for error in form.email.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% endif %}
</div>
</span>
...........
</form>
As you see from my registration route I have also checked for any potential errors in the form. This is my console output after a registration test.
Before form validate
{}
127.0.0.1 - - [18/Jun/2020 21:02:28] "GET /auth/register?csrf_token=IjFlZGRkNmQ5YzkwZmE2YWJiYzY5NWMxNTAyZTMzN2UxODNmZjgzOTEi.XuupQg.4_2FGVqnp-2lq2vriQbAkx1Qz3Q&username=test&email=test%40test.com&password=testing&confirm_password=testing&submit=Sign+Up HTTP/1.1" 200 -
127.0.0.1 - - [18/Jun/2020 21:02:29] "GET /favicon.ico HTTP/1.1" 404 -
Thanks in advance!

Related

Front-end form with Craft CMS for users to submit entries not working?

I've put together an entry form to allow registered users to submit content. I followed the example given in the Craft 3 Docs but it still doesn't seem to work. Was hoping someone could see what I can't. Here is the code I'm using for my form.
{% macro errorList(errors) %}
{% if errors %}
<ul class="errors">
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
{% from _self import errorList %}
<form method="post" accept-charset="UTF-8">
{{ csrfInput() }}
<input type="hidden" name="action" value="entries/save-entry">
{{ redirectInput('viewentry/{slug}') }}
<input type="hidden" name="work" value="2">
<input type="hidden" name="enabled" value="1">
<label for="title">Title</label>
<input id="title" type="text" name="title"
{%- if entry is defined %} value="{{ entry.title }}"{% endif -%}>
{% if entry is defined %}
{{ errorList(entry.getErrors('title')) }}
{% endif %}
<label for="fields-projectDescription">Project Description</label>
<textarea id="fields-projectDescription" name="fields[projectDescription]">
{%- if entry is defined %}{{ entry.projectDescription }}{% endif -%}
</textarea>
<input type="submit" value="Publish">
</form>
The error I recieve when this form is submitted is:
Bad Request Request - missing required body param
Screenshot of Error
I though this could mean I was required to keep the 'body' field form the example. eg.
<label for="body">Body</label>
<textarea id="body" name="fields[body]">
{%- if entry is defined %}{{ entry.body }}{% endif -%}
</textarea>
{% if entry is defined %}
{{ errorList(entry.getErrors('body')) }}
{% endif %}
However, adding this in made no difference.
Any help appreciated.
You are missing sectionId in your form:
<input type="hidden" name="sectionId" value="{{ craft.sections.getSectionByHandle('sectionHandle').id }}">

Sub-navigation in Grav CMS

I want to make a subnav for my Grav Theme. I already saw a question on this topic:
GRAV subnavigation
{% block navigation %}
{% macro loop(page) %}
{% for p in page.children %}
{% if p.visible %}
{% set active_page = (p.active or p.activeChild) ? 'active' : '' %}
<div>
<a href="{{ p.url }}" class="btn btn-nav" role="button">
{{ p.menu }}
</a>
{% if p.children.count > 0 %}
<div class="dropdown">
<a href="{{ p.url }}" class="btn btn-nav dropdown-toggle" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
{{ p.menu }}
<span class="icon icon--bottom"></span>
</a>
<div class="dropdown-menu" aria-labelledby="dropdownMenulink" x-placement="bottom-start">
{{ _self.loop(p) }}
</div>
</div>
{% endif %}
</div>
{% endif %}
{% endfor %}
{% endmacro %}
{% endblock %}
<div class="topics" style="display: flex;">
{{ _self.loop(pages) }}
</div>
The problem I ran into is that with my code the pages get listed two times in the navigation and that's because of the a-tag in the dropdown div.
Is there a way that I can have the a-tag in the dropdown with all the information I wrote in my code? And that it only appears once in the navigation.
Thanks for your answers!
{% block navigation %}
{% macro loop(page) %}
{% for p in page.children %}
{% if p.visible %}
{% set active_page = (p.active or p.activeChild) ? 'active' : '' %}
<div>
{% if p.children.count > 0 %}
<div class="dropdown">
<a href="{{ p.url }}" class="btn btn-nav dropdown-toggle" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
{{ p.menu }}
<span class="icon icon--bottom"></span>
</a>
<div class="dropdown-menu" aria-labelledby="dropdownMenulink" x-placement="bottom-start">
{{ _self.loop(p) }}
</div>
</div>
{% else %}
<a href="{{ p.url }}" class="btn btn-nav" role="button">
{{ p.menu }}
</a>
{% endif %}
</div>
{% endif %}
{% endfor %}
{% endmacro %}
{% endblock %}
<div class="topics" style="display: flex;">
{{ _self.loop(pages) }}
</div>
This is the code I used instead of what I wrote in my question

How to close newsletter popup automatically after signup - Shopify

I am not a programming expert so bear with me.
I have put up a shopify site with the template Icon-Christian. It comes with newsletter popup. The thing is that after signing up, the popup window doesn't close automatically. How can I edit the code?
{% if settings.popup %}
<script type="text/javascript">
if($(window).width() > 500){
// Fancybox Join our mailing list popup
$(document).ready(function(){
var check_cookie = $.cookie('mailing_list_delay_popup');
if(check_cookie == null){
$.cookie('mailing_list_delay_popup', 'expires_seven_days', { expires: 7 });
//fire your fancybox here
setTimeout(function(){
$.fancybox({
href: "#subscribe_popup"
});
}, 3000);
}
});
};
</script>
{% endif %}
<div style="display:none">
<div id="subscribe_popup" class="row">
{% if settings.email_popup_image %}
<div class="left fifty">
<img src="{{ 'popup-image.jpg' | asset_url }}">
</div>
{% endif %}
<div class="right fifty">
<h3>{{ 'layout.homepage.mailing_list_join' | t }}</h3>
<p>{{ 'layout.homepage.mailing_list_text' | t }}</p>
<!-- BEGIN #subs-container -->
<div id="subs-container" class="clearfix">
<div id="mc_embed_signup">
<form action="{{ settings.mailchimp }}" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank">
<input value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="{{ 'general.newsletter_form.newsletter_email' | t }}" required="" type="email">
<input value="{{ 'general.newsletter_form.submit' | t }}" name="subscribe" id="mc-embedded-subscribe" class="button" type="submit">
</form>
</div>
</div>
<div class="clear"></div>
<ul id="footer-icons">
{% if settings.show_facebook %}<li><i class="icon-facebook icon-2x"></i></li>{% endif %}
{% if settings.show_twitter %}<li><i class="icon-twitter icon-2x"></i></li>{% endif %}
{% if settings.show_pinterest %}<li><i class="icon-pinterest icon-2x"></i></li>{% endif %}
{% if settings.show_tumblr %}<li><i class="icon-tumblr icon-2x"></i></li>{% endif %}
{% if settings.show_youtube %}<li><i class="icon-youtube icon-2x"></i></li>{% endif %}
{% if settings.show_googleplus %}<li><i class="icon-google-plus icon-2x"></i></li>{% endif %}
{% if settings.show_instagram %}<li><i class="icon-instagram icon-2x"></i></li>{% endif %}
</ul>
</div>
</div>
</div>

Create form in popup in Shopify (callback function)

I added form to button (in left top in header) https://en.partizanstore.eu/
I checked form in page and it works, but when I added form to snippet and to button, it dont work, dont send letter.
Can anybody help?
And by the way, can I create form anywhere, except on pages?
{% capture contact_form %}
<div class="contact">
{% form 'contact', class: 'contact__form' %}
{% if form.posted_successfully? %}
<div class="alert alert--success">
<span class="alert-title">{{ 'contact.form.successfully_sent' | t }}</span>
</div>
{% endif %}
{% if form.errors %}
<div class="alert alert--error">
<span class="alert__title">{{ 'general.forms.errors' | t }}</span>
{% include 'form_errors' %}
</div>
{% endif %}
<div class="form__control">
<label class="form__label" for="contact__name">{{ [ 'contact.form.name' | t }}</label>
<input type="text" id="contact__name" name="contact[name]">
</div>
<div class="form__control">
<label class="form__label" for="contact__phone">{{ 'contact.form.phone' | t }}</label>
<input type="text" id="contact__phone" name="contact[phone]">
</div>
<input type="submit" class="button button--primary" value="{{ 'contact.form.submit' | t }}">
{% endform %}
</div>
{% endcapture %}

Bootstrap 3: formatted checkboxes with Symfony & Twig

How to create a formatted group of checkboxes as described in the Bootstrap documentation using the Symfony Form Factory and Twig?
Using something like
<div class="row">
<div class="col-lg-4">
{{ form_label(form.sample) }}
</div>
<div class="col-lg-8">
{{ form_widget(form.sample) }}
</div>
</div>
will not result in the needed output:
a) each checkbox within a Bootstrap 3 structure like:
<div class="radio">
<label>
<input type="radio" ... />Option one
</label>
</div>
b) in addition the ability to output the checkboxes in two or more columns if needed:
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="radio"> ... </div>
</div>
<div class="col-lg-6 col-md-6">
<div class="radio"> ... </div>
</div>
</div>
The proper way to do this is to create your own form theme. I will not write the whole thing here, but what matters to you are those:
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }} class="my-form-choices">
{% for child in form %}
{{ form_widget(child) }}
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
{% block checkbox_widget %}
{% spaceless %}
<div class="checkbox">
<label for="{{ id }}"><input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans({}, translation_domain) }}</label>
</div>
{% endspaceless %}
{% endblock checkbox_widget %}
I removed the label rendering from the choice_widget_expanded so I could have the checkbox inside the label tag, just like what you have in your solution. But you can basically do whatever you want in your form theme. You can also overwrite radio_widget if you want to.
If you look closely at the div around the checkboxes, I gave it the class "my-form-choices". You could give it the classes you want. It could be "col-lg-8", like you have, but for me, it makes more sense to have a generic class name, and then use mixins in your own less file. Your less file would look like this:
#import '../../../../../../vendor/twitter/bootstrap/less/bootstrap.less';
.my-form-row {
.make-row();
}
.my-form-choices {
.make-lg-column(8);
}
.my-form-row-label {
.make-lg-column(4);
}
But that's up to you. You don't have to do this if you don't want to. Finally, you use your theme by starting the twig for your page like this:
{% extends 'MyOwnBundle::layout.html.twig' %}
{% form_theme form 'MyOwnBundle:Component:formtype.html.twig' %}
And you display the row simply like that (the field I used in my test is availability, yours is sample):
{{ form_row(form.availability) }}
I've tried that (with Symfony 2.4), and it works. The output is something like that:
<div class="my-form-row">
<div class="my-form-row-label">
<label class="required">Availability</label>
</div>
<div class="my-form-choices" id="myown_website_contactmessage_availability">
<div class="checkbox">
<label for="myown_website_contactmessage_availability_0">
<input type="checkbox" value="morning" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_0">
Morning
</label>
</div>
<div class="checkbox">
<label for="myown_website_contactmessage_availability_1">
<input type="checkbox" value="afternoon" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_1">
Afternoon
</label>
</div>
<div class="checkbox">
<label for="myown_website_contactmessage_availability_2">
<input type="checkbox" value="evening" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_2">
Evening
</label>
</div>
</div>
</div>
Also notice that I do not have sub-rows, like you have in your solution. In fact, your solution goes beyond the question you were asking in the first place.
EDIT: here's a solution for having multiple columns
To have multiple columns, here is a quick solution. First, the form theme could be something like this:
{% block choice_widget_expanded %}
{% spaceless %}
<div class="my-form-choices-container">
<div {{ block('widget_container_attributes') }} class="my-form-choices">
{% for child in form %}
{{ form_widget(child) }}
{% endfor %}
</div>
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
{% block checkbox_widget %}
{% spaceless %}
<div class="my-form-choice">
<div class="checkbox">
<label for="{{ id }}"><input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans({}, translation_domain) }}</label>
</div>
</div>
{% endspaceless %}
{% endblock checkbox_widget %}
And then your less file would look like this:
#import '../../../../../../vendor/twitter/bootstrap/less/bootstrap.less';
.my-form-row {
.make-row();
}
.my-form-row-label {
.make-lg-column(4);
}
.my-form-choices-container {
.make-lg-column(8);
}
.my-form-choices {
.make-row();
}
.my-form-choice {
.make-md-column(6);
}
In this solution, you change the number of columns by changing the size of the columns. The cells should stack neatly. In this case, it is better to compile less (I won't explain that here). I have tried this solution, and it works well. The advantage of using less in this case, is that you can use the same form theme on multiple pages, and change the number of columns just by having a different "less" file for each of your pages.
You need to access to the form vars which contain the information about the checkboxes:
form.sample.vars.form.children
now you can loop through the checkboxes and access the values:
{% for children in form.sample.vars.form.children %}
<div class="checkbox>
<label>
<input type="checkbox" name="{{ children.vars.full_name }}" id="{{ children.vars.id }}" value="{{ children.vars.value }}"{% if children.vars.data %} checked="checked"{% endif %} />
{% if children.vars.label is defined %}
{{ children.vars.label|trans }}
{% else %}
{{ children.vars.value|capitalize|trans }}
{% endif %}
</label>
</div>
{% endfor %}
I place this code in a Twig template and add some logic to create rows with variable columns, so it look like this:
{% set cols = columns|default(1) %}
{% set i = 1 %}
{% for children in childrens %}
{% if i == 1 %}<div class="row">{% endif %}
<div class="col-lg-{{ 12/cols }} col-md-{{ 12/cols }}">
<div class="checkbox {{ class|default('') }}">
<label>
<input type="checkbox" name="{{ children.vars.full_name }}" id="{{ children.vars.id }}" value="{{ children.vars.value }}"{% if children.vars.data %} checked="checked"{% endif %} />
{% if children.vars.label is defined %}
{{ children.vars.label|trans }}
{% else %}
{{ children.vars.value|capitalize|trans }}
{% endif %}
</label>
</div>
</div>
{% set i = i+1 %}
{% if i > cols %}
</div>
{% set i = 1 %}
{% endif %}
{% endfor %}
{% if i != 1 %}</div>{% endif %}
now you can include this checkbox template where you need it:
<div class="row">
<div class="col-lg-4">
{{ form_label(form.sample) }}
</div>
<div class="col-lg-8">
{% include 'checkbox.twig' with {childrens:form.sample.vars.form.children, columns:2} only %}
</div>
</div>
the example above will return well formatted Bootstrap 3 output with checkboxes in two columns like this:
<div class="row">
<div class="col-lg-4">
<label class="required">Veranstalter</label>
</div>
<div class="col-lg-8">
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="checkbox ">
<label><input type="checkbox" name="form[sample][]" id="form_sample_0" value="DUMMY">Dummy</label>
</div>
</div>
<div class="col-lg-6 col-md-6">
<div class="checkbox ">
<label><input type="checkbox" name="form[sample][]" id="form_sample_1" value="DUMMY_1">Dummy 1</label>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="checkbox ">
<label><input type="checkbox" name="form[sample][]" id="form_sample_2" value="DUMMY_2">Dummy 2</label>
</div>
</div>
</div>
It's easy to use and will also work for radio buttons - just replace the class "checkbox" with "radio".
Ran into this issue today and thought I'd share my solution. I already had a form input override file, but didn't like what I found elsewhere. So wrote a form_label block override like so.
{% block form_label -%}
{% if label is not sameas(false) -%}
{% if not compound -%}
{% set label_attr = label_attr|merge({'for': id}) %}
{%- endif %}
{% if required -%}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
{%- endif %}
{% if label is empty -%}
{% set label = name|humanize %}
{%- endif -%}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{% if 'checkbox' in block_prefixes %}{{ form_widget(form) }}{% endif %}{{ label|trans({}, translation_domain) }}</label>
{%- endif %}
{%- endblock form_label %}
Then the form_row block like so:
{% block form_row %}
{% spaceless %}
{% if 'checkbox' not in block_prefixes %}
<div class="form-group">
{{ form_label(form) }}
{{ form_errors(form) }}
{% if 'datetime' not in block_prefixes %}
{{ form_widget(form, { 'attr': {'class': 'form-control'} }) }}
{% else %}
{{ form_widget(form) }}
{% endif %}
</div>
{% else %}
{% import _self as forms %}
<div class="checkbox">
{{ form_label(form) }}
</div>
{% endif %}
{% endspaceless %}
{% endblock %}
I choose this method because it allowed me to continue to use the basic form(form) method in templates. Hope this helps you.
If you're looking for the simple version of this answer (ie you've already applied the bootstrap_3_layout theme to your form and just want to apply custom label text)
{{ form_widget( form.field, { 'label': 'Custom Label Text' } ) }}