I'm currently coding a website using Django and Bootstrap.
I created the templates and models first, and now, I'm implementing the controllers. All is not implemented yet, but I needed some help on this. I was wondering how to render a Django authentication form with the Boostrap grid system. I'm using Boostrap 4 and Django 2.0.4. My older form was like this :
<div class="jumbotron">
<form class="form-horizontal" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
<div class="col-lg-4 offset-lg-4">
<label class="control-label" for="usernameInput">{{ form.username.label_tag }}</label>
<input id="usernameInput" type="text" name="{{ form.field.html_name }}" value="{{ form.username }}" class="form-control"
placeholder="Username">
</div>
</div>
<div class="form-group">
<div class="col-lg-4 offset-lg-4">
<label class="control-label" for="passwordInput">{{ form.password.label_tag }}</label>
<input id="passwordInput" type="password" name="{{ form.field.html_name }}" value="{{ form.field.value }}" class="form-control"
placeholder="Password">
</div>
</div>
<div class="container" id="btn_login">
<button type="submit" class="btn btn-primary btn-md" value="login" role="button">Log in</button>
<input type="hidden" name="next" value="{{ next }}"/>
</div>
</form>
<span class="container" id="forgotten_password">
Forgot your password ?
</span>
</div>
And here is the new one :
<div class="jumbotron">
{% load widget_tweaks %}
<form class="form-horizontal" method="post" action="{% url 'login' %}">
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
<div class="container" id="btn_login">
<button type="submit" class="btn btn-primary btn-md" role="button">Log in</button>
</div>
</form>
<span class="container" id="forgotten_password">
Forgot your password ?
</span>
</div>
But as you can obviously tell, this is not rendering the same way.
For example, I'd like to take back the width of the input.
For the rest, I use this line in my urls.py
re_path(r'^login/$', auth_views.login, {'template_name': 'main/login.html'}, name='login'),
And this one in my settings.py to get redirected to the right page :LOGIN_REDIRECT_URL = 'my_pls'
I googled a lot and finally used this link (in case you case notice something I didn't understand) : https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html#understanding-the-rendering-process
You should use custom HTML attributes on your **forms.py**.
It's simple:
from django import forms
class your_form(forms.Form):
attrs_for_the_field = {
'class': 'form-control',
'placeholder': 'Write here!',
}
field = forms.CharField(widget=forms.CharField(attrs=attrs_for_the_field))
With this code you will render the following HTML:
<input type="text" name="field" class="form-control" placeholder="Write here!" id="id_field">
Take a look at https://docs.djangoproject.com/en/2.0/ref/forms/widgets/ in order to know how Django represents an HTML input element.
You also should read https://docs.djangoproject.com/en/2.0/ref/forms/fields/ so that you could understand how it works.
You can add all the HTML configuration for the fields in the form code in forms.py . Than the form can be displayed with just {{ form.as_p}}.
Width of input can be retrieved with jQuery or JavaScript .
Related
So, here I have a piece of HTML code that is supposed to render a form using django form class. I have several forms on one page, they are rendered in 'for' cycle and should have different values as default (appointment.id). How can I set a value of a field here inside a template? Is in at least possible?
{% for appointment in appointments%}
{% load crispy_forms_tags %}
<form action="/register/" method="post" class="inline">
{% csrf_token %}
<div class="form-group w-25">
<div class="col-sm-10">
{{form.appointment_id|as_crispy_field}}
</div>
<input type="submit" class="btn btn-primary mt-1" value="Register">
</div>
</form>
</p>
{% endfor %}
You can do it in that way:
{% for appointment in appointments%}
{% load crispy_forms_tags %}
<form action="/register/" method="post" class="inline">
{% csrf_token %}
<div class="form-group w-25">
<div class="col-sm-10">
{{ form.appointment_id(value=appointment.id)|as_crispy_field }}
</div>
<input type="submit" class="btn btn-primary mt-1" value="Register">
</div>
</form>
</p>
{% endfor %}
I have a problem on a custom widget for a RadioField Wtforms used inside a Flask app.
The custom widget is rendered well, but it DOES NOT WORK because it does not set the "checked" on the field after choosing it. If instead I use the default widget everything is fine and it works.
I also tried another more standard way, that is the "real" custom widget called inside the form class definition ... but I have the exact same result.
Below is the code, any suggestions? Thanks :-)
#### ROUTE
bp = Blueprint('auth', __name__, url_prefix='/auth')
#bp.route('/generic_crud', methods=('GET', 'POST'))
#login_required
def generic_crud():
form = forms.BaseGenericForm()
if form.validate_on_submit():
# Insert the msg
models.BaseGenericFormTable.add_record( title_select = form.titleSelect.data,
title_radio = form.titleRadio.data,
title_checkbox = form.titleCheckbox.data )
return render_template('sample_wtforms/success.html')
return render_template('sample_wtforms/crud_generic.html', form=form)
#### FORM
class BaseGenericForm(FlaskForm):
titleSelect = SelectField( 'Title Select',
validators=[DataRequired(message='Title Select missed')],
choices=[ ('farmer' , 'Farmer'),
('politician', 'Corrupt Politician'),
('cop', 'No-nonsense City Cop'),
('rocket', 'Professional Rocket League Player'),
('lonely', 'Lonely Guy At A Diner'),
('pokemon', 'Pokemon Trainer')],
render_kw={"class":"custom-select"}
)
titleRadio = RadioField('Title Radio',
validators=[DataRequired(message='Title RadioBox missed')],
choices=[ ('farmer' , 'Farmer'),
('politician', 'Politician'),
('cop', 'No-nonsense Cop'),
('lonely', 'Lonely Guy'),
('pokemon', 'Trainer')]
)
titleCheckbox = RadioField('Title Checkbox',
validators=[DataRequired(message='Title CheckBox missed')],
choices=[ ('farmer' , 'Farmer'),
('politician', 'Politician'),
('cop', 'No-nonsense Cop'),
('lonely', 'Lonely Guy'),
('pokemon', 'Trainer')]
)
submit = SubmitField( 'Submit',
render_kw={"class":"btn btn-primary"}
)
#### TEMPLATE jinja2
{% block content %}
<form method="POST" class="container">
<!-- titleSelect -->
<div class="form-group row">
{{ form.titleSelect.label(class='col-4 col-form-label') }}
<div class="col-8">
{{ form.titleSelect }}
{% if form.titleSelect.errors %}
<div class="alert alert-danger" role="alert">
<ul class="errors">
{% for error in form.titleSelect.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
</div>
<!-- titleRadio -->
<div class="form-group row">
{{ form.titleRadio.label(class='col-4 col-form-label') }}
<div class="col-8">
{#{{ form.titleRadio }}#}
{% for value, label, selected in form.titleRadio.iter_choices() %}
<div class="custom-control custom-radio custom-control-inline">
<input id="radio{{ loop.index0 }}" name="titleRadio" type="radio" class="custom-control-input" value="{{ value }}" {% if selected %} checked="checked" {% endif %}>
<label for="radio{{ loop.index0 }}" class="custom-control-label">{{ label }}</label>
</div>
{% endfor %}
{% if form.titleRadio.errors %}
<div class="alert alert-danger" role="alert">
<ul class="errors">
{% for error in form.titleRadio.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
</div>
<!-- titleCheckbox ################################################ -->
<div class="form-group row">
{{ form.titleCheckbox.label(class='col-4 col-form-label') }}
<div class="col-8">
{#{{ form.titleCheckbox }}#}
{% for value, label, selected in form.titleCheckbox.iter_choices() %}
<div class="custom-control custom-checkbox custom-control-inline">
<input id="checkbox{{ loop.index0 }}" name="checkbox" type="checkbox" class="custom-control-input" value="{{ value }}" {% if selected %} checked="checked" {% endif %}>
<label for="checkbox{{ loop.index0 }}" class="custom-control-label">{{ label }}</label>
</div>
{% endfor %}
{% if form.titleCheckbox.errors %}
<div class="alert alert-danger" role="alert">
<ul class="errors">
{% for error in form.titleCheckbox.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
</div>
{{ form.csrf_token }}
<div class="form-group row">
<div class="offset-4 col-8">
{{ form.submit }}
</div>
</div>
</form>
{% endblock %}
For a custom widget I do:
<div id="{{ field.id }}">
{{ field.label(class="form-label") }}<br>
{% for subfield in field %}
<div class="form-check form-check-inline">
<input {% if subfield.checked %}checked {% endif %}type="radio" class="form-check-input" id="{{ subfield.id }}" name="{{ field.id }}" value="{{ subfield.id[-1] }}">
{{ subfield.label(class="form-check-label") }}
</div>
{% endfor %}
</div>
The relevant part for you should be "{% if subfield.checked %}checked {% endif %}"
The following is my current code:
{% for comment in commentlist %} <!-- Comment section -->
<h5>
{{ comment[0] }}
</h5>
<h6>Created {{ comment[1].strftime('%d/%m/%Y at %I:%M%p') }} By: {{ comment[2] }}</h6>
{% if session.username == comment[2] %}
<form action="{{ url_for('detail', slug=entry.slug) }}" class="form-horizontal" method="post">
<input class="form-control" name="commentid" type="hidden">
<div class="form-group">
<div class="col-sm-offset-0 col-sm-1">
<button class="btn btn-default1" type="submit">Delete!</button>
</div>
</div>
</form>
{% endif %}
<br></br>
{% endfor %}
When the button it pressed it should return the value of
{{ comment[3] }}
This value I should then be able to fetch from Flask in the form of
request.form.get('commentid')
Any ideas of how this could be done would be much appreciated!
<input class="form-control" name="commentid" type="hidden" value="{{ comment[3] }}">
I am currently learning python and am trying to write an app. I have the basics done. I followed a tutorial which was helpful but have gotten stuck. My understanding is 100% up to scratch yet so any help and reasoning behind it would be great.
I am getting a Method Not Allowed Error when trying to submit a form. I will post the code below and hopefully someone can help.
new_action.py
{% extends "base.html" %}
{% block content %}
<h2>New Action Request</h2>
{% include 'flash.html' %}
<div class="well">
<form class="form-horizontal" action="" method="post" name="post">
{{ form.hidden_tag() }}
<div class="control-group{% if form.errors %} error{% endif %}">
<label class="pull-right" for="post">Date: {{
datetime.date(datetime.utcnow()) }}</label>
<div class="controls">
{{form.timestamp}}
</div>
<label class="control-label" for="post">Raised By:</label>
<div class="controls">
{{ form.raised_by }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
<br/>
<label class="control-label" for="post">Source:</label>
<div class="controls">
{{ form.source }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
<br/>
<label class="control-label" for="post">Category:</label>
<div id="radios1" class="controls" data-toggle="buttons-radio">
<button type="button" class="btn active" name="health_safety" value="health_safety">Health &
Safety</button>
<button type="button" class="btn" name="quality" value="quality">Quality</button>
<input type="hidden" name="category" value={{request.form['category']}} />
</div><br/>
<br/>
<label class="control-label" for="post">Sub-Category:</label>
<div class="controls">
{{ form.sub_category }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
<br/>
<label class="control-label" for="post" width="80%" >Description:</label>
<div class="controls" >
{{ form.issue }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
<br/>
<label class="control-label" for="post">Immediate Action:</label>
<div class="controls">
{{ form.immediate_action }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn btn-primary" type="submit" value="Submit Action Request">
</div>
</div>
</form>
</div>
{% endblock %}
Views.py
#app.route('/new_action', methods=['GET', 'SET'])
#login_required
def new_action():
form = ActionRequestForm()
if request.method == 'POST':
return redirect(url_for('index'))
#actionrequest = ActionRequest(id = form.id.data, category = form.category.data)
'''post = Post(body=form.post.data, timestamp=datetime.utcnow(),
author=g.user)
db.session.add(post)
db.session.commit()
flash('Your post is now live!')'''
return render_template('new_action.html',
user = user,
form = form,
datetime = datetime
)
Your form is trying to POST data to the server. This is a HTTP POST request. You define GET and SET methods in your view. You need to use POST there.
#app.route('/new_action', methods=['GET', 'POST']) # Changed SET to POST here
#login_required
def new_action():
# ... what ever...
You should go through this RFC for HTTP. There is no SET-method.
#app.route('/new_action', methods=['GET', 'SET'])
This line of code is only allowing "GET" and "SET" methods, while you are trying to "POST" to that route.
Have form.
class AddLogo(forms.Form):
title = forms.CharField(max_length=100)
date = forms.TimeField()
image = forms.ImageField()
And have standard Django preview form.
from django.contrib.formtools.preview import FormPreview
from django.http import HttpResponseRedirect
from company.models import Company
class add_logo_preview(FormPreview):
form_template = 'add_logo_preview.html'
def done(self, request, cleaned_data):
return HttpResponseRedirect('/company/hey/')
In template
{% extends "base.html" %}
{% block block_js %}
{% endblock block_js %}
{% block content %}
<h1>Preview your submission</h1>
{% with form as job %}
<div class="job_block">
<div class="job_content">
<div class="job_title">
<h1>{{ job.title.data }}</h1>
<span class="date">{{ job.date.date.data }}</span>
</div>
<div class="job_company">
<div class="company_logo">
{{ job.image.url }}
</div>
<div class="company_description">
<div class="name">{{ job.company_name.data }}</div>
<div class="location">Главный офис: {{ job.company_location.data }}</div>
<div class="website">{{ job.company_url.data }}</div>
</div>
</div>
<article>
{{ job.description.data|safe }}
</article>
</div>
<aside>
<h4>Поделиться вакансией</h4>
</aside>
</div>
<div class="job_feedback">
<h3>Откликнутся на вакансию</h3>
<p>{{ job.apply_terms.data|safe }}</p>
</div>
{% endwith %}
<p>Security hash: {{ hash_value }}</p>
<form action="" method="post">{% csrf_token %}
{% for field in form %}{{ field.as_hidden }}
{% endfor %}
<input type="hidden" name="{{ stage_field }}" value="2" />
<input type="hidden" name="{{ hash_field }}" value="{{ hash_value }}" />
<p><input type="submit" value="Submit" /></p>
</form>
<h1>Or edit it again</h1>
<h1>Шаг первый: создайте свое объявление</h1>
<form action="/job/preview/" method="POST" class="form">{% csrf_token %}
<h3>Опишите вакансию</h3>
<fieldset>
<div class="label_box">
<label for="">Назавние вакансии</label>
</div>
<div class="fields_box">
{{ form.title }}
</div>
</fieldset>
<fieldset>
<div class="label_box">
<label for="">Категория</label>
</div>
<div class="fields_box">
{% for cat in form.category %}
{% if cat.choice_value %}
{{ cat }}
{% endif %}
{% endfor %}
</div>
</fieldset>
<fieldset>
<div class="label_box">
<label for="">Головной офис</label>
</div>
<div class="fields_box">
{{ form.company_location }}
</div>
</fieldset>
<fieldset class="one_col">
<div class="label_box">
<label for="">
Описание вакансии
</label>
</div>
<div class="fields_box">
{{ form.description }}
</div>
</fieldset>
<fieldset>
<div class="label_box">
<label for="">
Apply this job.
</label>
</div>
<div class="fields_box">
{{ form.apply_terms }}
</div>
</fieldset>
<h3>О компании</h3>
<fieldset>
<div class="label_box">
<label for="">Название</label>
</div>
<div class="fields_box">
{{ form.company_name }}
</div>
</fieldset>
<fieldset>
<div class="label_box">
<label for="">Логотип</label>
</div>
<div class="fields_box">
{{ form.image }}
</div>
</fieldset>
<fieldset>
<div class="label_box">
<label for="">URL</label>
</div>
<div class="fields_box">
{{ form.company_url }}
</div>
</fieldset>
<fieldset>
<div class="label_box">
<label for="">Email</label>
</div>
<div class="fields_box">
{{ form.company_email }}
</div>
</fieldset>
<fieldset>
<div class="label_box">
<span>
Подсветить это объявление?
</span>
<label for="">{{ form.highlight }} Подсветить?</label>
</div>
</fieldset>
<input type="submit" value="Просмотреть">
</form>
{% endblock %}
I try: {{ form.image.url }} but does not work. I understand one: Django do not upload file, but how i cane change this? How i can make preview image in django FormPreview?
Convert your image to a base64 string, add a field to your form for that base 64 string. In the preview template, display the base64 string. And when finally saving the image, you will need to create a file, write the content of the base 64 string to it, and then save that file to your model.