How do I submit "POST" method forms in Django without AJAX? - python

I'm completely new to Django and I'm also developing a very important project in this framework with some friends. I'm having problems in submitting a "POST" method form in Django.
I'm having the "403 Forbidden" error. It says that my CSRF token isn't configured correctly. I'm pretty sure that I did setup it correctly, though.
My form is about updating an django user account in the database (MySQL). I also don't know if my program logic is right in the view. I didn't even had the opportunity to test it because of this dumb error.
The image and codes below exemplificate my problem.
My form:
<form method="POST" action="/validacao/" name="user" class="current2"> {% csrf_token %}
<table>
<tr>
<td>Nome:</td><td>
<input type='text' name='first_name' maxlength='30' value='{{usuario.first_name}}' class="campo2" />
</td>
<td>Permissão: <font style="color: red;">
{% if usuario.is_staff %} Admin {% else %} Comum {% endif %}</font>
</td>
</tr>
<tr>
<td>Sobrenome:</td>
<td><input type='text' name='last_name' maxlength='30' value='{{usuario.last_name}}' class="campo2" /></td>
</tr>
<tr>
<td>Email:</td>
<td><input type='text' name='email' maxlength='75' value='{{usuario.email}}' class="campo2"/></td>
</tr>
<tr>
<td>Senha:</td><td> <input type='password' name='password' maxlength='120' class="campo2"/></td>
</tr>
<tr>
<td>Confirmar Senha:</td><td><input type='password' name='password2' maxlength='120' class="campo2"/></td>
</tr>
<tr><td></td><td><input type='submit' name='salvar' value='Salvar' class="botao2"/></td></tr>
</table>
</form>
My view:
def validacao_perfil(request):
if request.POST:
try:
request.user.first_name = request.POST['first_name']
request.user.last_name = request.POST['last_name']
request.user.email = request.POST['email']
request.user.password = request.POST['password']
request.user.save()
validacao=1
except:
validacao=0
variaveis_resposta={ 'usuario':request.user,
'MEDIA_URL':settings.MEDIA_URL,
'height_backgroud':'900',
'rodape':'position:relative; top: 148px;',
'ordem':0,
'validacao':validacao,
'context_instance':RequestContext(request),
}
return render_to_response("perfil_usuario.html", variaveis_resposta)
Obs.: the "urls.py" is set correctly and the bizarre thing is that I can see the csrftoken cookie var using Django Debug Toolbar.

just put #csrf_exempt on your def validacao_perfil(request):, to see if this work,and also try to read the doc of django .It's very good!!

Related

Multiple button in Django: Accept and Reject

I am new to Django. I am working on a project where I want accept and reject button and whenever client click on the respective button that object will go into the accept or reject template. I have no idea how can I do this.
This is my .html file which is displaying all the objects and have a accept and reject button:
<div class="body table-responsive">
<form id="form" method="POST" action = "{% url 'admin_team_detail' %}">
{% csrf_token %}
<table class="table table-hover">
<thead>
<tr>
<th>S No.</th>
<th>COMPANY NAME</th>
<th>TEAM MEMBER</th>
<th>EMAIL</th>
<th>STATUS</th>
<th><center>#</center></th>
</tr>
</thead>
<tbody>
{%for team in object%}
<tr>
<th scope="row"> {{ forloop.counter }}</th>
<td>{{team.company_name}}</td>
<td>{{team.team_member}}</td>
<td>{{team.email}}</td>
<td>-</td>
<td><center><input type="submit" value="accept" name="accept">
<input type="submit" value="reject" name="reject"></center></td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
Here is views.py:
def admin_team_detail(request):
obj= Create_Team.objects.all()
print(request.method)
if request.method == 'POST':
if 'reject' in request.POST :
Create_Team.status = 'reject'
else:
Create_Team.status = 'accept'
Create_Team.save()
return render(request, "admin/team-details.html", {"object": obj})
This is rendering all the objects from database and displaying on the website.
I know that I have to make two templates for accept and reject but I don't know how it will take the objects that have a accept or reject response.
And I also want that if client click on the button then that response will be saved in the database.
And I also want to know that whether I have to add a field in my model.py for status.
First your two buttons should send the desired value to your views.py and one hidden input in order to pass the team id
<input type="submit" value="reject" name="status">
<input type="submit" value="accept" name="status">
<input type="hidden" name="id" value={{ team.id }}>
Next, in your views.py
def admin_team_detail(request):
if request.method == 'POST':
# First, you should retrieve the team instance you want to update
team = Create_Team.objects.get(id=request.POST('id'))
# Next, you update the status
if request.POST.get('status'):
team.status = request.POST.get('status')
team.save()
Note: this example assumes your Team model has a status field in order to store the reject/accept value.
class Team(models.Model):
# You existing fields...
status = models.CharField(max_length=30)
First You need to create a form for each object inside the template.
{%for team in object%}
<form method="POST">
{%csrf_token%}
<input type="hidden" name="team_id" value={{ team.id }}>
<input type="submit" value="reject" name="status">
<input type="submit" value="accept" name="status">
</form>
{% endfor %}
Now in View.py, you need to do something like this:
def admin_team_detail(request):
if request.method == 'POST':
# I am assuming Create_Team is your model where all team's are present.
team = Create_Team.objects.get(id=request.POST.get("team_id"))
team.status = request.POST.get("status")
team.save()

