test client in tutorial 5 of django - django-tests

while doing tutorial 5 of django, in the section Django test client every thing work fine until now but when I write this code in shell from "response = client.get(reverse('polls:index'))" I got some error. I am not understanding what the error is about and so not able to correct it.
Please help how to correct it.
Screen shot of error.
Screen shot of error.
this is mysite/polls/views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views import generic
from .models import Choice, Question
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""Return the last five published questions."""
return Question.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
"""
"def vote(request, question_id):
" ... # same as above, no changes needed.
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
"""
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
this is mysite/polls/urls.py
from django.conf.urls import url
from . import views
app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

Related

multiple user-session managemnet

im trying to build an flask application with user authentication. each user has different pages to be shown. the issue im facing is whenever user A logs in his username is saved in session variable and i use this to prevent users toggling through url without logging in first. but whenever user B logs in,user A is able to see what user B can. the previous session data is being over written. it would amazing if anyone can let me know how do i declare another session each time a new user walks in.
from flask import Flask,render_template,redirect,session,request,g,make_response,url_for
import psycopg2
import os
appt = Flask(__name__)
appt.secret_key= os.urandom(16)
conn=psycopg2.connect( database="one",user="postgres",password="0000",host="localhost",port="5432" )
cursor = conn.cursor()
cursor.execute("select username from use")
us=cursor.fetchall()
cursor.execute("select password from use")
psw= cursor.fetchall()
i use the above database data for user authentication
#appt.route('/',methods=['GET','POST'])
def index():
if request.method=='POST':
global user_name
user_name=request.form['username'] # make it global
pass_word=request.form['password']
for i in range(len(us)):
if user_name in us[i][0]:
new=psw[i][0]
if new==pass_word:
print(session.get('user'))
if 'user' not in session:
print('new user')
user = request.form['username'] # setting user to cookie with userid: username
resp = make_response(render_template('monitor.html'))
resp.set_cookie('userID', user) # setting a cookie
print(request.cookies.get('userID'))
return resp
else:
print('old user')
return session.get('user')
else:
return render_template('login.html',info="invalid user")
return render_template('login.html')
#appt.route('/logout', methods=['GET', 'POST'])
def logout():
print("hello")
if g.user:
if request.method == 'GET':
print("hello")
print(session['user'][0])
session.pop('user',None)
return render_template("login.html")
else:
return redirect("monitor.html")
#appt.before_request
def before_request():
#g.user=None
if 'user' in session:
g.user = session['user']
if __name__ == '__main__':
appt.run(debug=True)

Unable to start a Session in Flask within a function

I'm running Flask Session and using Eve as an API. For the Session code I'm following the example here https://pythonhosted.org/Flask-Session/
from flask import Flask, session
from flask.ext.session import Session
app = Flask(__name__)
# Check Configuration section for more details
SESSION_TYPE = 'redis'
app.config.from_object(__name__)
Session(app)
#app.route('/set/')
def set():
session['key'] = 'value'
return 'ok'
#app.route('/get/')
def get():
return session.get('key', 'not set')
I have an Eve API located under /api, and I want to avoid starting a new Session for those requests at least.
I want to start my flask Session only if the request.environ['PATH_INFO'] doesn't start with '/api/' but whenever I put Session() anywhere else it fails.
Following the example:
sess = Session()
sess.init_app(app)
When I try to do that in before_request or similar, then I get:
A setup function was called after the first request was handled.
and if I try to start a session in a normal content generator I get:
AttributeError: 'SecureCookieSession' object has no attribute 'sid'
How can I start a session conditionally, depending on the path/environment/etc?
My current code looks like this:
import flask
import xml.etree.ElementTree as ElementTree
from bson.objectid import ObjectId
from random import shuffle, choice as pick
from cgi import escape as escapehtml
from time import mktime
from urllib import quote as escapeurl, unquote_plus as unescapeurl
from flask import Flask, request, session, render_template, send_from_directory, jsonify, redirect, abort
from flask.ext.session import Session
from flask.ext.login import LoginManager, login_user, logout_user, current_user, UserMixin, user_logged_in, login_required, fresh_login_required
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired, URLSafeTimedSerializer
from flask_mail import Mail, Message
from wtforms import Form, BooleanField, PasswordField
from flask.ext.mongoengine import MongoEngine
from flask.ext.security import Security, MongoEngineUserDatastore, RoleMixin, UserMixin
from flask.ext.principal import Principal, Permission, RoleNeed
from flask_security.forms import RegisterForm, Required, StringField
from flask_images import Images
from eve import Eve
from eve.auth import TokenAuth
from flask.ext.moment import Moment
from eve.io.mongo import Validator
from flask.ext.cors import CORS, cross_origin
from app.admin.one1 import one1
from app.emails.emails import emails
from app.alligator.alligator import alligator
from app.data.ndm_feed.ndm_feed import ndm_feed
from flask.ext import excel
...
login_serializer = URLSafeTimedSerializer(app.secret_key)
login_manager = LoginManager()
app.config.from_object(__name__)
login_manager.init_app(app)
Session(app)
and to avoid starting sessions for API calls I am trying to do things like this:
#app.before_request
def before_request():
if not request.environ['PATH_INFO'].startswith('/api/'):
Session(app)
or the equivalent:
#app.before_request
def before_request():
if not request.environ['PATH_INFO'].startswith('/api/'):
sess = Session()
sess.init_app(app)
But I can't seem to find a way to do it without the errors above.
How can I start a Flask session conditionally, depending on the path/environment/etc?
Actually your app already created before you use this: #app.before_request so it means you are late to add new configuration or extension initialize. Bu you can do with Blueprint:
# api.py
from flask import Blueprint
from flask_session import Session
sess = Session()
api = Blueprint('api', __name__)
# yourapp.py
...
def create_app():
...
try:
from api import api, sess
sess.init_app(app)
app.register_blueprint(api)
# views.py
#api.route('/set/')
def set():
session['key'] = 'value'
return 'ok

Okta api python sdk throwing json error

I'm trying to create a user with the python sdk. When I run my script, I get the following error:
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/sitepackages/oktasdk-python/okta/framework/ApiClient.py", line 53, in post
if self.__check_response(resp, attempts):
File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/sitepackages/oktasdk-python/okta/framework/ApiClient.py", line 88, in __check_response
raise OktaError(json.loads(resp.text))
okta.framework.OktaError.OktaError: The request body was not well-formed: Could not read JSON
Here is a snippet of my code:
from okta.UsersClient import UsersClient
from collections import namedtuple
def main():
create_okta_user()
def create_okta_user():
usersClient = UsersClient("https://example.okta.com", "0d0d0dexamplekey")
User = namedtuple("User", ["login", "email", "firstName", "lastName"], verbose=False, rename=False)
user = User(login="test#example.com",
email="test#example.com",
firstName="user",
lastName="tester")
usersClient.create_user(user, activate=False)
#usersClient.activate_user(user)
main()
It looks like you're trying to use a namedtuple, which is serialized to a json list, not an object.
Try using the User model like this:
from okta import UsersClient
from okta.models.user import User
def main():
create_okta_user()
def create_okta_user():
usersClient = UsersClient("https://example.okta.com", "0d0d0dexamplekey")
user = User(login="test#example.com",
email="test#example.com",
firstName="user",
lastName="tester")
user = usersClient.create_user(user, activate=False)
#usersClient.activate_user(user)
main()
http://developer.okta.com/docs/sdk/core/python_api_sdk/quickstart.html#create-a-user

Shared state between WebSocketHandler and RequestHandler

I am writing chat app and I need session data in my websocket handler. Problem is that login and logout is done by AJAX request, and updating/clearing cookie cannot be seen by websocket handler - it sees only state from the time website was initially rendered. But it cannot see, when cookie is changed by AJAX request. Do you have any idea, how this can be implemented?
import json
import tornado.web
import tornado.websocket
class BaseHandler(object):
#property
def db(self):
return self.application.db
def get_current_user(self):
id = self.get_secure_cookie('user')
user = self.db.get_user_by_id(id) if id else ''
return user
class JsonHandler(BaseHandler, tornado.web.RequestHandler):
def write(self, response):
if response:
response = json.dumps(response)
TemplateHandler.write(self, response)
#property
def body(self):
return json.loads(self.request.body.decode())
class WebSocketHandler(BaseHandler, tornado.websocket.WebSocketHandler):
pass
class Login(JsonHandler):
def post(self):
login = self.body.get('login')
password = self.body.get('password')
user = self.db.validate_user(login, password)
if user:
self.set_secure_cookie('user', str(user['id']))
self.write(user)
else:
raise tornado.web.HTTPError(401)
class Logout(JsonHandler):
def post(self):
self.clear_cookie('user')
self.write('')
class WebSocket(WebSocketHandler):
clients = set()
def open(self):
WebSocket.clients.add(self)
def on_close(self):
WebSocket.clients.remove(self)
def on_message(self, message):
# how to use method self.get_current_user()
# it uses self.get_secure_cookie('user')
# but it is not updated dynamically by Login and Logout handlers
# because websocket does not share state with them
for client in WebSocket.clients:
client.write_message(message)

Pylons, FormEncode and external validation

I'm building a web frontend to a server-side application, using Pylons 1.0.
Right now I'm writing the first form, and I'm facing a problem concerning validation.. Using FormEncode and the #validate decorator I can easily validate the user input from a client-side perspective, but when I submit the data to the server, it may perform additional checks and eventually throw back exceptions that I need to show to the user.
My question: is there a concise way to integrate/emulate this exception handling into the FormEncode/validate flow? For example, redisplay the form with filled fields and an error message, as would happen if the exception had come from the #validate itself?
Here's what I have at the moment:
def edit(self, id):
return render('/edit_user.mako')
#validate(schema=form.UserForm(), form="edit")
def add_user(self):
if request.POST:
u = helpers.load_attributes(User(), self.form_result)
try:
model.save_to_server(u)
except MyBaseException, exc:
helpers.flash(unicode(exc))
return self.edit()
In this way, in case of a server-side exception I can see the "flash" message but the form of course will have empty fields :/
I like to implement:
from formencode import htmlfill
def create(self):
if request.params:
try:
Post.validate(request.paramse)
post = helpers.load_attributes(Post(), request.params)
model.save_to_server(post)
flash('OK', 'success')
redirect(...)
except InvalidException as e:
for key, message in e.unpack_errors().iteritems():
flash(message, 'error')
return htmlfill.render(render('/blogs/create.html'), request.params)
where my Post.validate:
#staticmethod
def validate(data):
schema = PostSchema()
schema.to_python(data)
In this way, if is the first time (request.params empty) html fills form with nothing, when user send datas html fills form with request.params
Another way (inspired by this answer) is to write a decorator similar to #validate that would catch the desired exceptions and use htmlfill to display their message:
def handle_exceptions(form):
def wrapper(func, self, *args, **kwargs):
try:
return func(self, *args, **kwargs)
except MyBaseException, e:
request = self._py_object.request
errors = { "exception" : unicode(e) }
params = request.POST
decoded = params.mixed()
request.environ['REQUEST_METHOD'] = 'GET'
self._py_object.tmpl_context.form_errors = errors
request.environ['pylons.routes_dict']['action'] = form
response = self._dispatch_call()
# If the form_content is an exception response, return it
if hasattr(response, '_exception'):
return response
htmlfill_kwargs2 = {}
htmlfill_kwargs2.setdefault('encoding', request.charset)
return htmlfill.render(response, defaults=params, errors=errors,
**htmlfill_kwargs2)
return decorator(wrapper)
The decorator would be used like:
#handle_exceptions("edit")
#validate(schema=form.UserForm(), form="edit")
def add_user(self):
if request.POST:
u = helpers.load_attributes(User(), self.form_result)
model.save_to_server(u)

Resources