Two forms one view: model variable loses value - python

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!

Related

How Do I solve Interface Binding Error In Python Flask

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)

Lines before form.save() are not saving the right values

I have a view with model form, the ModelForm doesn't really contain all fields in the model. other fields I've used the methods of form.field = value before form.save(), but all of this fields being saved as default. none take the value am trying to give. here are the code :
def PostAd(request):
ad_post_form = AdPostForm()
if request.user.is_authenticated:
obj = Account.objects.get(user=request.user)
if request.method == "POST":
ad_post_form = AdPostForm(request.POST, request.FILES)
if ad_post_form.is_valid():
ad_post_form.created_by = request.user
if obj.role == 'admin':
ad_post_form.is_active = True
ad_post_form.save()
return redirect('home')
else:
ad_post_form = AdPostForm(request.POST, request.FILES)
else:
if request.method == "POST":
ad_post_form = AdPostForm(request.POST, request.FILES)
if ad_post_form.is_valid():
otp_number = random.randint(100000, 999999)
ad_post_form.otp = otp_number
ad_post_form.is_activated = False
ad_post_form.save()
current_id = ad_post_form.id
current_contact_email = request.POST.get('contact_email')
email_url_active = str(settings.URL_LOCAL) + 'new_ad/adidnumberis' + str(
current_id) + '/needactivate/activate/' + str(otp_number) + '/'
email_msg = "Please Confirm adding the Ad to Jehlum. Click link " + email_url_active
email = EmailMessage('Active Email', email_msg, to=[current_contact_email])
email.send()
return redirect('home')
else:
ad_post_form = AdPostForm()
context = {
'ad_post_form': ad_post_form,
}
return render(request, 'pages/post-ad.html', context)
the problem is ad_post_form.is_active = True is being saved as False(default)
also ad_post_form.otp = otp_number is being saved as 0 (default) and i need to give the spicific values i assigned here .
You need to get the model instance and set the attributes there. You so this by calling save with commit=False.
if ad_post_form.is_valid():
ad_post = ad_post_form.save(commit=False)
ad_post.created_by = request.user
...
ad_post.save()

Flask & Wtforms: 400 Bad Request - Submitting upload form

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.

Passing uploaded file to template -- Django

I was following the instructions from the top comment of this post: Need a minimal Django file upload example and this is my views.py. I'm not interested in creating a list of files, so I removed that.
def reikna(request):
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
new_doc = Document(docfile = request.FILES['docfile'])
# Marks the file as /options/ file
new_doc.save()
# Redirect to the document list after POST
#return HttpResponseRedirect(reverse('notendur.views.options'))
else:
form = DocumentForm() # An empty, unbound form
return render('file_view2.html', {'new_doc': new_doc})
However, when I do this, I get
UnboundLocalError: local variable 'new_doc' referenced before assignment
Does this have something to do with the scope of new_doc? How should I do this?
EDIT __ My model
class Document(models.Model):
docfile = models.FileField(upload_to=_upload_path)
def get_upload_path(self,filename):
return "uploads/"+str(self.user.id) + '/' + str(date.today()) + '/' + filename

Not saving data to Database from Form

When i have this view, It only change username a password from first Form, but it would save any data from second form. Why?
if request.method == 'POST': # If the form has been submitted...
username_a_heslo = UserCreationForm(request.POST, prefix = "začátek")
přidat_údaje = UcitelZmenaForm(request.POST, prefix = "konec")
if username_a_heslo.is_valid() and přidat_údaje.is_valid(): # All validation rules pass
změnajména = request.user
změnajména.username = username_a_heslo.cleaned_data["username"]
změnajména.save()
zmenahesla=request.user.set_password(username_a_heslo.cleaned_data["password1"])
# primary = username_a_heslo.save()
cast_form = Ucitel.objects.all().filter(user=request.user)
form = UcitelZmenaForm(přidat_údaje.cleaned_data, instance=cast_form[0])
form.save
#b = přidat_údaje.save()
return HttpResponseRedirect('/hlavni_stranka/')
else:
username_a_heslo = UserCreationForm(prefix = "začátek")
přidat_údaje = UcitelZmenaForm(prefix = "konec")
return render(request, 'registration/prihlasen.html', {'prvni_prihlaseni':prvni_prihlaseni,'první_form': username_a_heslo,'druhý_form':přidat_údaje})
You did not call the function on the second one, you only have form.save when you need form.save().

Categories

Resources