Django (HTML) - Clickable label in template (not working) - python

I'm working on a Django project where I would like using some customized checkbox forms when this issue shown up. Both code chunks are exactly the same, but using different forms. The issue comes when the first's sample label is clickable (so I can hide the radio button), but the second one is not working as expected, the user must click on the radio button, if I hide it the whole label becomes useless.
WORKING PROPERLY:
<form action="" class="form-group" method="POST">
<div class="modal-body">
<div class="row">
<div class="col">
<ul>
{% csrf_token %}
<fieldset >
{% for radio in form_emp.producto %}
<li style="list-style-type:none">
<span class="radio">{{ radio.tag }}
<label class="label" for="{{ radio.id_for_label }}">
{{ radio.choice_label }}
</label>
</span>
</li>
{% endfor %}
</fieldset>
</ul>
</div>
<div class="col">
{{form_emp.cantidad.label}}
{{form_emp.cantidad}}
{{form_emp.observaciones.label}}
{{form_emp.observaciones}}
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-light" type="button" data-bs-dismiss="modal">Volver</button>
<input type="submit" class="btn btn-primary" value="Agregar" />
</div>
NOT WORKING PROPERLY:
<form action="" class="form-group" method="POST">
<div class="modal-body">
<div class="row">
<div class="col">
<ul>
{% csrf_token %}
<fieldset >
{% for radio in form_pizzas.producto %}
<li style="list-style-type:none">
<span class="radio">{{ radio.tag }}
<label class="label" for="{{ radio.id_for_label }}">
{{ radio.choice_label }}
</label>
</span>
</li>
{% endfor %}
</fieldset>
</ul>
</div>
<div class="col">
{{form_pizzas.cantidad.label}}
{{form_pizzas.cantidad}}
{{form_pizzas.observaciones.label}}
{{form_pizzas.observaciones}}
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-light" type="button" data-bs-dismiss="modal">Volver</button>
<input type="submit" class="btn btn-primary" value="Agregar" />
</div>
FORMS.PY
#WORKING FORM
class CartEmpanadasForm(ModelForm):
lista_prod=Producto.objects.filter(categoria=1)
producto=forms.ModelChoiceField(widget=forms.RadioSelect, queryset=lista_prod)
class Meta:
model=Cart
fields=["producto","cantidad","observaciones"]
#NOT WORKING FORM
class CartPizzasForm(ModelForm):
#LISTA DE PRODUCTOS, FILTRO POR CATEGORÍA
lista_prod=Producto.objects.filter(categoria=2)
#MOSTRAR LOS ELEMENTOS COMO UN CHOICEFIELD
producto=forms.ModelChoiceField(widget=forms.RadioSelect, queryset=lista_prod)
class Meta:
model=Cart
fields=["producto","cantidad","observaciones"]
CSS File
label{
width: 100%;
border: 3px solid #1881f9;
position: relative;
margin: 5% 5% 5% 5%;
border-radius: 10px;
background-color: rgb(178, 201, 243);
transition: 5ms;}
input[type="radio"]:checked+label{
background-color: orange;
border: 6px solid #f95818;
box-shadow: 5px 5px rgb(178, 201, 243);}
I hope you guys could help me figure out what is going on there! Thank you so much in advance! Have a nice week!

The issue was that I was showing more than one form in the same view, as default the form's tag-id are "id_columnname_n", so the multiple forms weren't allowing to identify the tags properly. The label id was repeated.
I solved introducing customized ids in the forms.py file and setting manually every label-tag in the template.
FORMS.py
class CartEmpanadasForm(ModelForm):
#LISTA DE PRODUCTOS, FILTRO POR CATEGORÍA
lista_prod=Producto.objects.filter(categoria=1)
#MOSTRAR LOS ELEMENTOS COMO UN CHOICEFIELD
producto=forms.ModelChoiceField(widget=forms.RadioSelect(attrs={'name': 'empanada','id':'empanada'}), queryset=lista_prod)
class Meta:
model=Cart
fields=["producto","cantidad","observaciones"]
VIEW.html
<fieldset >
{% for radio in form_emp.producto %}
<li style="list-style-type:none">
<span class="radio">{{ radio.tag }}
<label class="label" for="empanada_{{forloop.counter0}}">
{{ radio.choice_label }}
</label>
</span>
</li>
{% endfor %}

