How to use POST in Django - html

I use Django 1.11.3 and python2.7
I want write a easy message board
and here is my code
<form name='my form' action='/talkpost/' method='POST'>
{% csrf_token %}
{% for m in moods %}
<input type='radio' name='mood' value='{{ m.status }}'>{{ m.status }}
{% endfor %}
<textarea name='user_post' rows=3 cols=70></textarea><br/>
<label for='user_id'>nicknameļ¼š</label>
<input id='user_id' type='text' name='user_id'>
<label for='user_pass'>password</label>
<input id='user_pass' type='password' name='user_pass'><br/>
<input type='submit' value='submit'>
<input type='reset' value='reset'>
<input type="hidden" name="ok" value="yes">
</form>
urls.py
url(r'^talkpost/', talkpost),
url(r'^talk/', talk),
talk is just for user to see the from and talkpost is for Django to get the post
request
views.py
def talk(request):
template = get_template('talk.html')
moods = Mood.objects.all()
message = 'Leave some message!'
html = template.render(locals())
return HttpResponse(html)
def talkpost(request):
template = get_template('talk.html')
if 'ok' in request.POST:
user_id = request.POST['user_id']
user_pass = request.POST['user_pass']
user_post = request.POST['user_post']
user_mood = request.POST['mood']
message = 'success!'
request_context = RequestContext(request)
request_context.push(locals())
html = template.render(request_context)
return HttpResponse(html)
I try using {% csrf_token %} and RequestContext But i still get CSRF token missing or incorrect.
I have no idea how to fix it

add the following:
from django.views.decorators.csrf import csrf_protect
your function will be:
#csrf_protect
def talkpost(request):
template = get_template('talk.html')
if 'ok' in request.POST:
user_id = request.POST['user_id']
user_pass = request.POST['user_pass']
user_post = request.POST['user_post']
user_mood = request.POST['mood']
message = 'success!'
request_context = RequestContext(request)
request_context.push(locals())
html = template.render(request_context)
return HttpResponse(html)
more info here:
https://docs.djangoproject.com/ko/1.11/ref/csrf/#how-to-use-it

Related

HTML form with post method sent get request

I had a form which used post method. However, after I clicked sumbmit, only get request was sent. Can I please know why?
<form action="/review_page/{{yelp_id}}" method=post>
<label for="review-score">Your overall rating of this restaurant</label>
<select name="score" id="review-score">
{% for num in range(1,6) %}
<option value="{{ num }}">{{ num }}</option>
{% endfor %}
</select>
<div>
<label for="review-title">Title of your review</label><br>
<input type="text" name="title" id="review-title">
</div>
<div>
<label for="reviewText">Your review</label>
<div>
<textarea name="review" id="reviewText" data-minlen="100" data-maxlen="20000"
placeholder="Tell people about your experience"></textarea>
</div>
</div>
<input type="submit" value="Submit Your Review">
</form>
Please also find my routes below.
#app.route("/review_page/<yelp_id>", methods=["POST"])
def save_user_review(yelp_id):
"""Save user review into database"""
user_id = session.get("user_id")
print(user_id)
if user_id is None:
flash("Please log in to leave a review")
return redirect(f"/review_page/{yelp_id}")
else:
user = User.query.get(session["user_id"])
title = request.form.get("title")
score = int(request.form.get("score"))
review = request.form.get("review")
yelp_id = yelp_id
rating = crud.create_rating_without_pic(user, title, score, review, yelp_id)
db.session.add(rating)
db.session.commit()
return redirect(f"/rest_details/{yelp_id}")
Maybe is it.
You have this
<form action="/review_page/{{yelp_id}}" method=post>
And probably you should have this
<form action="/review_page/{{yelp_id}}" method="post">

Fetch preventing rendering template in the controller