HTML form button not deleting rows from sqlite database

I have built a forum in pythonanywhere using python and html, in which users can post information that gets inserted into a sqlite database. At the bottom of each post is a delete button that will delete the post that it's under from the database and refresh the page. Right now the delete button only refreshes the page while the post remains. I am wondering how to edit the code so that the post which the form button is attached to is deleted and the page is refreshed.
HTML Code snippet
{% for post in forumposts %}
<tr>
<td>
<h1>{{post[1]}}</h1>
<h3>{{post[3]}}</h3>
<p>{{post[2]}}</p>
<p>{{post[6]}}</p>
<img src="{{post[7]}}" alt="Wrong image link.">
<p></p>
<form action="{{ url_for('delete_post') }}" method=POST class=delete-post>
<input type=hidden value="{{ postid }}"name=post_to_delete></input>
<input type=submit></input>
</form>
</td>
</tr>
{%endfor%}
</table>
Python Code snippet
#app.route('/delete', methods=['POST'])
def delete_post():
db = connect_db()
db.execute('DELETE FROM posts WHERE postid = ?', [request.form['post_to_delete']])
db.commit()
db.close()
return redirect(url_for('forum'))
Got the code working.
HTML
{% for post in forumposts %}
<tr>
<td>
<h1>{{post[1]}}</h1>
<h3>{{post[3]}}</h3>
<p>{{post[2]}}</p>
<p>{{post[6]}}</p>
<img src="{{post[7]}}" alt="Wrong image link.">
<p></p>
<form action="{{ url_for('delete_post') }}" method=POST class=delete-post>
<input type=hidden value={{post[0]}} name=post_to_delete></input>
<input type=submit value=POST></input>
</form>
</td>
</tr>
{%endfor%}
</table>
PYTHON
#app.route('/delete', methods=['POST'])
def delete_post():
if request.method == 'POST':
db = connect_db()
db.execute('DELETE FROM posts WHERE postid = ?', (request.form['post_to_delete'],))
db.commit()
db.close()
return redirect(url_for('forum'))
Hope this helps someone. :)

Render an editable table using Flask, Jinja2 templates, then process the form data returned