Related

How to associate form with a `bootstrap_field` outside that form?

Given this field {% bootstrap_field form.photo %} which is a forms.ImageField and the form after, I need to associate the field with the form in a way that when the form is submitted, I get the value in form.photo.
<div class="row container h-100">
<div class="col-xl-4">
<div class="card mb-4 mb-xl-0">
<div class="card-body text-center">
<img style="max-width: 50%" alt="Avatar" class="img-account-profile rounded-circle mb-2"
src={{ request.user.profile.photo.url }}>
{% bootstrap_field form.photo %}
</div>
</div>
</div>
<div class="col h-100">
<div class="card shadow-lg">
<div class="card-body p-5">
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
<div class="row">
<span class="col">
{% bootstrap_field form.first_name %}
</span>
<span class="col">
{% bootstrap_field form.last_name %}
</span>
<button class="btn btn-success col">Update</button>
</div>
</form>
</div>
</div>
</div>
</div>
Currently if a photo is uploaded, it won't show up in the form response because it's not included within <form></form>. I need it to be outside the form because the locations of the form fields and the photo are different.
One way to do so is to wrap both cards inside the form tags. Is this the best way to do it or is there a simpler way like specifying {% bootstrap_field my_field form=my_form %}

How to create multiple Submit buttons with Flask forms?

Problem : I want to do the whole thing with the Form_Setting class in the forms.py file. Here I have defined the 4 submit buttons. I then use the buttons in the settings.html. In the routes.py file I want to react when they are pressed. However, at the moment it is still so that I can react with form.validate_on_submit() only generally on the submit. How can I distinguish which of the submit buttons were pressed to then perform different actions?
routes.py
from page import app
from flask import render_template, redirect, url_for
from page.models import Settings
from page.forms import Form_Setting
from page import db
#app.route('/settings', methods=['GET','POST'] )
def Settings_Page():
form = Form_Setting()
if form.validate_on_submit():
save_email = Settings(email_adress=form.email_adress.data)
db.session.add(save_email)
db.session.commit()
return redirect(url_for('Settings_Page'))
return render_template('settings.html',form=form)
forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
class Form_Setting(FlaskForm):
email_adress = StringField(label='Email')
dooralarm_time = StringField(label='Türalarm')
minimum_temp = StringField(label='MinTemp')
maximum_temp = SubmitField(label='MaxTemp')
submit_email = SubmitField(label='Eingabe')
submit_door = SubmitField(label='Eingabe')
submit_temp_max = SubmitField(label='Eingabe')
submit_temp_min = SubmitField(label='Eingabe')
settings.html
{%extends 'base.html' %}
{% block ActivSettings%}
active
{% endblock %}
{% block css %}
<link rel="stylesheet" type="text/css" href="{{url_for('static',filename='css/style.css')}}"/>
{% endblock %}
{% block title %}
Einstellungen
{% endblock %}
{% block content %}
<div>
<div class="container">
<h1 class="setting-page">Einstellungen</h1>
<!--Email Adresse-->
<div class="row ">
<div class="col-sm-12">
<div class="d-flex justify-content-start align-items-center" style="height: 8vh;">
<div class="col-sm-3 ">
<h3 class="setting-label">E-mail</h3>
</div>
<div class="col-sm-9">
<form method="POST" class="form-register flex-fill d-flex" >
<!--Schutz gegen CSRF-->
{{ form.hidden_tag() }}
{{ form.email_adress(class="form-control", placeholder="E-Mail") }}
{{ form.submit_email(class="btn btn-md btn-block btn-primary", style="background-color: #6941c6; border:none; color: #f9f5ff; margin-left: 1vw;" )}}
</form>
</div>
</div>
<hr class="divider">
</div>
</div>
<!--Türalarm Zeitintervall-->
<div class="row ">
<div class="col-sm-12">
<div class="d-flex justify-content-start align-items-center" style="height: 8vh;">
<div class="col-sm-3 ">
<h3 class="setting-label">Türalarm Zeitintervall</h3>
</div>
<div class="col-sm-9">
<form method="POST" class="form-register flex-fill d-flex" >
<!--Schutz gegen CSRF-->
{{ form.hidden_tag() }}
{{ form.dooralarm_time(class="form-control", placeholder="Zeitintervall") }}
{{ form.submit_door(class="btn btn-md btn-block btn-primary", style="background-color: #6941c6; border:none; color: #f9f5ff; margin-left: 1vw;" )}}
</form>
</div>
</div>
<hr class="divider">
</div>
</div>
<!--Temp. Schwellwert Minimal-->
<div class="row ">
<div class="col-sm-12">
<div class="d-flex justify-content-start align-items-center" style="height: 8vh;">
<div class="col-sm-3 ">
<h3 class="setting-label">Temp. Schwellwert Minimal</h3>
</div>
<div class="col-sm-9">
<form method="POST" class="form-register flex-fill d-flex" >
<!--Schutz gegen CSRF-->
{{ form.hidden_tag() }}
{{ form.dooralarm_time(class="form-control", placeholder="Temp. Minimal") }}
{{ form.submit_temp_max(class="btn btn-md btn-block btn-primary", style="background-color: #6941c6; border:none; color: #f9f5ff; margin-left: 1vw;" )}}
</form>
</div>
</div>
<hr class="divider">
</div>
</div>
<!--Temp. Schwellwert Maximal-->
<div class="row ">
<div class="col-sm-12">
<div class="d-flex justify-content-start align-items-center" style="height: 8vh;">
<div class="col-sm-3 ">
<h3 class="setting-label">Temp. Schwellwert Maximal</h3>
</div>
<div class="col-sm-9">
<form method="POST" class="form-register flex-fill d-flex" >
<!--Schutz gegen CSRF-->
{{ form.hidden_tag() }}
{{ form.dooralarm_time(class="form-control", placeholder="Temp. Maximal") }}
{{ form.submit_temp_min(class="btn btn-md btn-block btn-primary", style="background-color: #6941c6; border:none; color: #f9f5ff; margin-left: 1vw;" )}}
</form>
</div>
</div>
<hr class="divider">
</div>
</div>
</div>
</div>
{% endblock %}
Webseite
The result for the page
You can iterate through request.form using the variable name of the submit button.
from flask import request
if 'submit_email' in request.form:
# do something
elif 'submit_door' in request.form:
# do something
Be sure that the form will still validate properly form.validate_on_submit()