I'm working on a project for a class and I have starter code that I am editing. they way its supposed to work is that when the user creates a venue it goes to the home page with a message saying venue x has been listed. Once I add the post request in the new_venue.html it does nothing after I click the submit button nothing happens, but I know its doing something because the app.py prints the name that signed up.
Below is Code from the new_venue.html.
I added the script section and the post request
{% extends 'layouts/main.html' %}
{% block title %}New Venue{% endblock %}
{% block content %}
<div class="form-wrapper">
<form id="venueInfo" method="post" class="form">
<h3 class="form-heading">List a new venue <i class="fa fa-home pull-right"></i></h3>
<div class="form-group">
<label for="name">Name</label>
{{ form.name(id='name', class_ = 'form-control', autofocus = true) }}
</div>
<div class="form-group">
<label>City & State</label>
<div class="form-inline">
<div id='city' class="form-group">
{{ form.city(class_ = 'form-control', placeholder='City', autofocus = true) }}
</div>
<div id='state' class="form-group">
{{ form.state(class_ = 'form-control', placeholder='State', autofocus = true) }}
</div>
</div>
</div>
<div id='address' class="form-group">
<label for="address">Address</label>
{{ form.address(class_ = 'form-control', autofocus = true) }}
</div>
<div id='phone_num' class="form-group">
<label for="phone">Phone</label>
{{ form.phone(class_ = 'form-control', placeholder='xxx-xxx-xxxx', autofocus = true) }}
</div>
<div id="genres" class="form-group">
<label for="genres">Genres</label>
<small>Ctrl+Click to select multiple</small>
{{ form.genres(class_ = 'form-control', autofocus = true) }}
</div>
<div id="fb_link" class="form-group">
<label for="genres">Facebook Link</label>
{{ form.facebook_link(class_ = 'form-control', placeholder='http://', autofocus = true) }}
</div>
<input type="submit" value="Create Venue" class="btn btn-primary btn-lg btn-block">
</form>
<script type="text/javascript">
document.getElementById("venueInfo").onsubmit=function(e){
e.preventDefault();
fetch('/venues/create',{
method:'POST',
body:JSON.stringify({
'name': document.getElementById('name').value,
'city': document.getElementById('city').value,
'state': document.getElementById('state').value,
'address': document.getElementById('address').value,
'phone_num': document.getElementById('phone_num').value,
'genres': document.getElementById('genres').value,
'fb_link': document.getElementById('fb_link').value,
}),
headers: {'Content-type': 'application/json'}
})
.then(function(){
})
}
</script>
</div>
{% endblock %}
below is the code from app.py
#app.route('/venues/create', methods=['GET'])
def create_venue_form():
form = VenueForm()
return render_template('forms/new_venue.html', form=form)
#app.route('/venues/create', methods=['POST'])
def create_venue_submission():
name = request.get_json()['name']
print(name)
flash('Venue ' + request.form['name'] + ' was successfully listed!')
return render_template('pages/home.html')
flash messages work with redirection, refer to https://flask.palletsprojects.com/en/1.1.x/patterns/flashing/#simple-flashing
so instead rendering the template, return redirection object to the home page:
#app.route('/venues/create', methods=['POST'])
def create_venue_submission():
# name = request.get_json()['name']
name = request.values.get('name')
print(name)
flash('Venue ' + request.form['name'] + ' was successfully listed!')
# return render_template('pages/home.html')
return redirect(url_for('home')) # -- HERE --
Update
i think you are doing things the wrong way, you don't need the javascript to submit the form data via ajax post since ajax is used to update the page without reloading it (btw you didn't put any logic in .then(function(){}) callback to show up the message), but after submitting the form you want to redirect the user to the home page with a flash message so the ajax approach you are using is the wrong approach, just remove or comment the javascript code block and add the action to the form
<form id="venueInfo" method="post" action="{{ url_for('create_venue_submission') }}" class="form">
...
and in your function create_venue_submission() you should change
name = request.get_json()['name']
to
name = request.values.get('name')
# other fields
name = request.values.get('name')
city = request.values.get('city')
state = request.values.get('state')
address = request.values.get('address')
phone_num = request.values.get('phone_num')
genres = request.values.get('genres')
fb_link = request.values.get('fb_link')
see this wiki https://stackoverflow.com/a/16664376/12368419
If you are submitting your form via ajax, you will need to redirect in the success portion of the ajax call. Also, keep in mind that flash will not work via ajax. You will need to use the standard form post.
$.ajax({
'url': 'post_url',
success: function(msg){
//read the msg here and determine if success or not then redirect
}
})
This will not work when doing an ajax form post:
return redirect(url_for('index'))
If you use the standard (pseudo code) without posting via ajax, it will redirect:
<form method=post action=route>
<input type=submit>
</form>

