I have an Issue trying to Bind my PostForm with an Image Uploading Ability for a Post Made, However there is a functional Profile picture coding which accepts images and save the name to the data base and to avoid error, it adds uuid1 to the image name which is saved on the data base and the image itself is saved in the static folder, image section where it is called upon when needed, all part of the UserForm, but for the PostForm, the method is the same, but instead of a profile picture, it is a post image which should appear there and it keeps giving me interface error, however if the image is excluded, the Post is added to the Database successfully, please I need your help to know what is going wrong, Here is the Code:
#app.route('/add-post', methods=['GET', 'POST'])
def add_post():
form = PostForm()
if form.validate_on_submit():
if request.files['post_image']:
post_image = request.files['post_image']
post_filename = secure_filename(post_image.filename)
post_name = str(uuid.uuid1()) + "_" + post_filename
saver = request.files['post_image']
post_image = str(uuid.uuid1()) + "_" + post_filename
try:
db.session.commit()
saver.save(os.path.join(app.config['UPLOAD_FOLDER'], post_name))
except:
flash("Error! Looks Like There Was a Problem... Try Again!")
else:
db.session.commit()
poster = current_user.id
post = Posts(title=form.title.data, post_image=form.post_image.data, content=form.content.data, poster_id=poster, slug=form.slug.data)
form.title.data = ''
form.content.data = ''
form.slug.data = ''
form.post_image.data = ''
db.session.add(post)
db.session.commit()
flash("Blog Post Submitted Successfully !")
return render_template("add_post.html", form=form)
After weeks of trying and having errors, I finally got the hang of it... I will post the answer below:
#app.route('/add-post', methods=['GET', 'POST'])
def add_post():
form = PostForm()
if form.validate_on_submit():
poster = current_user.id
post = Posts(title=form.title.data, content=form.content.data, file=form.file.data, poster_id=poster, slug=form.slug.data)
if request.files['file']:
upload.file = request.files['file']
filename = secure_filename(upload.file.filename)
file_name = str(uuid.uuid1()) + "_" + filename
saver = request.files['file']
post.file = file_name
try:
db.session.add(post)
db.session.commit()
saver.save(os.path.join(app.config['UPLOAD_FOLDER'], file_name))
flash("User Updated Successfully !")
return render_template("add_post.html",
form=form)
except:
flash("Error! Looks Like There Was a Problem... Try Again!")
return render_template("add_post.html",
form=form)
else:
db.session.add(post)
db.session.commit()
flash("User Updated Successfully !")
return render_template("add_post.html",
form=form)
form.title.data = ''
form.content.data = ''
form.slug.data = ''
db.session.add(post)
db.session.commit()
return render_template("add_post.html",
form=form,
id = id or 1)
Related
-- This is the error Im getting --
InterfaceError
sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 0 - probably unsupported type.
[SQL: UPDATE user SET image_file=? WHERE user.id = ?]
[parameters: (<FileStorage: 'default.jpg' ('image/jpeg')>, 6)]
(Background on this error at: https://sqlalche.me/e/14/rvf5)
-- This is my code for saving a picture into the app folder --
def save_picture(form_picture):
random_hex = secrets.token_hex(8)
_, f_ext = os.path.splitext(form_picture.filename)
picture_fn = random_hex + f_ext
picture_path = os.path.join(app.root_path, 'static/profile_pics/' + picture_fn)
form_picture.save(picture_path)
return picture_fn
-- This is the route where Im calling the save_picture function --
#app.route("/account", methods=['GET', 'POST'])
#login_required
def account():
form = UpdateAccountForm()
if form.validate_on_submit():
if form.picture.data:
picture_file = save_picture(form.picture.data)
current_user.image_file = form.picture.data
current_user.username = form.username.data
current_user.email = form.email.data
db.session.commit()
flash('Your account has been updated', 'success')
return redirect(url_for('account'))
elif request.method == 'GET':
form.username.data = current_user.username
form.email.data = current_user.email
image_file = url_for('static', filename='profile_pics/' + current_user.image_file)
return render_template("account.html", title="MY BLOG", image_file=image_file, form=form)
After debbug I got that the db.session.commit() is calling the error, but I checked many times and still dont understand where is the problem. The picture is getting saved in the app's folder, but is not getting saved into the database.
So I was making the wrong attributions to the current.user.image_file,
I needed to attribute current.user.image_file with the picture_file I saved and renamed with the secrets.token_hex(8) not the one I got from the open file inside the webpage
if form.picture.data:
picture_file = save_picture(form.picture.data)
current_user.image_file = picture_file
I am trying to run my flask app, but every time I load my index page, it gives me the error:
AttributeError: 'Flask' object has no attribute 'login_manager'.
It works before I put in this specific code
bp = flask.Blueprint("bp", __name__, template_folder="./build")
#bp.route('/index')
#login_required
def index():
# TODO: insert the data fetched by your app main page here as a JSON
DATA = {"your": "data here"}
data = json.dumps(DATA)
return flask.render_template(
"index.html",
data=data,
)
app.register_blueprint(bp)
This is my current code where it does work
#app.route("/index", methods=["GET", "POST"])
def index():
global current_user
if not current_user:
return flask.redirect(flask.url_for("login"))
if flask.request.method == "GET":
track_name, genius_link, track_artist, track_image, track_url = render()
# If user has no favorite artists, redirect back to profile.
if track_name == None:
return flask.redirect(flask.url_for("profile"))
return flask.render_template(
"index.html",
variable=track_name,
variable1=genius_link,
variable2=track_artist,
variable3=track_image,
variable4=track_url,
)
else:
valid_artist = validate_and_insert_artist(flask.request.form["artistId"])
if not valid_artist:
return flask.render_template("index.html", error=True)
else:
track_name, genius_link, track_artist, track_image, track_url = render()
# If user has no favorite artists, redirect back to profile.
if track_name == None:
return flask.redirect(flask.url_for("profile"))
return flask.render_template(
"index.html",
variable=track_name,
variable1=genius_link,
variable2=track_artist,
variable3=track_image,
variable4=track_url,
)
I am not sure why as soon as I put in the blueprint code, it stops working and gives me that error
This is my login.html
#app.route("/login", methods=["GET", "POST"])
def login():
global current_user
if current_user:
return flask.redirect(flask.url_for("profile"))
if flask.request.method == "GET":
return flask.render_template("login.html")
if flask.request.method == "POST":
username = flask.request.form["username"]
cursor.execute(
"SELECT user_name FROM public.users WHERE user_name = %s", [username]
)
results = cursor.fetchall()
if len(results) != 0: # if a user exists, "log" them in
current_user = username
return flask.redirect(flask.url_for("profile"))
else:
return flask.render_template("login.html", error=True)
You need to read the Flask documentation for #login_required. As soon as you've added a method that requires the user to be logged in, you need to provide a method by which the user can log in.
Or perhaps you just want to delete the #login_required?
Here I am trying to redirect to another page if the form is submitted successfully but this code is not working properly .The code saves the form data sends the email , everything is fine but the problem is while redirecting to another page if the form succeed. The error I get is:
Django Version: 2.0.6
Exception Type: ValueError
Exception Value:
dictionary update sequence element #0 has length 0; 2 is required
context_processor.py
def volunteer_page2(request):
volunteer = Volunteer.objects.all().order_by('date')
if request.method == 'POST':
form = VForm(request.POST or None)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = "{0} with email address {1} has sent you new message \n\n{2}".format(name, email, form.cleaned_data['message'])
form.save(commit = False)
try:
send_mail(name, message, 'appname <settings.EMAIL_HOST_USER>', ['myemail'])
except:
return HttpResponse('Invalid header found')
form.save()
messages.success(request, 'Success')
return redirect('volunteer_page')
else:
messages.error(request, "Sorry try again")
else:
form = VForm()
return {'volunteer': volunteer, 'form':form}
views.py
def about_page(request):
about = About.objects.all().order_by('date')
banner = Banner.objects.all()
testimonial = Testimonial.objects.order_by('-pk')[0:2]
nav = Nav.objects.all()
footer = Footer.objects.all()
latest_event2 = Events.objects.order_by('-pk')[0:2]
context = {
'about': about,
'testimonial': testimonial,
'footer':footer,
'banner': banner,
'nav': nav,
'latest_event2': latest_event2,
}
return render(request, 'myapp/about.html', context)
settings.py
'myapp.context_processor.volunteer_page2'
Django's context processor should always return dictionary. In your code you are returning HttpResponse also. This is problem.
Here's my code
#login_required
def upload(request):
form_type = ''
transcript = Transcript()
transcript.file_path = ''
if request.method == 'POST':
if 'file_form' in request.POST:
file_form = FileForm(request.POST, request.FILES)
if file_form.is_valid():
path = handle_uploaded_file(request.FILES['file'], request.user)
transcript.file_path = path
transcript.user = request.user
export_form = InfoForm()
form_type = 'info_form'
elif 'info_form' in request.POST:
if transcript.file_path:
info_form = InfoForm(request.POST)
if info_form.is_valid():
transcript.user = request.user
transcript.title = info_form.cleaned_data.get('title')
transcript.instructions = info_form.cleaned_data.get('instructions')
transcript.save()
return HttpResponseRedirect('thanks')
else:
raise ValueError('Transcript object has no file path attribute')
else:
export_form = FileForm()
form_type = 'file_form'
return render(request, 'transcription/upload.html', {'form': export_form, 'form_type': form_type})
always, the file-form is called before the info-form, so the code in the if statement
if transcript.file_path:
#...
should always execute. But the ValueError always gets raised, meaning transcript.file_path is reset. How does this happen, and how can it be fixed?
file_form and info_form in POST are names of the different submit buttons, so I know which form I am dealing with.
def handle_uploaded_file(file, user):
id = randint(0, 10000)
user_dir = settings.MEDIA_ROOT + '/' + str(user.id).replace(".", "") + '/'
path = user_dir + file.name.replace(".mp3", str(id) + ".mp3")
if not os.path.exists(user_dir):
os.makedirs(user_dir)
with open(path, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
file = File(destination)
info = {'path': path, 'file': file}
return path
So it was a rookie mistake.
I didn't know that during each post request the whole view gets called again.
So I just initialized my variables
form_type = ''
transcript = Transcript()
transcript.file_path = ''
outside the view and voila!
Im trying to create a movie DB for a school project and I am getting a '400' after submitting the form.
The use of this form is to add Movies to your DB with a description, titel, year and picture(Url to DB) as of now.
routes.py:
#login_required
#app.route('/upMovie', methods=['GET'])
def movieup():
return render_template('upload.html', MovieUploadForm=MovieUploadForm())
#login_required
#app.route('/upMovie', methods=['POST'])
def movieup_validate():
upload_form = MovieUploadForm()
if upload_form.validate_on_submit():
if Movie.query.filter_by(title=upload_form.title.data).first() is not None:
return 'Movie already exists.Back'
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(upload_form.filename.file.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
upload_form.filename.file.save(file_path)
movie = Movie(
title=upload_form.title.data,
info=upload_form.info.data,
year=upload_form.year.data,
filename=file_path,
rating=5
)
db.session.add(movie)
db.session.commit()
return redirect(url_for('uploaded_file', filename=filename))
return 'Registration of movie successful.<br/>Home'
else:
upload_form.flash_form_errors()
return render_template('errors.html')
forms.py:
class MovieUploadForm(StandardForm):
title = StringField('Title', validators=[InputRequired(), length(1, 80)])
info = TextAreaField('Info', validators=[length(1, 2000)])
year = DateField('YYYY/MM/DD', format='%Y/%m/%d')
filename = FileField('File URL')
def flash_form_errors(self):
for field, errors in self.errors.items():
for error in errors:
flash("<strong>Error in field: %s</strong> - %s" % (getattr(self, field).label.text, error))
funtions.py
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']
So I experimentent around for a while and found a working solution.
The changes I made in routes.py
if upload_form.validate_on_submit():
if upload_form.filename.data.filename is not "":
filename = secure_filename(upload_form.filename.data.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
# file_path = "imdb/static/pic/" + filename
upload_form.filename.data.save(file_path)
movie = Movie(
title=upload_form.title.data,
info=upload_form.info.data,
year=upload_form.year.data,
filename=file_path if upload_form.filename.data else None,
rating=5
)
db.session.add(movie)
db.session.commit()
return 'Registration of movie successful.<br/>Home'
As we are getting our date from our wtforms, we don't need to file = request.files['file'] as the object we are getting is empty.
in forms.py
class MovieUploadForm(StandardForm):
title = StringField('Title', validators=[InputRequired(), length(1, 80)])
info = TextAreaField('Info', validators=[length(1, 2000)])
year = DateField('YYYY/MM/DD', format='%Y/%m/%d')
filename = FileField('File URL', validators=[FileAllowed(['jpg', 'png', 'jpeg'], 'Images only!')])
def validate(self):
v = Form.validate(self)
if not v:
return False
if Movie.query.filter_by(title=self.title.data).first() is not None:
self.title.errors.append("Movie already exists!")
return False
else:
return True
I changed them accordingly, with allowed file endings and also added a Validation for duplicates.
With this code everything seems to work just fine.