I'm using Flask and Jinja2 and I need to make an editable table with multiple rows.
This is what the table will look like:
And here's HTML for that:
<form action="/support/team-members-update" method="post">
<table>
<tbody><tr>
<th>Name</th>
<th>Id</th>
<th>Inbox Share</th>
</tr>
<tr>
<td>Ben</td><td>55555</td><td><input type="text" name="share_55555" value="0"></td></tr> <tr>
<td>Steve</td><td>66666</td><td><input type="text" name="share_66666" value="1"></td></tr> <tr>
<td>Harry</td><td>77777</td><td><input type="text" name="share_77777" value="1"></td></tr> <tr>
<td>Sally</td><td>88888</td><td><input type="text" name="share_88888" value="1"></td></tr></tbody></table>
<button type="submit">Send</button>
</form>
My current implementation is in Lua, where I'm hard coding a bunch of strings and connecting up the post data to native Lua types by hand (fun!). If I have to, I can process the form data by hand in Python as well, but I imagine there's probably a better solution out there.
I have explored WTForms a bit, but haven't had much luck getting it to work correctly.
I did find FieldList, but that seems to deal with a list of the same field, not multiple rows with the same exact fields.
I also found TableWidget, but the documentation is sparse and I can't figure out how to implement it to know if that would do what I'm looking to do.
FieldList will work, you need to make a list of a FormField. Specify your FormField like so:
class MemberForm(Form):
name = StringField('name')
member_id = StringField('member_id')
inbox_share = IntegerField('inbox_share')
# etc.
class TeamForm(Form):
title = StringField('title')
teammembers = FieldList(FormField(MemberForm))
Then you can create the forms from your database in a view function like so:
#app.route('/support/team-members-update', methods=['GET','POST'])
def update_team_members():
teamform = TeamForm()
teamform.title.data = "My Team" # change the field's data
for member in DB.get('teammembers') # some database function to get a list of team members
member_form = MemberForm()
member_form.name = member.name # These fields don't use 'data'
member_form.member_id = member.id
member_form.inbox_share = member.share
teamform.teammembers.append_entry(member_form)
return render_template('edit-team.html', teamform = teamform)
And then in the template, you can iterate over each item in teammembers as you create your table rows:
<html>
<head>
<title>Edit Team Members</title>
</head>
<body>
<h1>Edit Team</h1>
<div>
<form action="" method="post" name="teamform">
{{ teamform.hidden_tag() }}
Team Title: {{ teamform.title }}<br>
<div>
<table>
<tr>
<th> Name </th>
<th> ID </th>
<th> Inbox Share </th>
</tr>
{% for member in teamform.teammembers %}
<tr>
<td>{{ member.name }}</td>
<td>{{ member.member_id }}</td>
<td>{{ member.inbox_share }}</td>
</tr>
{% endfor %}
</table>
</div>
<p><input type="submit" name="edit" value="Send"></p>
</form>
</div>
</body>
</html>
I never was able to get WTForms to work quite how I wanted. I think it was a bit too heavy for my needs, so I ended up just using my own Jinja2 template to build the form and then used the formencode library to parse the post variables into a dict. This works well enough for me. (Thanks to this question for pointing me to the formencode library).
I'll give you a rough look at the various files I'm using and then explain the important parts at the bottom:
app.py:
from flask import Flask, render_template, request
from formencode import variabledecode
import pickledb
app = Flask(__name__)
DB = pickledb.load('data/data.db', False)
#app.route('/team-members', methods=['GET', 'POST'])
def team_members():
global DB
teammembers = DB.get('teammembers')
# teammembers looks like this, roughly:
# [{"id": 55555, "name": "Ben", "share": 0},
# {"id": 66666, "name": "Amy", "share": 1},
# {"id": 77777, "name": "Ted", "share": 1}]
if request.method == 'POST':
postvars = variabledecode.variable_decode(request.form, dict_char='_')
for k, v in postvars.iteritems():
member = [m for m in teammembers if m["id"] == int(k)][0]
member['share'] = v["share"]
DB.set('teammembers', teammembers)
DB.dump()
return render_template('team-members.html', teammembers=teammembers)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--debug', '-d', action='store_true')
parser.add_argument('--port', '-p', default=5000, type=int)
parser.add_argument('--host', default='0.0.0.0')
args = parser.parse_args()
app.run(args.host, args.port, debug=args.debug)
I have three template files, but you of course don't need this many. team-members.html has the code that's relevant to this problem.
_formhelpers.html:
{% macro render_input(id, fieldname, value) %}<input type="text" name="{{ id }}_{{ fieldname }}" value="{{ value }}" />{% endmacro %}
layout.html:
<!doctype html>
<html>
<head>
<title>Support Team Site</title>
</head>
<body>
<div class="page">
<h1>Support Team Site</h1>
{% for message in get_flashed_messages() %}
<div class=flash>{{ message }}</div>
{% endfor %}
{% block body %}{% endblock %}
</div>
</body>
</html>
team-members.html:
{% from "_formhelpers.html" import render_input %}
{% extends "layout.html" %}
{% block body %}
<form action="/team-members" method="post">
<table>
<tr>
<th>Name</th>
<th>ID</th>
<th>Inbox Share</th>
</tr>
{% for member in teammembers %}
<tr>
<td>{{member['name']}}</td>
<td>{{member['id']}}</td>
<td>{{ render_input(member['id'], 'share', member['share']) }}</td>
</tr>
{% endfor %}
</table>
<button type="submit">Send</button>
</form>
{% endblock %}
This will render the following HTML:
<!doctype html>
<html>
<head>
<title>Support Team Site</title>
</head>
<body>
<div class="page">
<h1>Support Team Site</h1>
<form action="/team-members" method="post">
<table>
<tr>
<th>Name</th>
<th>ID</th>
<th>Inbox Share</th>
</tr>
<tr>
<td>Ben</td>
<td>55555</td>
<td><input type="text" name="55555_share" value="0" /></td>
</tr>
<tr>
<td>Amy</td>
<td>66666</td>
<td><input type="text" name="66666_share" value="1" /></td>
</tr>
<tr>
<td>Ted</td>
<td>77777</td>
<td><input type="text" name="77777_share" value="1" /></td>
</tr>
</table>
<button type="submit">Send</button>
</form>
</div>
</body>
</html>
It's worth mentioning what's going on in the if request.method == 'POST': part of app.py. The request.form variable will be of type ImmutableMultiDict, which would look kind of like this when printed out:
ImmutableMultiDict([('55555_share', u'0'), ('66666_share', u'1'), ('77777_share', u'1')])
This is somewhat useful, but we'd still have to parse this by hand to do anything with it. Note the format of the keys there, in the id_fieldname format (e.g. 55555_share). This was thanks to the render_input macro we put in our _formhelpers.html template file. When we process the post form input, we use variabledecode.variable_decode(request.form, dict_char='_'), which parses the form data and turns it into a dictionary based on the naming convention we used for the name values of the form inputs. Here's what it looks like:
{
"55555": {
"share": "0"
},
"66666": {
"share": "1"
},
"77777": {
"share": "1"
}
}
This makes it easy to map back to our original data and update it.