How to set number of files that can be uploaded in flask

I want to limit number of images per post request in flask so how can i do that
My Code
from flask import Flask, redirect, url_for, render_template, request
from werkzeug.utils import secure_filename
from flask_uploads import UploadSet , IMAGES, configure_uploads
app = Flask(__name__)
UPLOAD_FOLDER = 'static/img/'
photos = UploadSet('photos', IMAGES)
app.config['MAX_CONTENT_LENGTH'] = 4 * 1024 * 1024
app.config['UPLOADED_PHOTOS_DEST'] = UPLOAD_FOLDER
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
configure_uploads(app, photos)
#app.route('/upload/', methods=["POST","GET"])
def upload():
if request.method == "POST" and 'photo' in request.files:
photo = request.files['photo']
photos.save(photo)
return 'saved'
else:
return render_template("upload.html)
if __name__ == "__main__":
app.run(debug=True,host="0.0.0.0", port="5000")
I want to be able to upload multiple files but limit only 2 at back-end
also is there a way to limit file upload in html?
HTML Code
<form action="#" method="POST" enctype="multipart/form-data">
<div class="custom-file">
<label for="customFile">Choose Cover Photo --Optional--</label>
<br>
<input type="file" name="photo" id="customFile">
</div>
</form>
Below is the code to handle the file limit from backend:
#app.route('/upload', methods=["POST","GET"])
def upload():
if request.method == "POST" and 'photo' in request.files:
uploaded_photos = request.files.getlist('photo')
if len(uploaded_photos) > 2:
error = "You are only allowed to upload a maximum of 2 files"
return render_template("upload.html", error=error)
else:
for photo in uploaded_photos:
photos.save(photo)
return 'saved'
else:
return render_template("upload.html")
Need to specify multiple attribute in the input field of the file to allow multiple images to be uploaded at a time
{% if error %}
<p class=error><strong>Error:</strong> {{ error }}</p>
{% endif %}
<form action="upload" method="POST" enctype="multipart/form-data">
<div class="custom-file">
<label for="customFile">Choose Cover Photo --Optional--</label>
<br>
<input type="file" name="photo" id="customFile" multiple>
<input type = "submit" value = "submit">
</div>
</form>
You can handle it in frontend using jquery. Below is the code.
$(function(){
$("input[type = 'submit']").click(function(){
var $fileUpload = $("input[type='file']");
if (parseInt($fileUpload.get(0).files.length) > 2){
alert("You are only allowed to upload a maximum of 2 files");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="#" method="POST" enctype="multipart/form-data">
<div class="custom-file">
<label for="customFile">Choose Cover Photo --Optional--</label>
<br>
<input type="file" name="photo" id="customFile" multiple>
<input type = "submit" value = "submit">
</div>
</form>

how to get post data in django from iterating over different id

I am creating a app which is quetion and 4 options.Each time it gives different 5 quetions.using a id in html page i am creating a radio button for each choice.Now how can save this value by post method in database.
views.py
def result(request,id) :
if request.method=='POST':
selected_choice = request.POST['choice.id']
return redirect('list_view.html')
else:
return render (request,'create_view.html')
urls.py
path('result/<id>',views.result,name='result')
html page
<div>
{% for element in q %}
<h2>{{element.id}} .{{element.question}}</h2>
<form action="{% url 'app1:result' element.id %}" method="POST">
{% csrf_token %}
{% for choice in c %}
{% if element.id == choice.id %}
<input name="{{choice.id}}" type="radio" >{{choice.choice1}}<br>
<input name="{{choice.id}}" type="radio" >{{choice.choice2}}<br>
<input name="{{choice.id}}" type="radio" >{{choice.choice3}}<br>
<input name="{{choice.id}}" type="radio" >{{choice.choice4}}<br>
{% endif %}
{% endfor %}<br>
{% endfor %}
<input type="submit" value="submit">
</form>
</div>
models.py
class Question(models.Model):
question=models.CharField(max_length=100)
def __str__(self):
return self.question
class Choice(models.Model):
choice1=models.CharField(max_length=50)
choice2=models.CharField(max_length=50)
choice3 = models.CharField(max_length=50)
choice4 = models.CharField(max_length=50)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
I would for sure try to go for Django forms for this. It is much easier. Check the answer from this question where it is detailed how to configure a radio button using Django forms.
You would like to change the input name of your choices from {{choice.id}} to choiceid-{{choice-id}}, it makes implementation easier.
For each input radio choice field, add a value attribute, for ex:
<input name="{{choice.id}}" type="radio" value="choice1">{{choice.choice1}}<br>
Create a ChoiceAnswer model with choice as foreign key.
for key in request.POST:
if key.startswith('choiceid-'):
# You can access user by request.user .
# Extract the choice here so that you can reference it in ChoiceAnswer instance.
choice = get_object_or_404(Choice, id=key.split('-')
if request.POST[key] == 'choice1':
# save data in your answer model here that choice1 has been selected.
elif request.POST[key] == 'choice2':
# save data in your answer model here that choice2 has been selected.

Appear data in URL form bu using Django

I want to create a record and want to appear data in the form fields. How can I do that ? Do I need to write javascript for it. If you help me, really apprepriate it. Thanks for now.
Here is models.py;
class hesaplarim(models.Model):
hesap_id = models.AutoField(primary_key=True)
tc_no = models.IntegerField(unique=True)
name = models.CharField(max_length=55)
surname = models.CharField(max_length=55)
phone_number = models.IntegerField()
gender = models.CharField(max_length=5)
Here is views.py;
def home(request):
form = HesapForm(request.POST or None)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = HesapForm()
return render(request, 'home.html', {'form': form})
Here is forms.py;
class HesapForm(forms.ModelForm):
ERKEK = 'ERKEK'
KADIN = 'KADIN'
gender_choices = (
(ERKEK, 'ERKEK'),
(KADIN, 'KADIN')
)
tc_no = forms.IntegerField(widget=forms.NumberInput)
name = forms.CharField(widget=forms.TextInput)
surname = forms.CharField(widget=forms.TextInput)
phone_number = forms.IntegerField(widget=forms.NumberInput)
gender = forms.ChoiceField(choices=gender_choices)
class Meta:
model = hesaplarim
fields = ('tc_no', 'name', 'surname', 'phone_number',
'gender')
Here is html file;
<form method="post" class="form-horizontal" novalidate>
{% csrf_token %}
<div class="form-group">
<label for="id_tc_no">TC No:</label>
{{ form.tc_no }}
</div>
<div class="form-group">
<label for="id_name">Ad:</label>
{{ form.name }}
</div>
<div class="form-group">
<label for="id_surname">Soyad:</label>
{{ form.surname }}
</div>
<div class="form-group">
<label for="id_phone">Cep Telefonu:</label>
{{ form.phone_number }}
</div>
<div class="form-group">
<label for="id_gender">Cinsiyet:</label>
{{ form.gender }}
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Kaydet">
</div>
</form>
You need to initialize the form:
def home(request):
form = HesapForm(request.POST or None)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = HesapForm(initial={'your_field': 'your_value'})
return render(request, 'home.html', {'form': form})
Dynamic initial values you can refer about the same here.
You can also initialize it with object as well.