HOw to send data and file from a form using flask? - flask

i have created a form using html and flask. where user will fill his name , address and other information , and will also upload his photo and other documents. once the user will fill the information and submits the form he will be redirected to another page with his own filled information and photo on the page.
i am able to get user information filled and redirect him to another page "apply.html" but when i am trying to upload photo. it's able to upload pic but do not redirect me to "apply.html"
in my routes.py
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
#app.route('/form.html', methods=['POST'])
def upload_file():
nform = NewRegistration(request.form)
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
#app.route('/form.html', methods=['GET', 'POST'])
def form():
nform = NewRegistration(request.form)
if request.method == 'POST':
if nform.validate() == False:
flash('All fields are required.')
return render_template('form.html', form=nform)
else:
post = request.form['element_15'].strip()
name = request.form['element_1_1'].strip()
last = request.form['element_1_2'].strip()
Name = str(name)+ ' ' +str(last)
father = request.form['element_2'].strip()
mother = request.form['element_3'].strip()
gender = request.form['element_17'].strip()
data = {'Name' : Name, 'post' : post, 'father' : father}
return render_template("apply.html", data=data)
elif request.method == 'GET':
return render_template('form.html', form=nform)
i know the problem is because of two function "upload_file" and "form" so suggest me the best way to get information and photo and also be able to redirect user to apply.html

Becuase you need to add render_template() in
#app.route('/form.html', methods=['POST'])
def upload_file():
// do something
render_template("yourpage.html")
Every route must return a response.
Also I would recommend use the same route for saving file+form.
#app.route('/form.html', methods=['GET', 'POST'])
def form():
nform = NewRegistration(request.form)
if request.method == 'POST':
if nform.validate() == False:
flash('All fields are required.')
return render_template('form.html', form=nform)
else:
try:
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
except Exception as e:
print "Form without file "+e
post = request.form['element_15'].strip()
name = request.form['element_1_1'].strip()
last = request.form['element_1_2'].strip()
Name = str(name)+ ' ' +str(last)
father = request.form['element_2'].strip()
mother = request.form['element_3'].strip()
gender = request.form['element_17'].strip()
data = {'Name' : Name, 'post' : post, 'father' : father}
return render_template("apply.html", data=data)
elif request.method == 'GET':
return render_template('form.html', form=nform)
Let me know if this helps.

Related

Django post-form cannot validate when using Form with additional inputs

I have a form containing af MultipleChoiceField where the choices are created dynamic based on the given user
class UpdateForm(forms.Form):
def __init__(self,names,*args,**kwargs):
super(UpdateForm,self).__init__(*args,**kwargs)
self.fields["list_names"] = forms.MultipleChoiceField(choices = zip(names,names),widget=forms.CheckboxSelectMultiple,label="Pick some names")
add_new = forms.BooleanField(initial=True, label="Add new names?",required=False)
delete_missing = forms.BooleanField(label = "Delete names?",required=False)
and it works fine as GET-request, the issues arrives with the post-request:
My view is the following:
def update(request):
user = request.user
list_names = MyModel.objects.filter(user=user).all().values_list("nick_name",flat=True).distinct()
form = UpdateWishlistForm(names =list_names)
if request.method == "POST":
post_form = UpdateForm(request.POST)
if post_form.is_valid():
list_names = post_form.cleaned_data["list_names"]
add_new = post_form.cleaned_data["add_new"]
delete_missing = post_form.cleaned_data["delete_missing"]
messages.success(request, "Success")
context = {
"form":form,
}
redirect("home")
else:
#invalid post_form
messages.error(request, "Error")
context = {
"form":form,
}
return render(request, "discounttracker/update.html")
else: #Get request
context = {
"form":form,
}
return render(request, "myapp/update.html",context=context)
The post_form = UpdateForm(request.POST) does not validate and the post_form.errors is empty.
It does contain data though (before calling post_form.is_valid())
print(post_form)
# UpdateForm: <UpdateForm bound=False, valid=Unknown, fields=(add_new;delete_missing;list_names)>
print(request.POST.dict())
#<QueryDict: {'csrfmiddlewaretoken': ['...'], 'add_new': ['on'], 'list_names': ['test_name_1']}>
but I notice it is not bound, thus not validating. But I cannot understand why it's not "binding" when parsing request.POST?
In the POST request, you need to pass the names as well, so:
list_names = MyModel.objects.filter(user=user).values_list("nick_name",flat=True).distinct()
form = UpdateWishlistForm(names=list_names)
if request.method == 'POST':
post_form = UpdateForm(names=list_names, data=request.POST)
# …
# …
But I would advise to work with a ModelMultipleChoiceField [Django-doc] and thus pass a queryset. Since the nick names apparently can contain duplicates, it might be better to make a Nickname model, and use ForeignKeys to that model.

Django Error: local variable 'fav' referenced before assignment

