I am making a homework system on my site which should include the fact that the teacher will be able to create a task with an attachment, but I don't know how to break up the file that the teacher sends to the file name and file data in the table in the mysql database. I am programming it in vanilla flask, could someone please advise me how to do it, I would be grateful. So far I have this code which reports this error:
AttributeError AttributeError: 'str' object has no attribute 'filename'
Sample code where I create a homework with an attachment, but it is not working:
@app.route("/create_homework", methods=["POST", "GET"])
@isLoggedIn
def create_homework():
if session["group_id"] != Group.REDITEL and session["group_id"] != Group.UCITEL:
abort(401, description="Nemáš dostatečné oprávnění")
form = HomeworkForm()
if request.method == "POST":
connection = mysql.connection
cursor = connection.cursor(prepared=True)
hmTitle = request.form.get("hmTitle")
description = request.form.get("description")
date_of_completion = request.form.get("date_of_completion")
classname = session["class"]
school = session["school"]
if session["class"] == None:
return "Učitel není přiřazen k žádné třídě"
if(request.method == "POST"):
usersName = loadUserNameFromClass(classname, school)
for userName in usersName:
if form.validate_on_submit():
attachment_data = form.attachment.data
attachment_name = secure_filename(attachment_data.filename)
file_stream = Binary(attachment_data.read(1024))
attachment_data.save(file_stream)
cursor.execute("INSERT INTO homeworks (id, userName, homework_title, homework_description, school, class, date_of_completion, status, attachment_name, attachment_data) VALUES (0, %s, %s, %s, %s, %s, %s, 0, %s, %s);", (userName, hmTitle, description, school,classname, date_of_completion, attachment_name, file_stream, ))
clearForm(form)
connection.commit()
return redirect(url_for("homeworks"))
else:
return redirect(url_for("homeworks"))
cursor.close()
connection.close()
return render_template("profile/homework/create_homework.html", form=form)
Sample code where I select the attachment so that the user can download it:
@app.route("/download_file/<int:id>")
@isLoggedIn
def download_file(id):
connection = mysql.connection
cursor = connection.cursor(prepared=True)
file_name = get_file_name(cursor, id)
file_data = get_file_data(cursor, id)
return send_file(BytesIO(file_data), attachment_filename=file_name, as_attachment=True)
def get_file_name(cursor, id):
cursor.execute("SELECT attachment_name FROM homeworks WHERE id=%s;", (id, ))
output = cursor.fetchone()
return output[0]
def get_file_data(cursor, id):
cursor.execute("SELECT attachment_data FROM homeworks WHERE id=%s;", (id, ))
output = cursor.fetchone()
return output[0]
HomeworkForm code:
class HomeworkForm(FlaskForm):
hmTitle = TextField('Titulek', [validators.DataRequired(), validators.Length(min=1, max=200)])
description = TextAreaField("Popis", [validators.DataRequired()])
attachment = FileField('Příloha', validators=[FileRequired(), FileAllowed(['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar'], 'Povolené typy souborů: pdf, doc, docx, xls, xlsx, ppt, pptx, zip, rar')], id='attachment')
date_of_completion = DateTimeLocalField('Datum odevzdání', format='%m/%d/%y', validators=[validators.DataRequired()])
submit = SubmitField("Vytvořit")
HTML code:
<form method="POST" action="/create_homework" enctype="multipart/form-data">
{{ form.csrf_token }}
<strong>{{ form.hmTitle.label() }} </strong>
{{ form.hmTitle(id="hmTitle", ) }}
<br>
<strong>{{ form.description.label() }} </strong>
{{ form.description(id="description", ) }}
<br>
<strong>{{ form.attachment.label() }} </strong>
{{ form.attachment(id="attachment", ) }}
<br>
<strong>{{ form.date_of_completion.label() }} </strong>
{{ form.date_of_completion(id="date_of_completion", ) }}
<br>
{{ form.submit(id="submit", ) }}
<!--<input type="file" name="attachment">-->
<br>
{%if success == False%}
<p style="color: red;">Zpráva nebyla zaslána</p>
{%endif%}
<hr>
<button href="/homeworks" id="return-back">Vrátit zpátky</button>
</form>
CodePudding user response:
You haven't provided the definition of your HomeworkForm() so it's hard to provide an answer but I can tell you why you're seeing that exception.
On the line if attachment(attachment.filename):
the attachment variable is a string and doesn't have the property 'filename' on it.
You need to change the line attachment = request.form.get("attachment")
. If you are using WTForms FileField, this returns the path to a file, which is why you're getting a string here and seeing that exception.
Here's a tutorial that goes into detail on how to use flask and WTForms to upload a file.
Edit: Looking at the documentation for Flask-WTForms's FileField
To get the data of the file:
if form.validate_on_submit():
homework_data = form.attachment.data
homework_filename = secure_filename(homework_data.filename)
The docs also mention making sure you set the encoding type for the form in your html:
<form method="POST" enctype="multipart/form-data">