Django/Bootstrap template rendering - python

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

How can I set form field value in a template in django forms?

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 %}

Custom widget for a RadioField Wtforms used inside a Flask app not set CHECKED

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 %}"

Force a hidden input to return a fixed value

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] }}">

Python, Flask Method Not Allowed

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.

Django FormPreview and ImageField, Image not displayed

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.

Categories

Resources