Flask apply filter with multiple checkboxes

Hey good people of stackoverflow,
My application randomly selects a recipe from MongoDB (using pymongo) and displays it to the user.
My intention is to be able to apply filters (vegetarian, fish, beef and so on) to the next "random" selection after hitting Something else button.
I think I can achieve it by using request.form.getlist and creating the form in the pick_meal.html but it feels a bit overkill.
So far I am unable to figure it out.
Any help would be greatly appreciated.
The html and python function looks like this:
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h3>{% block title %} You should cook: {% endblock %}</h3>
<div class="row">
<div class="col-md-5 align-self-center text-center">
<span>{{ dish.dish_name }}</span>
</br>
</br>
<a class="btn btn-outline-success" href="{{ dish['dish_source'] }}" role="button">Go to web</a>
</div>
<div class="col-md-4">
<img src="{{ dish.dish_image }}" width="250px">
</div>
</div>
</br>
<div class="row">
<div class="col-md-5">
<button class="btn btn-primary">Something else</button>
<button class="btn btn-primary">Configrm choice</button>
<button class="btn btn-primary">Already cooked</button>
</div>
<div class="col-md-5">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="vegetarian" id="flexCheckDefault" name="property_checkbox">
<label class="form-check-label" for="flexCheckDefault">Vegetarian</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="grill" id="flexCheckDefault" name="property_checkbox">
<label class="form-check-label" for="flexCheckDefault">Grill</label>
</div>
</div>
</div>
</div>
{% endblock %}
#app.route('/pick_meal/<string:dish_type>')
def pick_meal(dish_type):
# pick random meal based on category
dish = list(coll.aggregate([
{'$match':{
'cooked': False,
'dish_type': dish_type}},
{ '$sample':{
'size': 1 } }]))[0]
return render_template('pick_meal.html', dish=dish, dish_type=dish_type)

