How to update form element data value after construction using multidict - python

I have a website post creator / editor im writing. I have successfully been able to create post (saves to json) , get a pull down menu list of the made post from same db (and a second, all posts.json, which is where the list of posts comes from. ), and have the element forms populated with said information. I can then save it, and it is indeed writing to the file. Problem is , the data in the text fields is not updating in saved post. It saves the original data passed with the multidict. I CAN manually update it as : Ex. form.title.data = "New Title" , and it saves as such, so i know its handling everything correctly on the save end. If anyone has an idea how to get the updated information from the form fields, id be grateful. Thank you.
Constructors at line 103
Code:
https://hastebin.com/lafavifike.py
from flask import Flask, render_template, request, flash, redirect, url_for
from QFlask import QFlask
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired
from wtforms.fields import Field, TextAreaField, TextField, SelectField
from wtforms.widgets import TextArea
import os, json
from werkzeug.datastructures import MultiDict
app = Flask(__name__)
app.config['SECRET_KEY'] = "test"
class editPostForm(FlaskForm):
id_pos = ['blog_posts', 'security_posts', 'game_posts','music_posts','project_posts']
file_path_all = str(os.getcwd()) + "\\static\\allposts.json"
with open(file_path_all, 'r') as post_edit:
all_posts = json.load(post_edit)
posts = [('default', 'Choose Post To Edit')]
for key in all_posts.keys():
if key not in id_pos:
posts.append((all_posts[key]['id'], all_posts[key]['title']))
loadform = SelectField('Choose Post', choices=posts)
loadposts = SubmitField('Load')
class PostForm(FlaskForm):
#Actual form fields
categories = [('blog_posts','Blog Post'), ('security_posts','Security Post'),('game_posts','Games Post'),('music_posts','Music Post'),('project_posts','Projects Post')]
category = SelectField('Category', choices = categories, validators = [DataRequired()])
title = StringField('Title', validators=[DataRequired()])
date = StringField('Date', validators=[DataRequired()])
content = TextAreaField('Content', validators=[DataRequired()], widget=TextArea())
submit = SubmitField('Submit')
#app.route('/', methods=['POST', 'GET'])
def index():
file_path = str(os.getcwd()) + "\\static\\posts.json"
with open(file_path, 'r+') as post_edit:
data = json.load(post_edit)
positions = {}
for key in data['id_pos'].keys():
positions[key] = data['id_pos'][key]
#Create Post Form
prefixs = {'1':'blog_posts','2':'security_posts',"3":"game_posts","4":"music_posts","5":"project_posts"}
form = PostForm()
edit_form = editPostForm()
if request.method == 'POST':
print(edit_form.loadform.data)
if edit_form.loadform.data != 'None':
return redirect('/edit_post/'+ edit_form.loadform.data)
else:
form.validate()
category = form.category.data
title = form.title.data
date = form.date.data
content = form.content.data
post_id = str(int(positions[category]) +1)
post = {
"id": post_id,
"title": title,
"date": date,
"content": content
}
#Update data structure, and save back to the file
data['id_pos'][category] = post_id
data[category][post_id] = post
#SAVE POST
data['index_posts'][post_id] = post
with open(file_path, 'w') as post_edit:
json.dump(data, post_edit)
print('Post Saved')
flash('Post Saved')
file_path_all = str(os.getcwd()) + "\\static\\allposts.json"
with open(file_path_all, 'r+') as file:
data = json.load(file)
with open(file_path_all, 'w') as file:
data[post_id] = post
json.dump(data, file)
return redirect(url_for('index'))
return render_template('post_editor.html', title="Post Creator", form=form, edit_form = edit_form)
#app.route('/edit_post/<id>', methods=['GET','POST'])
def edit_post(id):
#Load data from JSON Files. posts= categorized posts, allposts is all posts key'd by id.
file_path_all = str(os.getcwd()) + "\\static\\allposts.json"
file_path = str(os.getcwd()) + "\\static\\posts.json"
with open(file_path, 'r+') as post_edit:
data = json.load(post_edit)
with open(file_path_all, 'r') as post_edit:
all_posts = json.load(post_edit)
posts = [('default', 'Choose Post To Edit')]
for key in all_posts.keys():
posts.append((all_posts[key]['id'], all_posts[key]['title']))
#Auto filling category and data for fields
prefixs = {'1':'blog_posts','2':'security_posts',"3":"game_posts","4":"music_posts","5":"project_posts"}
category = prefixs[id[0]]
form = PostForm(MultiDict([("id", id),("title", data[category][str(id)]['title']) ,("date", data[category][str(id)]['date']),("content" , data[category][str(id)]['content'])]))
if request.method == "POST":
form.validate()
data[category][str(id)] = {
'id': str(id),
'title': form.title.data,
'date': form.date.data,
'content': str(form.content.data)
}
all_posts[str(id)] = {
'id': str(id),
'title': form.title.data,
'date': form.date.data,
'content': str(form.content.data)
}
#Write to file.
print('Saving the edited post..')
with open(file_path_all, 'w') as file:
json.dump(all_posts,file)
print('File Saved ')
with open(file_path, 'w') as file:
json.dump(data,file)
flash('File Saved')
return redirect('/')
return render_template('edited_post.html', title="Post Editor", form = form)
if __name__ == '__main__':
QFlask(app).run(title="Web Post Editor", zoom=0, width=600, height= 600)
posteditor.html
<html>
<head><title> Post Editor</title>
<style src="{{url_for('static', filename='css/bootstrap.min.css')}}"></style>
<style>
pre{
content-align: left;
}
body{
color: grey;
background-image: url({{url_for('static', filename='img/editor-bg.jpg')}});
}
</style>
<script src="{{url_for('static', filename='js/jquery.min.js')}}"></script>
<script src="{{url_for('static', filename='js/popper.js')}}"></script>
<script src="{{url_for('static', filename='js/bootstrap.min.js')}}"></script>
</head>
<body>
<div class="container">
{% with message = get_flashed_messages()%}
<ul class="flashes">
{{message}}
</ul>
{% endwith%}
{{ form.csrf_token }}
<form method="POST" action="" id="selection">
<fieldset class="form-group">
<div class="form-group">
{{edit_form.loadform.label(class="form-control-label")}}
{{ edit_form.loadform(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{ edit_form.loadposts(class="btn btn-outline-info")}}
</div>
</fieldset>
</form>
<form method="POST" action="">
<fieldset class="form-group">
<div class="form-group">
{{ form.category.label(class="form-control-label")}}
{{ form.category(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{ form.title.label(class="form-control-label")}}
{{ form.title(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{ form.date.label(class="form-control-label")}}
{{ form.date(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{ form.content.label(class="form-control-label")}}
{{ form.content(cols="50", rows="20",class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</fieldset>
</form>
</div>
</body>
</html>
editedpost.html:
<html>
<head><title> Post Editor</title>
<style src="{{url_for('static', filename='css/bootstrap.min.css')}}"></style>
<style>
pre{
content-align: left;
}
body{
color: grey;
background-image: url({{url_for('static', filename='img/editor-bg.jpg')}});
}
</style>
<script src="{{url_for('static', filename='js/jquery.min.js')}}"></script>
<script src="{{url_for('static', filename='js/popper.js')}}"></script>
<script src="{{url_for('static', filename='js/bootstrap.min.js')}}"></script>
</head>
<body>
<div class="container">
{% with message = get_flashed_messages()%}
<ul class="flashes">
{{message}}
</ul>
{% endwith%}
<form method="POST" action="">
{{ form.csrf_token }}
<fieldset class="form-group">
<div class="form-group">
{{ form.category.label(class="form-control-label")}}
{{ form.category(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{ form.title.label(class="form-control-label")}}
{{ form.title(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{ form.date.label(class="form-control-label")}}
{{ form.date(class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{ form.content.label(class="form-control-label")}}
{{ form.content(cols="50", rows="20",class="form-control form-control-lg")}}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</fieldset>
</form>
</div>
</body>
</html>

I found the answer(with the help of some IRC folk ).The problem was the form data was always pulling from the initialized version. It never requested the update from the page. in data[category][str(id)] = , the values should be updated via request.form.get('title')

Related

I'm trying to create a website for reserving tickets. I need to add as many passengers as needed using one single form. How is that possible?

`#views.route('/flight.html',methods = ['GET','POST'])
def flight():
if request.method == 'POST':
global no_of_passenger
no_of_passengers = request.form.get('no_of_passengers')`
In the above view, I'm getting the passenger count from an earlier html page which I'm using later. I need to get the input from the user as many times as the no_of_passengers.
`#views.route('/passengers.html',methods = ['GET','POST'])
def passenger():
if request.method == 'POST':
return render_template('passengers.html')
return render_template('passengers.html')
#views.route('/passengersinfo.html',methods = ['GET','POST'])
def passenger_information():
passengercount = no_of_passengers
passengercount = int(passengercount)
print(passengercount)
if request.method == 'POST':
for i in range(0,passengercount):
passenger_info = {}
passenger_info['passengername'] = request.form.get('Passenger_Name')
passenger_info['Street'] = request.form.get('Street')
passenger_info['City'] = request.form.get('City')
passenger_info['State'] = request.form.get('State')
passenger_info['ZipCode'] = request.form.get('ZipCode')
return redirect(url_for("views.passenger"))
return render_template('passengersinfo.html')`
In this view I'm trying to run the form as per the user input using a for loop.
The below attached code is the HTML form which is used to get the user form data.
`{% extends 'base.html'%}
{% block title %}Passenger Information Page{% endblock %}
{% block content %}
<form id="Form1" action = 'passengersinfo.html' method = 'POST'>
<div>
<label for ='Passenger_Name' >Passenger Name</label>
<input type = 'text' name = 'Passenger_Name' id='Passenger_Name' id="Form1">
<br>
<label for ='Street' >Street</label>
<input type = 'text' name = 'Street' id='Street' id="Form1">
<br>
<label for ='City' >City</label>
<input type = 'text' name = 'City' id='City' id="Form1">
<br>
<label for ='State' >State</label>
<input type = 'text' name = 'State' id='State' id="Form1">
<br>
<label for ='Zip' >Zip Code</label>
<input type = 'text' name = 'Zip' id='Zip' id="Form1">
</div>
<button type = 'submit' id="Form1" >Next</button>
</form>
{%endblock%}
`
An easy way to implement your requirements is to use Flask-WTF.
Using a FieldList and a FormField, it is possible to create a list of a predefined form.
In this way you create a form for your address details and, depending on the required number, you duplicate this. In addition, you can validate the entries made.
If you only want to display one nested form at a time, you can use JavaScript to navigate forward or back.
The following example uses the session to avoid using global variables and stay as close to your defaults as possible.
Flask
from flask import (
Flask,
redirect,
render_template,
request,
session,
url_for
)
from flask_wtf import FlaskForm, Form
from wtforms import (
FieldList,
FormField,
IntegerField,
StringField,
SubmitField
)
from wtforms.validators import (
InputRequired,
NumberRange
)
app = Flask(__name__)
app.secret_key = 'your secret here'
class PassengersForm(FlaskForm):
passenger_count = IntegerField('Ticket Count',
validators=[NumberRange(min=1)]
)
submit = SubmitField('Next')
class PassengerForm(Form):
name = StringField('Name',
validators=[InputRequired()]
)
street = StringField('Street/No')
city = StringField('City')
state = StringField('State')
zipcode = StringField('Zip')
class PassengerDetailsForm(FlaskForm):
passengers = FieldList(FormField(PassengerForm))
submit = SubmitField()
#app.route('/passengers', methods=['GET', 'POST'])
def passengers():
form = PassengersForm(request.form, data={'passenger_count': 1})
if form.validate_on_submit():
session['count'] = form.passenger_count.data
return redirect(url_for('.passengers_info'))
return render_template('passengers.html', **locals())
#app.route('/passengers-info', methods=['GET', 'POST'])
def passengers_info():
form = PassengerDetailsForm(request.form)
form.passengers.min_entries = max(1, int(session.get('count', 1)))
while len(form.passengers.entries) < form.passengers.min_entries:
form.passengers.append_entry()
if form.validate_on_submit():
for passenger in form.passengers.data:
print(passenger)
return redirect(url_for('.passengers'))
return render_template('passengers_info.html', **locals())
HTML (./templates/passengers.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Passengers</title>
</head>
<body>
<form method="post">
{{ form.csrf_token }}
<div>
{{ form.passenger_count.label() }}
{{ form.passenger_count() }}
{% if form.passenger_count.errors -%}
<ul>
{% for error in form.passenger_count.errors -%}
<li>{{ error }}</li>
{% endfor -%}
</ul>
{% endif -%}
</div>
{{ form.submit }}
</form>
</body>
</html>
HTML (./templates/passengers_info.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Passenger Informations</title>
<style type="text/css">
.step {
display: none;
}
.step.active {
display: block;
}
</style>
</head>
<body>
<form method="post">
{{ form.csrf_token }}
{% for subform in form.passengers -%}
<div class="step {%if loop.first %}active{% endif %}" id="step-{{loop.index0}}">
{% for field in subform -%}
<div>
{{ field.label() }}
{{ field() }}
{% if field.errors -%}
<ul>
{% for error in field.errors -%}
<li>{{ error }}</li>
{% endfor -%}
</ul>
{% endif -%}
</div>
{% endfor -%}
{%if not loop.first %}
<button type="button" class="btn-prev">Prev</button>
{% endif %}
{%if not loop.last %}
<button type="button" class="btn-next">Next</button>
{% else %}
{{ form.submit() }}
{% endif %}
</div>
{% endfor -%}
</form>
<script type="text/javascript">
(function() {
let step = 0;
const btns_next = document.querySelectorAll('.btn-next');
btns_next.forEach(btn => {
btn.addEventListener('click', evt => {
[`step-${step}`, `step-${++step}`].forEach(sel => {
const elem = document.getElementById(sel);
elem && elem.classList.toggle('active');
});
});
});
const btns_prev = document.querySelectorAll('.btn-prev');
btns_prev.forEach(btn => {
btn.addEventListener('click', function(evt) {
[`step-${step}`, `step-${--step}`].forEach(sel => {
const elem = document.getElementById(sel);
elem && elem.classList.toggle('active');
});
});
});
})();
</script>
</body>
</html>

how to us the prefix?

I try to upload two forms with one submit button.
A user can select a pdf file and a excel file. And then uploading both files. And then the contents of both are returned.
So I try to upload both files with one submit button.
But the two selected file options are not visible for uploading the files.
So I have the template like this:
{% extends 'base.html' %} {% load static %} {% block content %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Create a Profile</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="{% static 'main/css/custom-style.css' %}" />
<link rel="stylesheet" type="text/css" href="{% static 'main/css/bootstrap.css' %}" />
</head>
<body>
<div class="container center">
<span class="form-inline" role="form">
<div class="inline-div">
<form class="form-inline" action="/controlepunt140" method="POST" enctype="multipart/form-data">
<div class="d-grid gap-3">
<div class="form-group">
{% csrf_token %}
{{ form.0.as_p }}
<button type="submit" name="form_pdf" class="btn btn-warning">Upload!</button>
</div>
<div class="form-outline">
<div class="form-group">
<textarea class="inline-txtarea form-control" id="content" cols="70" rows="25">
{{content}}</textarea>
</div>
</div>
</div>
<div class="d-grid gap-3">
<div class="form-group">
{{ form.1.as_p }}
</div>
<div class="form-outline">
<div class="form-group">
<textarea class="inline-txtarea form-control" id="content" cols="70" rows="25">
{{conten_excel}}</textarea>
</div>
</div>
</div>
</form>
</div>
</span>
</div>
</body>
</html>
{% endblock content %}
and the views.py:
class ReadingFile(View):
def get(self, *args, **kwargs):
return render(self.request, "main/controle_punt140.html", {
"form1": UploadFileForm(),
"form2": ExcelForm()
})
def post(self, *args, **kwargs):
filter_text = FilterText()
types_of_encoding = ["utf8", "cp1252"]
form1 = UploadFileForm(
self.request.POST, self.request.FILES, prefix="form1")
form2 = ExcelForm(self.request.FILES,
self.request.FILES, prefix="form2")
content = ''
content_excel = ''
if form1.is_valid() and form2.is_valid() and self.request.POST:
uploadfile = UploadFile(image=self.request.FILES["upload_file"])
excel_file = self.request.FILES["upload_file"]
uploadfile.save()
for encoding_type in types_of_encoding:
with open(os.path.join(settings.MEDIA_ROOT, f"{uploadfile.image}"), 'r', encoding=encoding_type) as f:
if uploadfile.image.path.endswith('.pdf'):
content = filter_text.show_extracted_data_from_file(
uploadfile.image.path)
else:
content = f.read()
if uploadfile.image.path.endswith('xlsx'):
wb = openpyxl.load_workbook(excel_file)
worksheet = wb['Sheet1']
print(worksheet)
excel_data = list()
for row in worksheet.iter_rows():
row_data = list()
for cell in row:
row_data.append(str(cell.value))
excel_data.append(row_data)
print(excel_data)
content_excel = excel_data
else:
content_excel = f.read()
return render(self.request, "main/controle_punt140.html", {
'form1': ExcelForm(),
'form2': UploadFileForm(),
"content": [content, content_excel]
})
# I've adjusted the indent here to what I think it should be.
return render(self.request, "main/controle_punt140.html", {
"form1": form1,
"form2": form2,
})
and forms.py:
class UploadFileForm(forms.Form):
upload_file = forms.FileField(required=False)
class ExcelForm(forms.Form):
upload_file = forms.FileField(required=False)
urls.py:
urlpatterns = [
path('', views.starting_page, name='starting_page'),
path('controlepunt140', views.ReadingFile.as_view(), name='controlepunt140'),
]
The variable name used in the template is the key of the dictionary, not the value. The value is what is inserted into the template when django renders the page.
You have {{form1.as__p}} in your template, but you send "form": [form1, form2] as your context, so the variable in the template should be {{ form.0.as_p }} and {{ form.1.as_p }}. I haven't tested this, but if it doesn't work, you could just send the two forms separately like:
from django.shortcuts import redirect
class ReadingFile(View):
def get(self, *args, **kwargs):
return render(self.request, "main/controle_punt140.html", {
"form1": UploadFileForm(),
"form2": ExcelForm()
})
def post(self, *args, **kwargs):
filter_text = FilterText()
types_of_encoding = ["utf8", "cp1252"]
form1 = UploadFileForm(self.request.POST, self.request.FILES, prefix="form1")
form2 = ExcelForm(self.request.FILES, self.request.FILES, prefix="form2")
content = ''
content_excel = ''
if form1.is_valid() and form2.is_valid() and self.request.POST:
uploadfile = UploadFile(image=self.request.FILES["upload_file"])
excel_file = self.request.FILES["upload_file"]
uploadfile.save()
for encoding_type in types_of_encoding:
with open(os.path.join(settings.MEDIA_ROOT, f"{uploadfile.image}"), 'r', encoding=encoding_type) as f:
if uploadfile.image.path.endswith('.pdf'):
content = filter_text.show_extracted_data_from_file(
uploadfile.image.path)
else:
content = f.read()
if uploadfile.image.path.endswith('xlsx'):
#Uploading excel form:
#this is just logic.
pass
else:
content_excel = f.read()
# You probably should do a redirect after the form is
# submitted, rather than render the page.
return redirect('main:controlepunt140')
# return render(self.request, "main/controle_punt140.html", {
'form1': ExcelForm(),
'form2': UploadFileForm(),
"content": [content, content_excel]
})
# I've adjusted the indent here to what I think it should be.
return render(self.request, "main/controle_punt140.html", {
"form1": form1,
"form2": form2,
})
You probable should also change to a redirect after the form is submitted and saved successfully. Check out Post/Redirect/Get and/or rendering content after a succesful post request.
Edit
Changed template to use {{ form.0.as_p }} as indicated by #nigel239
You can redirect to the same page where the form was submitted, so if the user hits the refresh button on their browser for some reason, you will not get an alert box asking the user to resend the form.

Django Dependent/Chained Dropdown List - Select A Valid Choice Error

I have implemented a Dependent dropdown list within Django but when I try to submit the form I get the following error 'Select a valid choice. That choice is not one of the available choices.'
I have spent a while looking on the web for the answer and have tried a few with little avail.
From my understanding and reading, this is an error because I render the form with a queryset of none. Then I use ajax to fill in the options. Even though I have updated the dropdown list, the form validation is checking my submitted answer against a queryset of none - thus the error.
So i'm hoping someone can help me to update the choices the form will accepted on form submission.
views.py
# stage6 is where I render my view and check validation
def stage6(request):
form_deal = DealForm(request.POST or None, prefix='inst')
if form_deal.is_valid():
form_deal.save()
messages.success(request, 'Deal added successfully.')
form_deal = DealForm()
context = {
'dform': form_deal,
}
return render(request, 'stages/stage6/stage6.html', context)
# This is used for my ajax request
def load_offers(request):
property_process_id = request.GET.get('propertyprocess_link')
offers = Offer.objects.filter(propertyprocess_link=property_process_id).order_by('id')
return render(request, 'stages/stage6/offers_dropdown_list.html', {'offers': offers})
forms.py
class DealForm(forms.ModelForm):
deal_date = forms.CharField(
label='',
widget=forms.TextInput(attrs={'type': 'date'})
)
target_move_date = forms.CharField(
label='',
widget=forms.TextInput(attrs={'type': 'date'})
)
def __init__(self, *args, **kwargs):
super(DealForm, self).__init__(*args, **kwargs)
# filter the foreign keys shown
self.fields['propertyprocess_link'].queryset = PropertyProcess.objects.filter(sector="Sales")
# filter used for ajax request
self.fields['offer_accepted'].queryset = Offer.objects.none()
# add a "form-control" class to each form input
# for enabling bootstrap
for name in self.fields.keys():
self.fields[name].widget.attrs.update({
'class': 'form-control',
})
class Meta:
model = Deal
fields = ('propertyprocess_link',
'deal_date',
'price_agreed',
'target_move_date',
'offer_accepted'
)
models.py
class Deal(models.Model):
propertyprocess_link = models.ForeignKey(PropertyProcess,
on_delete=models.CASCADE)
deal_date = models.DateField()
price_agreed = models.IntegerField()
target_move_date = models.DateField()
offer_accepted = models.ForeignKey(Offer,
on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "deals"
def __str__(self):
return '%s, %s' % (
self.propertyprocess_link.property_link.address_line_1,
self.propertyprocess_link.property_link.postcode
)
html
{% block content %}
<div class="container-fluid header-container">
<div class="row">
<div class="col-sm-9 col-md-7 col-lg-5 mx-auto">
<div class="card-au card-signin my-5">
<div class="card-body">
<form id="offers-form" data-offers-url="{% url 'ajax_load_offers' %}" class=" text-center text-white" method="post" novalidate>
{% csrf_token %}
{{ dform.non_field_errors }}
<div class="form-colour mt-2">
{{ dform.propertyprocess_link.errors }}
<label class="mb-0 mt-1">Property Being Offered On:</label>
{{ dform.propertyprocess_link }}
</div><div class="form-colour mt-2">
{{ dform.offer_accepted.errors }}
<label class="mb-0 mt-1">Offer Being Accepted:</label>
{{ dform.offer_accepted }}
</div>
<div class="form-colour mt-2">
{{ dform.price_agreed.errors }}
<label class="mb-0 mt-1">Price Agreed:</label>
{{ dform.price_agreed }}
</div>
<div class="form-colour mt-2">
{{ dform.deal_date.errors }}
<label class="mb-0 mt-1">Deal Date:</label>
{{ dform.deal_date }}
</div>
<div class="form-colour mt-2">
{{ dform.target_move_date.errors }}
<label class="mb-0 mt-1">Target Move Date:</label>
{{ dform.target_move_date }}
</div>
<div class="mb-3"></div>
{# hidden submit button to enable [enter] key #}
<div class="hidden-btn" style="margin-left: -9999px"><input class="hidden-btn" type="submit" value=""/></div>
<div class="text-center mt-2">
<input type="submit" class="login-btn btn-green btn btn-lg border-green text-uppercase py-3" value="Add Deal" />
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
{% block postloadjs %}
{{ block.super }}
<script>
$("#id_inst-propertyprocess_link").change(function () {
var url = $("#offers-form").attr("data-offers-url"); // get the url of the `load_offers` view
var propertyID = $(this).val(); // get the selected Property Process ID from the HTML input
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= localhost:8000/ajax/load-offers/)
data: {
'propertyprocess_link': propertyID // add the Property Process id to the GET parameters
},
success: function (data) { // `data` is the return of the `load-offers` view function
$("#id_inst-offer_accepted").html(data); // replace the contents of the offers input with the data that came from the server
}
});
});
</script>
{% endblock postloadjs %}
Thanks very much for any help anyone can give.

File could not be opened because it is empty

I want to upload 2 images from requests. I am creating the function which accepts the request.files as a parameter and save both images.
The function is :
def store_offer_images(files, **service_response):
"""
Stores the Images
"""
create_diretory_if_not_exist()
lrg_img, sml_img = files.get('detail_image'), files.get('listing_image')
lrg_img_filename = service_response.get('content').get('offerId') + ".png"
sml_img_filename = service_response.get('content').get('offerId') + ".png"
sml_img.save(
os.path.join(config.NORMAL_FILE_UPLOAD_FOLDER, sml_img_filename))
lrg_img.save(
os.path.join(config.LARGE_FILE_UPLOAD_FOLDER, lrg_img_filename))
When I am trying to save the images. It saves properly. files is the request.files and service_response is the kwargs.
When I want to open image in Finder(OS GUI Window), then I got the message:
The file “b516f2dca72e4f559c3a72a1f48727a9.png” could not be opened because it is empty.
How can I upload the images?
Edit:
When I look files in the pdb, here are the response:
(pdb) files.get('detail_image')
(pdb) <FileStorage: u'python-640x444.png' ('image/png')>
The model which models my request data is:
import datetime
from app_config import AppConfig
class Offer(object):
"""
Offer Details
"""
def __init__(self, form):
self.REST_API_TIME_FORMAT = AppConfig().REST_API_TIME_FORMAT
self.title = form.get('title')
self.start_date = form.get('startsOn') + ' 00:00'
self.end_date = form.get('endsOn') + ' 23:59'
self.short_description = form.get('shortDescription')
self.long_description = form.get('longDescription')
self.outlets = form.getlist('outlets')
self.offer_value = form.get('offerValue')
self.offer_old_value = form.get('oldValue')
self.currency = form.get('currency')
def add_offer_body(self):
"""
Return the request body in json format
"""
outlets_list = []
for i in self.outlets:
outlets_list.append({'code': i})
starts_on_date = datetime.datetime.strptime(
self.start_date, '%d/%m/%Y %H:%M')
ends_on_date = datetime.datetime.strptime(
self.end_date, '%d/%m/%Y %H:%M')
body = {
"outlets": outlets_list,
"title": self.title,
"shortDescription": self.short_description,
"longDescription": self.long_description,
"endsOn": ends_on_date.strftime(self.REST_API_TIME_FORMAT),
"startsOn": starts_on_date.strftime(self.REST_API_TIME_FORMAT),
"isActive": "true",
}
if self.offer_value is not u'':
body['offerValue'] = {
"value": self.offer_value,
"currency": self.currency
}
if self.offer_old_value is not u'':
body["offerOldValue"] = {
"value": self.offer_old_value,
"currency": self.currency
}
return body
def __repr__(self):
return self.title
The views.py is:
#portal.route('/admin/offers/add', methods=['POST'])
def add_offer():
"""
Return status of added offer
"""
offer = Offer(request.form)
if controller.valid_content(request.files):
service_response = controller.add_offer(offer)
if 'errors' in service_response:
message = str(service_response.get('errors')[0].get('message'))
flash("Adding Offer Failed.!! " + message)
current_app.logger.error(
'Offer adding failed with details' + str(request.form))
return redirect(url_for('portal.list_running_offers'))
else:
controller.store_offer_images(request.files, **service_response)
current_app.logger.info('User added a offer successfully.')
flash("Offer added successfully..!!")
return redirect(url_for('portal.list_running_offers'))
else:
flash("Please upload all Images of mentioned Resolution.!!")
return render_template(
'addoffer.jinja', body=offer.add_offer_body(), help=help_messages)
The HTML is:
{% extends "base.jinja" %}
{% block script %}
<script type="text/javascript" src="static/js/addOffer.js"></script>
<script type="text/javascript" src="static/js/bootstrap-datepicker.min.js"></script>
<link href="static/css/datepicker.css" rel="stylesheet">
{% endblock %}
{% block title %}
Add Offer
{% endblock %}
{% block content %}
<legend><h1>
Add Offer
</h1></legend>
<br>
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-10">
<form id="offerForm"enctype="multipart/form-data" class="form-horizontal" action="{{ url_for('portal.add_offer') }}" data-toggle="validator" role="form" method="post">
<div class="form-group">
<label class="control-label col-xs-3" for="file">OFFER LISTING IMAGE *</label>
<div class="col-xs-7 input-group">
<input id="image" type="file" class="form-control" name="listing_image" accept="image/x-png" data-error="{{help.listing_image}}" required>
<span class="help-block with-errors">{{help.listing_image}}</span>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-3" for="file">OFFER DETAIL IMAGE *</label>
<div class="col-xs-7 input-group">
<input id="image" type="file" class="form-control" name="detail_image" accept="image/x-png"
data-error="{{help.detail_image}}" required>
<span class="help-block with-errors">{{help.detail_image}}</span>
</div>
</div>
</form>
</div>
<div class="col-md-1"></div></div>
</div>
{% endblock %}
I fixed the problem. It was happening because If I perform any operation on Image, it will move my pointer at last, so when you save the image, it start saving image where your pointer is, which is at the last. So the saved image is empty.
Now to fixed this I just move my pointers to the beginning. Here is sample code what I did:
if img is not None and img.filename != u'':
img.seek(0, os.SEEK_END)
size = img.tell()
imgs = Image.open(img)
res = imgs.size
img.seek(0)

Django form won't show up on template

I'm making a sign in system in Django Python, i've been preparing the forms.py, views.py and the template itself, but so far the form fail to load on the template, can anyone help?
Forms.py
class Email_Only_SignUp_Form(forms.Form):
email = forms.EmailField(initial='Your Email...')
Views.py
def email_only_signup_form(request, template_name):
if request.method == 'POST':
signup_form = Email_Only_SignUp_Form(request.POST)
if signup_form.is_valid():
email = signup_form.cleaned_data['email']
username = email
try:
#check for duplicate username
User.objects.get(username=username)
email_error = 'email already exist'
except:
#initial creation of user object
try:
import os, random, string
length = 13
chars = string.ascii_letters + string.digits + '!#$()'
random.seed = (os.urandom(1024))
password = ''.join(random.choice(chars) for i in range(length))
User.objects.create_user(username,
username,
password,
)
user = User.objects.get(username=username)
user_profile=UserProfile(user=user)
user_profile.save()
#send email to user
try:
admin_email = settings.EMAIL_ORIGIN_MEMBERS
email_txt = loader.get_template('account/emails/createaccount.html')
email_html = loader.get_template('account/emails/createaccounthtml.html')
email_context = Context({'u_name': username,
'username': username,
'password': password,
})
new_user_mail = EmailMultiAlternatives('Welcome!',
email_txt.render(email_context),
admin_email,
[user.email, ],
headers={'Reply-To': 'admin#admin.com'}
)
new_user_mail.attach_alternative(email_html.render(email_context), 'text/html')
new_user_mail.send()
except:
pass
return redirect('/account/thankyou/?next=%s'%next)
except:
pass
else:
print('user form in not valid')
else:
signup_form = Email_Only_SignUp_Form()
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
email_only_signup_form.html
{% extends "index.html" %}
{% block heroslider %}
<div class="page_title2" style="padding:150px 0px 50px 0px;">
<div class="container">
<h1>User Registration</h1>
</div>
</div><!-- end page title -->
{% endblock %}
{% block main_body %}
<style type="text/css">
input[type='radio'], input[type='checkbox'] {
width:20px;
vertical-align: middle;
}
div.reg_error {
position:relative;
top:-10px;
margin-top:0px;
padding-top:0px;
color:red;
}
</style>
<div class="container">
<form class="pagesignup logiform" action="" method="POST">{% csrf_token %}
<div class="row">
<div class="large-12 columns" style="margin-bottom: 30px;">
<div class="reg_form">
<div class="sky-form">
<header>REGISTER</header>
</div>
<div class="row">
<div class="large-12 columns">
<p>Email<br/>
{{signup_form.email}}
<div class="reg_error">{{ signup_form.email.errors.as_text }}{{email_error}}</div></p>
</div>
</div>
<div class="row">
<div class="large-12 large-centered columns" style="text-align:center;padding:20px;">
<input class="but_medium1" style="border:none;" type = "submit" value="REGISTER" /><br>
<br>By clicking on register, you have read and agreed to our terms of use
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<!-- Google Code for Sign Up Page (landed) Conversion Page -->
<script type="text/javascript">
/* <![CDATA[ */
var google_conversion_id = 969557266;
var google_conversion_language = "en";
var google_conversion_format = "3";
var google_conversion_color = "ffffff";
var google_conversion_label = "5zU4CJby_FoQkoqpzgM";
var google_remarketing_only = false;
/* ]]> */
</script>
<script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js">
</script>
<noscript>
<div style="display:inline;">
<img height="1" width="1" style="border-style:none;" alt="" src="//www.googleadservices.com/pagead/conversion/969557266/?label=5zU4CJby_FoQkoqpzgM&guid=ON&script=0"/>
</div>
</noscript>
{% endblock %}
You have not passed the signup_form to the template.
return render_to_response(template_name, {'signup_form': signup_form}, context_instance=RequestContext(request))
I have no idea what locals() does.
Edit: I just saw locals which is a built in python function. It will be better if you explicitly pass the variables you need in the template.
Edit 2: Check if it is the correct template_name. In the template simply print and see the form {{ signup_form }}. See if it is available.
You are not returning the form.
Try changing the last line of the view to
return render_to_response(template_name, locals(), context_instance=RequestContext(request, {'signup_form' : signup_form ))

Categories

Resources