I got an error in Djang, When I try to pass the favourite_add to ajax I got
local variable 'fav' referenced before assignment
def favourite_add(request, id):
data = {}
video = get_object_or_404(Video, id=id)
if request.method == "POST":
account = request.user.id
if video.favourites.filter(id=account.id).exists():
fav = False
video.favourites.remove(account)
else:
video.favourites.add(account)
fav = True
data["fav"] = fav
print(data)
return JsonResponse(data)
Indent data["fav"] = fav so that it is within the outer-most if-block.
currently fav only exists if a POST request is made so it will error if you make a GET request. I'm guessing you are making a GET request with your ajax function instead of a POST request.
def favourite_add(request, id):
data = {}
video = get_object_or_404(Video, id=id)
if request.method == "POST":
account = request.user.id
if video.favourites.filter(id=account.id).exists():
fav = False
video.favourites.remove(account)
else:
video.favourites.add(account)
fav = True
data["fav"] = fav
print(data)
return JsonResponse(data)

Randomizing again in Django

When I generate a quiz in django, the question value before if request.method == 'POST': is one and then changed. Follow the screenshots.
views.py
questao = Questao.objects.annotate(resp_count=models.Count(models.Case(models.When(resposta__usuario=request.user, then=1),output_field=models.IntegerField()))).filter(resp_count=0,tipoQuestao=1).order_by("?").first()
print (questao)
if request.method == 'POST':
print (questao)
respostaform = RespostaForm(request.POST or None)
if respostaform.is_valid():
resp = respostaform.save(commit=False)
resp.idQuestao = questao
resp.save()
return HttpResponseRedirect(request.path_info)
Your view should look something like this, where you only fetch a random question when the request IS NOT POST:
if request.method == 'POST':
respostaform = RespostaForm(request.POST or None)
if respostaform.is_valid():
resp = respostaform.save()
return redirect(...)
else:
questao = Questao.objects\
.annotate(
resp_count=models.Count(
models.Case(
models.When(resposta__usuario=request.user, then=1),
output_field=models.IntegerField())))\
.filter(resp_count=0,tipoQuestao=1)\
.order_by("?")\
.first()
print(questao)
return render(request, 'some template', {'questao': questao})
Your RespostaForm should include a field named idQuestao (You did not show the code of the form, but I assume it is a ModelForm).
Does that help?

Save and Continue in Django Forms

I have created a django form which at the moment I can only save the POST. Would like to add Save and Add another button in my templates and views function. Has anyone found a solutions.
if request.method == "POST":
form = StktxnsForm(request.POST )
if form.is_valid():
new_txns = form.save(commit=False)
new_txns.created_by = request.user
new_txns.save()
return redirect('pending_transactions')
else:
form = StktxnsForm()
return render(request,'new_transaction.html', {'form': form})
You may think use AJAX function to save and continue without reload. Send 'POST' request to save data in Ajax. It will help you.
I used like this in class-based view (vanilla method)
class PackageCreateView(View):
def get(self,request,*args,**kwargs):
return render(request,'package/create_package.html')
def post(self,request,*args,**kwargs):
if request.user.is_authenticated:
if request.method == 'POST':
data = request.POST
name = data.get('name')
detail = data.get('des')
price = data.get('price')
fname = Package.objects.all().filter(name=name)
if fname:
messages.info (request,'sorry name already exits')
return redirect ('create_package')
elif request.POST.get ('continue') :
pac = Package(name=name, detail=detail, price=price)
pac.save()
return redirect('create_package')
else:
pac = Package(name=name, detail=detail, price=price)
pac.save()
return redirect('packagelist')
else:
return redirect ('create_package')
else:
return redirect('login')
Here's one way to do it.
On your template:
<button type="submit" name="save_add" value="True">Save & Add another</button>
In your view:
if form.is_valid():
new_txns = form.save(commit=False)
new_txns.created_by = request.user
new_txns.save()
if request.POST.get('save_add'):
return redirect('create_transaction')
return redirect('pending_transactions')

File Uploading Using Django

i'm new in django and i have a problem with Uploading File Please Help me!! :X
here is my view.py
def uploadimg(request):
try:
user = request.session['user']
if request.method == 'POST':
form = User_image_form(request.POST, request.FILES)
#if form.is_valid():
usr_img = User_image(imgfile = request.FILES['imgfile'])
return HttpResponse("yes")
#usr_img.user = user
usr_img.save()
return HttpResponse("yees the first upload is right !! :X")
else:
return HttpResponse("Noooooo!!!")
except:
pass
this is my form.py
class User_image_form(forms.Form):
imgfile = forms.FileField()
and this is my models.py
class User_image(models.Model):
imgfile = models.ImageField(upload_to = 'User-Image')
#user = models.ForeignKey(User_account)
and i have problem in view.py at line which
usr_img = User_image(imgfile = request.FILES['imgfile'])
and it's never get to the
return HttpResponse("Yes")
error:
Exception Value: The view User.views.uploadimg didn't return an HttpResponse object.
Plz Help
If there is an exception, you are not returning an HttpResponse object. Hence the error.
use form.is_valid() to see if the form is valid.
Something like this:
if request.method == 'POST':
form = User_image_form(request.POST, request.FILES)
if form.is_valid():
usr_img = User_image(imgfile = form.cleaned_data['imgfile'])
usr_img.user = user
usr_img.save()
return HttpResponse("yees the first upload is right !! :X")
else:
print form.errors #for debugging purposes only.
return HttpResponse("Noooooo!!!")