How to connect 2 forms in HTML and Django?

I am creating a web page and i'm wondering if i could make sure that the data on the left is filled before pressing the blue button. On the left you can see a form to pay by entering your address, city etc. but on the right you can see another form with stripe implemented to pay with credit card. I don't know how to get the data from the left and save it in the database so I can create a receipt after successful payment. Here is the code down below.
<div class="container-2">
<div class="gray-hover">
<form method="POST">
<div class="item" id="payment">
<div class="row">
<h4>Možnost nakupa 1: Plačilo po povzetju <small><i>(Za plačevanje s kartico je treba izbrati samo
količino in vrsto izdelka!)</i></small></h4>
{% csrf_token %}
{% if form %}
<div class="input-group">
<div style="color: red;">{{ form.name.errors }}</div>
{{ form.name }}
</div>
<div class="input-group">
<div style="color: red;">{{ form.last_name.errors }}</div>
{{ form.last_name }}
</div>
<div class="input-group">
<div style="color: red;">{{ form.street_name.errors }}</div>
{{ form.street_name }}
</div>
<div class="input-group">
<div style="color: red;">{{ form.city_name.errors }}</div>
{{ form.city_name }}
</div>
<div class="input-group">
<div style="color: red;">{{ form.email.errors }}</div>
{{ form.email }}
</div>
<div class="input-group">
<div style="color: red;">{{ form.number.errors }}</div>
{{ form.number }}
</div>
{% endif %}
</div>
</div>
<div class="item" id="payment2">
<div class="row">
<div class="input-group">
{{ form.num_elements.errors }}
{{ form.num_elements }}
</div>
<div class="input-group" id="check_div">
<div
style="display: flex;width:100%;justify-content: space-between;align-items: center;font-size:medium;flex-wrap: wrap;">
<div style="display: flex;justify-content: space-between;margin:3px;">
{{ form.select_type.errors }}
{{ form.select_type.label_tag }}
{{ form.select_type }}
</div>
<div style="display: flex;justify-content: space-between;margin:3px;">
{{ form.select_type2.errors }}
{{ form.select_type2.label_tag }}
{{ form.select_type2 }}
</div>
</div>
</div>
<div class="input-group">
{{ form.warning_el.errors }}
{{ form.warning_el }}
</div>
<div style="display: flex;justify-content: space-between;margin: 0.5rem;">
<button class="button" type="submit" id="button"> Naroči <small>(povzetje)</small></button>
<a class="button" id="stripe-button">Plačaj s kartico!</a>
</div>
</div>
</div>
</form>
</div>
<div class="gray-hover">
<div class="item" id="payment3" style="width:100%;">
<h4>Možnost nakupa 2: Plačilo s kartico <small><i>(Za plačevanje s kartico je treba izbrati samo
količino in vrsto izdelka!)</i></small></h4>
<div class="row" style="display: flex; justify-content: center;">
<form id="payment-form" data-locale="si" style="width:100%;">
<div id="payment-element">
<!--Stripe.js injects the Payment Element-->
</div>
<button id="submit" class="button1">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Plačaj</span>
</button>
<div id="payment-message" class="hidden"></div>
</form>
</div>
</div>
</div>
</div>
AND HERE IS THE SCREENSHOT OF THAT 'CONTAINER-2'
Firstly make sure all your inputs are under one form and one view.
Use required=True in your Django form in order to make sure every input is entered.
If you are using Django forms, for example
from django import forms
class FooForm(forms.Form):
email = forms.EmailField(max_length=100,required=True,
widget=forms.TextInput(
attrs={ 'required': 'true' }),
)
In your view use the form is_valid method
form = FooForm(request.POST)
if form.is_valid():
# Complete Your Business Logic
...
return redirect("redirect_view")
# Else Return With Error Message
Use the form to save your data. If using Django form is not an option, you have to use javascript to disable the button until all inputs are not filled up

