I'm stumped at the moment on what to do here. I have a Flask server where an app.route has a list called "addresses" that gets passed to rendered page customeraddresses.html to be displayed.
The goal is to show the user the list displayed by checkboxes so they can check the ones they would like to remove from the list. Currently I'm displaying a list of checkboxed items for the user to check, but I'm not sure how to grab everything that the user wants to remove.
How can I pass everything to app.route /removelistitems that the user checked?
Any assistance would be greatly appreciated.
app.py
from flask import Flask, render_template, request
import requests
import json
app = Flask(__name__)
...
...
#app.route('/customeraddresses', methods=["POST"])
def currentaddresses():
customername = request.form.get("customername")
addresses = ['1.1.1.1', '2.2.2.2', '3.3.3.3', '4.4.4.4']
return render_template("/customeraddresses.html", customername=customername, addresses=addresses)
#app.route('/removelistitems', methods=["POST"])
def removeitems():
thingstoremove= request.form.get('thingstoremove')
currentaddresses.html
...
...
<form action="/removelistitems" method="POST">
<div class="row">
<div class="col">
</div>
<div class="col-md-11">
{% for address in addresses %}
<div class="form-group">
<label for="existing_{{address}}" class="control-label col-sm-2">{{address}}</label>
<input type="checkbox" name="existing_{{address}}"/>
<br/>
</div>
{% endfor %}
<button type="submit" [disabled]="!name" class="btn btn-secondary">Submit</button>
</div>
<div class="col">
</div>
</div>
</form>
...
...
Related
so the basic goal of my project is to allow teachers and admin to login to the system and take attendance for the students. my new issue is that i have a view function that is suppose to check to see if students student is already added to the respective class and if they are it will exclude them from the drop down menu and display the students who aren't in the class but it not doing that instead it is showing me a blank drop down menu. the way i have it set up is that the admin clicks the add student button then it will convert a .html page to modal which brings up the list of students to select from. When i add the form responsible for saving the student to the class in the Django admin it work perfect but i cant seem to get it to work in the user section Ui. I am new to Django and this is my first project so any help is really appreciated
Views
#check to see if students already exist in class and display those who aint to be added
#login_required
def manage_class_student(request, classPK=None):
if classPK is None:
messages.warning(request,'Class ID is Unknown')
else:
context['classPK'] = classPK
_class = Room.objects.get(id=classPK)
# print(ClassStudent.objects.filter(classIns = _class))
students = Student.objects.exclude(id__in=ClassStudent.objects.filter(classIns=_class).values_list('student').distinct()).all()
context['students'] = students
return render(request, 'manage_class_student.html', context)
#save the students to the respective class after being selected
#login_required
def save_class_student(request):
form = SaveClassStudent()
if request.method == 'POST':
form = SaveClassStudent(request.POST)
if form.is_valid():
form.save()
messages.success(request, "Student has been added successfully.")
redirect('class_detail')
else:
messages.error(request, 'Error Adding student in class')
template with the form to show the available students
<!-- Modal -->
<div class="modal fade" {% block modal-id %} id="addModal{{class.pk}}" {% endblock%} data-bs-backdrop="static"
data-bs-keyboard="false" tabindex="-1" aria-labelledby="addModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h6 class="modal-title" id="addModalLabel"> {% block modal-title%}<i class="fas fa-plus"></i> Add
Student To Class{% endblock%}</h6>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="container-fluid">
<form {% block action %} action="{% url 'save-class-student' %}" {% endblock%} method="post">
{% csrf_token %}
<div class="modal-body">
<input type="hidden" name="classIns" value="{{ classPK }}">
<div class="form-group mb-3">
<label for="student" class="control-label">Student</label>
<select name="student" id="student" class="form-select rounded-0 select2" required>
<option disabled selected></option>
{% for student in students %}
<option value="{{ student.id }}">{{ student }}</option>
{% endfor %}
</select>
</div>
<div>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
What triggers the modal
<div class="tools">
<button type="button" class="btn btn-secondary border rounded-0 bg-gradient btn-sm"
id='print_attendance_report'><i class="fa fa-print"></i> Print Attendance Report</button>
<a data-bs-toggle="modal" data-bs-target="#addModal{{class.pk}}"> <button type="button"
class="btn btn-primary rounded-0 bg-gradient btn-sm" id='add_new'><i class="fa fa-plus"></i>
Add Student</button></a>
</div>
form that save students to classroom
class SaveClassStudent(forms.ModelForm):
classIns = forms.IntegerField()
student = forms.IntegerField()
class Meta:
model = ClassStudent
fields = ('classIns', 'student')
def clean_classIns(self):
cid = self.cleaned_data['classIns']
try:
classIns = Room.objects.get(id=cid)
return classIns
except:
raise forms.ValidationError("Class ID is Invalid.")
def clean_student(self):
student_id = self.cleaned_data['student']
_class = Room.objects.get(id=self.data.get('classIns'))
student = Student.objects.get(id=student_id)
try:
cs = ClassStudent.objects.get(classIns=_class, student=student)
if len(cs) > 0:
raise forms.ValidationError(
f"Student already exists in the Class List.")
except:
return student
This question has “grown” from Django Model Field for html5 Range Slider but is specific and different enough to warrant its own question, I believe, rather than continue in the comments section.
The aim of the original post was to write Django code that would render and display a slider in the webpage. That has been done. The challenge that this question relates to is writing the value of the slider to a field in a table/model. I will first show code for a table/model update that works then show how far I have got displaying the slider and showing where I am stuck. I am giving all this detail rather than just asking for a fix, because I am trying to understand how the Django code works - and by trying to explain it hopefully you can correct my misunderstandings.
First I will show the code I have copied and modified that just displays textboxes that the View(?) form(?) takes the input values and write a new record to the table. I will describe my understanding of the various parts of the view and the form.
Then I will show the code I have to display the slider and how it differs from the working code – which is where I need help to write data to the table/model.
My template, create.html, that works contains:
<form method="POST">
{% csrf_token %}
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label for="question">Enter Survey Question</label>
{% render_field form.q_text rows="3" class="form-control" %}
</div>
</div>
</div>
<div class="row">
<div class="col-lg-5">
<div class="form-group">
<label for="Choice1_text ">Choice 1</label>
{% render_field form.Choice1_text class="form-control" %}
<label for="C1_type">Type 1</label>
{% render_field form.C1_Type class="form-control" %}
</div>
</div>
<div class="col-lg-5">
<div class="form-group">
<label for="option2">Choice 2</label>
{% render_field form.Choice2_text class="form-control" %}
<label for="C2_type">Type 2</label>
{% render_field form.C2_Type class="form-control" %}
</div>
</div>
</div>
<div class="row">
<hr />
<div class="col-lg-4">
<button type="submit" class="btn btn-info">Submit</button>
</div>
</div>
</div>
</form>
My understanding the form will be “interpreted” by the view as a POST.
The input fields which appear on the rendered webpage as input boxes, are coded in the template as in the following examples:
<label for="question">Enter Survey Question</label>
<label for="Choice1_text ">Choice 1</label>
<label for="C1_type">Type 1</label>
(There are other inputs)
Are “passed back” to the View(?) form(?) via the {% render_field
{% render_field form.q_text rows="3" class="form-control" %}
{% render_field form.Choice1_text class="form-control" %}
{% render_field form.C1_Type class="form-control" %}
There are other {% render_field
The
form.q_text
form.Choice1_text
form.C1_Type
are the names of the fields in the table/model to be updated by the data typed in the boxes on the webpage.
in forms.py, there is:
from django import forms
… deleted lines …
class AnyForm(forms.ModelForm):
class Meta:
model = CC_Questions
fields = ['q_text', 'Choice1_text', 'Choice2_text','C1_Type','C2_Type']
where:
class AnyForm(forms.ModelForm):
indicates this is a “modelForm” which is “used unmodified” in a view(?) template(?) will result in a collection of boxes to accept input being displayed on the screen, without any formatting.
the:
model = CC_Questions
is the name of the model/table to which data will be written
the:
fields = ['q_text', 'Choice1_text', 'Choice2_text','C1_Type','C2_Type']
Are the fields that will display input boxes in the template and will be the fields where the data is written in the model when data is input in the webpage. This form may not display all of the fields in the model if they do not all require a value from this form.
The view is:
def p2create(request):
if request.method == 'POST':
form = AnyForm(request.POST)
if form.is_valid():
form.save()
return redirect('/polls/p2')
else:
form = AnyForm()
context = {'form' : form}
return render(request, 'pollapp2/create.html', context)
Since the template contained the line
<form method="POST">
the code below
if request.method == 'POST':
will evaluate as True resulting in the form, AnyForm, being "used"
form = AnyForm(request.POST)
if the form is valid (how can a form be “invalid??)
if form.is_valid():
then save the values that the template “passes back” to the form (??) via the
{% render_field form.<field name>
The form “passes back” values to the view (??) via the
model =<model name>
fields = [“<field1>”, “<field2>”, ….]
and the view writes to the model (??) via the
form.save()
The next web page to be displayed is
return redirect('/polls/p2')
So that is my best understanding of how working code writes data to a table.
Now follows is the code I have working to display a slider, and the slider value, when I press the “Try it” button. The code successfully displays the value corresponding to the position of the slider on the underlying range. However, from the following I can’t work out what code I need to modify to “trap” the value of “myint” and write it to the appropriate field in a new record in the model.
Template that displays the slider:
<!-- p2slider.html -->
{% extends "pollapp2/base.html" %}
<!-- load widget tools to give me more control over layout of form in template -->
{% load widget_tweaks %}
{% block title %}P2Slider test{% endblock %}
{% block main %}
<div class="row">
<div class="col-lg-8 col-lg-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">P2Slider test</h3>
</div>
<div class="panel-body">
{% render_field form.RangeInput class="SliderForm" %}
{{form.myint}}
<label for="myint">Input Value</label>
<!-- https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_range_value2 -->
<p>Click the button to display the value of the value attribute of the slider control.</p>
<button onclick="myFunction()">Try it</button>
<p id="slider_val"></p>
<script>
function myFunction() {
var x = document.getElementById("id_myint").value;
document.getElementById("slider_val").innerHTML = x;
}
</script>
<!-- end -->
</div>
<div class="panel-footer">
Data here
</div>
</div>
</div>
</div>
{% endblock %}
Form that “relates” to this template. I notice that this code doesn’t use ModelForm
# attempt at range input slider
#
from polls.widgets import RangeInput
#
class SliderForm(forms.Form):
myint = forms.IntegerField(widget=RangeInput)
View I have copied and modified from the view for “Create” but I guess is wrong because I don’t have a model form:
def p2slider(request):
if request.method == 'POST':
form = SliderForm(request.POST)
if form.is_valid():
form.save() # ??????
context = {'form' : form} # ????
return render(request,'pollapp2/p2slider.html',context)
else:
form = SliderForm()
context = {'form' : form} # ??????
return render(request,'pollapp2/p2slider.html', context)
So I’m guessing I need to change the view function p2slider to the relevant model, cc_resp_nofk. But I don’t know what to code.
This is a simple Form, so there is no .save() method (since it is unclear what that would mean). You can obtain the value with the form.cleaned_data:
def p2slider(request):
if request.method == 'POST':
form = SliderForm(request.POST)
if form.is_valid():
slider_value = form.cleaned_data['myint']
# do something …
else:
form = SliderForm()
context = {'form' : form}
return render(request,'pollapp2/p2slider.html', context)
or if you want to use it in a ModelForm, you can plug this in as the widget of a form field:
class SomeModelForm(forms.ModelForm):
class Meta:
model = SomeModel
fields = ['intfield']
widgets = {
'intfield': RangeInput
}
If SomeModel thus has an intfield as field, you can use the RangeInput as widget for that field, and then .save() that form.
I am a Django newbie who is trying to convert an existing HTML based website to Django 3. The only complex piece of this page is a call to a Django method that uses the django.core.mail package and everything works, but, I am trying to pull some data off of the HTML template and pass it to this method.
The method works, only it sends a blank email. I am trying to pass contact information that the end user would fill out on the form. If I hard code the data into the method it works.
I have tried passing the data through urls.py, but, everything I try fails to even parse when I call the method. When I use a request.GET.get everything seems to work, just no data.
I was hoping to use something similar to JQuery like the following in the method.
name = str(request.GET.get('Name:', '').strip())
email = str(request.GET.get('Email:', '').strip())
msg1 = str(request.GET.get('Message:', '').strip())
with the fields being in the HTML form.
I am going to include some of the relevant configuration items below.
urls.py
from django.urls import path
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from . import views
app_name = 'willdoit'
urlpatterns = [
path('', views.index),
#url(r'^contact/(?P<name>\.+)/(?P<email>\.+)/(?P<msg1>\.+)/?$', views.contact, name='contact'),
path('contact/', views.contact, name='contact'),
]
views.py
def contact(request):
name1 = request.GET.get('name', '')
email1= request.GET.get('email', '')
msg1 = request.GET.get('message1', '')
subject = 'Work needed'
from_email = settings.DEFAULT_FROM_EMAIL
message = name + ' ' + email + ' ' + msg1
recipient_list = ['pkustra914#gmail.com']
send_mail(subject, message, from_email, recipient_list, fail_silently=False)
return HttpResponse('Success')
Relevant HTML Template section
<div class="contact_content">
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="contact_message wow fadeInLeft" data-wow-duration="1.5s">
<form action="#" id="formid">
<form action="#" id="formid">
<div class="form-group"> <input class="form-control" name="name"
placeholder="Name" required="" type="text"> </div>
<div class="form-group"> <input class="form-control" name="email"
placeholder="Email" required="" type="email"> </div>
<div class="form-group">
<div class="Descrizione"> <label for="InserisciDescrizione"
class=""><b>Message</b></label> <textarea class="form-control"
id="message" placeholder="Type message:" name="message1" rows="6" cols="50"
title="Message"></textarea> </div>
<a id="submit" href="{% url 'willdoit:contact' %}" class="btn btn-primary">Submit</a>
I would prefer to use the request.GET.get method, but, there is a lot more documentation passing it through the urls.
Thanks.
Your code request.GET.get('Name:', '') returns empty string when the key 'Name:' is not found.
To fix this, use request.GET.get('name', '') request.GET.get('email', '') request.GET.get('message', '') instead.
Details
I see that you are using a with template tag for nothing. The following line of code does not change the name attribute string to PascalCase. See with template tag (Docs)
{% with Name=name Email=email Message=message %}
Even if it worked, your code should be calling request.GET.get('Name', '') instead of request.GET.get('Name:', ''). But it won't work, as with would not modify the attribute names in the GET request.
#EDIT1
There are apparently more bugs in your html code. I have reformatted your code and listed up some obvious bugs.
<!--REFORMATTED CODE-->
<form action="#" id="formid"> <--------------DUPLICATES, remove one
<form action="#" id="formid"> <--------------DUPLICATES, remove one
<div class="form-group"> <input class="form-control" name="name"
placeholder="Name" required="" type="text"> </div>
<div class="form-group"> <input class="form-control" name="email"
placeholder="Email" required="" type="email"> </div>
<div class="form-group">
<div class="Descrizione">
<label for="InserisciDescrizione" class=""><b>Message</b></label>
<textarea class="form-control" id="message"
placeholder="Type message:" name="message1" rows="6" cols="50"
title="Message"></textarea>
</div>
<a id="submit" href="{% url 'willdoit:contact' %}"
class="btn btn-primary">Submit</a>
<-------- MISSING DIV END TAG
<-------- MISSING FORM END TAG
Furthermore, you are calling the server by url directly using the following code:
<a id="submit" href="{% url 'willdoit:contact' %}" class="btn btn-primary">Submit</a>
This does not tell the page which form you want to submit (there are cases where there are multiple forms).
You have two choices:
Replace the tag with standard html form submit button <input type="submit">, and add the url to the action attribute of the form. Use the following code to do so:
<form action="{% url 'willdoit:contact' %} id="formid">
...
...
<input id="submit" type="submit" class="btn btn-primary" value="Submit"/>
</form>
This solution will by default use the GET method to send a request to the server, and you will be able to get the inputted values by calling request.GET.get(name).
If you are using JQuery, you can replace the with the following:
Submit
This is however not recommended. Please use the standard html form input tag for the submit button.
Great. Moving the method call to the form tag worked great.
Thanks! You guys are the best.
I'm using for authentication extended AbstractUser and ModelForm. When I write on HTML page only {{ form }} everything works fine, the form is submitting, but in the following case I've added some stylings, but now nothing works. Please, help me find the reason.
HTML:
<form method='POST'>
{% csrf_token %}
<div class="sign-up-user">
<div class="sign-up-user-container">
<div class="sign-up-user-left">
<label for="">{{form.username.label}}</label>
{{form.username}}<br>
<label for="">{{form.password.label}}</label>
{{form.password}}<br>
<label for="">{{form.branch.label}}</label><br>
{{form.branch}}<br>
<label for="">{{form.license_number.label}}</label>
{{form.license_number}}<br>
<label for="">{{form.fin_number.label}}</label>
{{form.fin_number}}<br>
<label for="">{{form.voen_number.label}}</label>
{{form.voen_number}}<br>
</div>
</div>
<input type="submit" value="Register User" class="sign-up-btn">
</div>
</form>
Include two lines to your HTML to understand whats going wrong:
{{ form.errors }}
{{ form.non_field_errors }}
This will display any errors that are associated with the form. If they dont then in your views do the following:
form = YourForm()
if form.is_valid():
// Do things
else:
print (form.errors)
print(form.non_field_errors)
This will display some other errors that you are missing.
I have created a website based on the 'Build A Live Table Using Flask' with pusher from this example: https://pusher.com/tutorials/live-table-flask
Everything is working fantastic with the exception of one thing. For a few of my values instead of having the user enter their own value I am using a dropdown list of values for them to select between. When they go to edit the entry, all values are remembered except this which is changing back to the default value. I need a way for this value to be remembered and selected when they go to edit the part.
Code used to create/edit job (same for both html)
backend.html
{% extends 'base.html' %}
{% block content %}
<form method="POST" id="target">
<div class="form-group">
<input type="text" class="form-control" name="work" placeholder="Work No">
</div>
<div class="form-group">
<label for='opt'>Choose Option</label>
<select name='opt'>
<option value='Option 1'>Option 1</option>
<option value='Option 2'>Option 2</option>
<option value='Option 3'>Option 3</option>
<option value='Option 4'>Option 4</option>
</select>
</div>
<button type="submit" class="btn btn-block btn-primary">Submit</button>
</form>
{% endblock %}
update.html
{% extends 'base.html' %}
{% block content %}
<form method="POST" id="target">
<div class="form-group">
<input type="text" class="form-control" name="work" value="{{ data.work }}">
</div>
<div class="form-group">
<label for='opt'>Choose Option</label>
<select name='opt'>
<option value='Option 1'>Option 1</option>
<option value='Option 2'>Option 2</option>
<option value='Option 3'>Option 3</option>
<option value='Option 4'>Option 4</option>
</select>
</div>
<button type="submit" class="btn btn-block btn-primary">Submit</button>
</form>
{% endblock %}
app.py
from flask import Flask, request, jsonify, render_template, redirect
import pusher
from database import db_session
from models import Work
import os
app = Flask(__name__)
...
#app.route('/edit/<int:id>', methods=["POST", "GET"])
def update_record(id):
if request.method == "POST":
work = request.form["work"]
opt = request.form["opt"]
update_work = Work.query.get(id)
update_work.work = work
update_work.opt = opt
db_session.commit()
data = {
"id": id,
"work": work,
"opt": opt}
pusher_client.trigger('table', 'update-record', {'data': data })
return redirect("/active", code=302)
else:
new_work = Work.query.get(id)
new_work.opt = new_work.opt #do I need this?
return render_template('update.html', data=new_work)
models.py
from sqlalchemy import Column, Integer, String, DateTime
from database import Base
class Work(Base):
__tablename__ = 'works'
id = Column(Integer, primary_key=True)
work = Column(String(50))
opt = Column(String(120))
def __init__(self, work=None, opt=None):
self.work = work
self.opt = opt
def __repr__(self):
return '<Work %r>' % (self.work)
Wanting to be able to edit entries and have the dropdown list auto select the correct option, not the default option, so when editing you don't have to reenter all the values again.
You should be using WTForms instead of building this form yourself. It has a built-in SelectField. Once you do that, you'll be able to populate the options either where the form is defined (if the options are static) or in the view in question (update_record here). Example:
from flask import request, redirect
from flask_wtf import FlaskForm
from wtforms import SelectField
from operator import itemgetter
class WorkForm(FlaskForm):
opt = SelectField('Choose Option', coerce=int, choices=[(num, f"Option {num}") for num in range(1, 5)])
# ... etc ...
#app.route('/edit/<int:id>', methods=["POST", "GET"])
def edit(id):
form = WorkForm(request.form)
if form.validate_on_submit():
# Do things
return redirect(url_for('active'), code=302)
new_work = Work.query.get(id)
opt_id = 0
for choice in form.opt.choices:
if choice[1] == new_work.opt:
opt_id = choice[0]
form.opt.data = opt_id
return render_template('update.html', data=new_work)
Don't forget to use {{ form.hidden_tag() }} in the template inside your form. This will give you CSRF protection, which your present form doesn't have.
Also, backend.html and update.html seem to be nearly identical. It shouldn't be difficult to use a single file for these. E.g.:
{% if data is defined %}
<input type="text" class="form-control" name="work" value="{{ data.work }}">
{% else %}
<input type="text" class="form-control" name="work" placeholder="Work No">
{% endif %}