login_required - login success not redirecting to "next"

I am googling for 2 hours now and no sign of success.
after successfull login, I need to redirect user to the page where he was before login, using next parameter in the url.
but if i do print request.GET.get('next'), i am getting None even if i have next in the url like ?next=/next-page/ why is this?
my login view.
username = request.POST.get('username_login')
pwd = request.POST.get('pwd_login')
user = authenticate(username=_username, password=pwd)
if user is not None:
if user.is_active:
login(request, user)
print request.GET.get('next')
if request.GET.get('next', False):
return HttpResponseRedirect(request.GET.get('next'))
else:
return render_to_response("profil.html",{},context_instance=RequestContext(request))
else:#user not active
fail = 'account inactive'
return render_to_response("anmelden.html",{'fail':fail},context_instance=RequestContext(request))
i am using django 1.4 and i am using contrib.auth.login(). why cannot i redirect to the page?
if you are using django.contrib.auth.login() that should mean you have simply to override django default login by using LOGIN_REDIRECT_URL for example, you only have to override the views.py if you want to sign up and redirect to login.
so you can override django login urls.py login.html and other.
settings.py:
LOGIN_REDIRECT_URL='/' # to redirect to the home after login
urls.py:
urlpatterns += patterns('django.contrib.auth.views',
(r'^login/$','login',{'template_name':'registration/login.html'},'login'),
)
login.html :
<div id="main">
{% if form.errors %}
<ul class="errorlist">
<li>You entered an invalid username or password</li>
</ul> <br/>
{% endif %}
<form method="POST" action="{% url "django.contrib.auth.views.login" %}">{% csrf_token %}
<table summary="login" id="login">
<caption>Login</caption>
<tr>
<td>{{form.username.label_tag}}:</td>
<td>{{form.username}}</td>
</tr>
<tr>
<td>{{form.password.label_tag}}:</td>
<td>{{form.password}}</td>
</tr>
<tr>
<td colspan="2" class="right">
<input type="submit" value="Login" /></td>
</tr>
</table>
<input type="hidden" name="next" value="{{next}}" />
</form>
</div>

Using WTForms' populate_obj( ) method with Flask micro framework

I have a template which allows the user to edit their user information.
<form method="post">
<table>
<tr>
<td>Username:</td>
<td>{{user['username']}}</td>
</tr>
<tr>
<td>New Password:</td>
<td> <input type="password" name="password"></td>
<td>{% if form.password.errors %} {{form.password.errors}} {% endif %}<td>
</tr>
<tr>
<td>Re-enter Password:</td>
<td> <input type="password" name="confirm_password">
</td>
</tr>
<input type='hidden' name='username' value="{{user['username']}}">
<tr>
<td><input type="submit" value="Submit"></td>
</tr>
</table>
</form>
I also have a view function for handling such edits by the user. The database I am currently using is MongoDB with the MongoKit module. I have only been able to do up to this so far in the view function, yet with no luck.
def edit():
username = request.args.get('user')
user = User.find_one({'username':username}) # Is this a correct way of doing it?
form = UserForm(**what should be placed here?**, obj=user)
if request.method == 'POST' and form.validate():
form.populate_obj(user)
user.save()
return 'updated'
return render_template('edituser.html', form=form, user=user)
I am going through populate_obj(obj) for this purpose. I couldn't find much help in this matter. What should I do in order to get populate_obj() working?
UserForm should have request.form passed into it to populate it with the values available in the POST request (if any).
form = UserForm(request.form, obj=user)
Are you using Flask-WTF? If so, check out the following sample code:
https://github.com/sean-/flask-skeleton/blob/master/skeleton/modules/aaa/views.py#L13
Specifically, you would:
def edit():
form = UserForm()
if form.validate_on_submit():
# Commit your form data
Bottom line, if you're using Flask-WTF, I'm not sure what your question is. If you aren't using Flask-WTF, use Flask-WTF.
In case of Flask-WTF, you can write like
form = UserForm(obj=user)
Thant will work!

Categories