Why does this weird "content" attribute has no file associated with it error comes up in Django?

This question might have been asked several times before but I referred to them but I was not able to fix my problem. That is why I am having to ask it. So, I have a Django app where users can set up tasks. They can also upload attachments. I was successfully able to implement this but for some reason it has stopped working now. These are the relevant code:
models.py
def get_attachment_dir(instance, filename):
return f"users/{instance.parent_task.creator.username}_{instance.parent_task.creator.pk}/task_attachments/{instance.parent_task.pk}/{filename}"
class Attachments(models.Model):
content = models.FileField(null=True, blank=True, upload_to=get_attachment_dir, help_text="Add important documents or pictures")
parent_task = models.ForeignKey(ToDo, on_delete=models.CASCADE)
uploaded_on = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"Attachments of {self.parent_task.title}"
forms.py
class TaskAttachmentForm(forms.ModelForm):
class Meta:
model = Attachments
fields = ["content"]
Relevant part of the view function that renders the attachment form
if request.method == "POST":
attachment_form = TaskAttachmentForm(request.POST, request.FILES)
if attachment_form.is_valid():
# Making sure we get no Integrity Errors
attachment_form.instance.parent_task = todo
attachment_form.save()
if not todo.has_attachments:
todo.has_attachments = True
todo.save()
messages.success(request, "Your files were uploaded successfully")
else:
attachment_form = TaskAttachmentForm()
attachments = Attachments.objects.filter(parent_task=todo)
context = {
"todo": todo,
"note_form": ToDoNotesForm(),
"note": note,
"subtask_form": SubTaskForm(),
"attachment_form": attachment_form,
"subtasks": subtasks,
"due_form": DueDateForm(),
"title": todo.title,
"percentage": percentage,
"attachments": attachments
}
return render(request, "ToDo/detailed_view.html", context=context)
detailed_view.html relevant code where attachments are handled
{% if attachments %}
<div id="attachments-section" class="table-responsive dark-mode-assist-section">
<table class="table dark-mode-assist-section">
<thead>
<tr>
<th>File</th>
<th>Uploaded on</th>
<th>View/Download</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for attachment in attachments %}
<tr class="list-group-item" id="attachment-{{ attachment.pk }}">
<td>{{ attachment.content|getfilename }}</td>
<td>{{ attachment.uploaded_on|date:"F d"}}</td>
<td><a class="btn btn-success" href="{{ attachment.content.url }}">Click me</a></td>
<td>
<button style="font-size: 2.5ch;" data-toggle="modal" data-target="#exampleModalCenter{{ attachment.pk }}" class="btn btn-outline-danger">
<i class="fa fa-trash"></i>
</button>
</td>
</tr>
<div class="modal fade" id="exampleModalCenter{{ attachment.pk }}" tabindex="-1" role="dialog"
aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content dark-mode-assist-section">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Confirm the deletion</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure you want to delete this attachment?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button data-dismiss="modal" onclick="deleteItem('attachment', {{ attachment.pk }})" type="submit"
class="btn btn-danger">Yes, I am sure</button>
</div>
</div>
</div>
</div>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<a class="btn btn-outline-info" data-toggle="collapse" href="#multiCollapseExample-attachments" role="button"
aria-expanded="false" aria-controls="multiCollapseExample">
Upload attachments
</a>
<div class="row">
<div class="col">
<div class="collapse multi-collapse" id="multiCollapseExample-attachments">
<br>
<div class="card card-body dark-mode-assist-section">
<div class="content section">
<form method="POST" name="attachment-{{ todo.pk }}" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group dark-mode-assist">
<legend class="border-bottom mb-4">Add documents</legend>
{{ attachment_form|crispy }}
<input type="hidden" name="title" value={{ todo.pk }}>
<p id="hidden-parent-task-pk" style="display:none">{{ todo.pk }}</p>
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info btn-lg" type="submit"><i class="fas fa-upload"></i></button>
</div>
</form>
</div>
</div>
</div>i
</div>
</div>
I am saying that this seems weird is because I was able to access attachment.content when running the same command under python manage.py shell
Any help is seriously appreciated and needed. Thanks a lot.

Categories