django session key error for my simple captcha form - django

I just write a simple captcha for my login form.
I just add a simple session data.request.session['captcha'].
This is the login views function:
login (request):
if request.method =='GET':
form = LoginForm(auto_id=True)
a = random.randrange(1,10,1)
b = random.randrange(10,20.1)
request.session['captcha1']=a
request.session['captcha2']=b
return render_to_response('login.html',locals(),context_instance=RequestContext(request))
if request.method =='POST':
form = LoginForm(data=request.POST)
if form.is_valid():
captcha= request.POST.get('captcha','')
result = request.session.get('captcha1') + request.session.get('captcha2')
if captcha==result:
data = form.clean()
user=authenticate(username= data['username'],password = data['password'])
if user is not None:
auth_login(request,user)
return HttpResponseRedirect('/')
else:
form = LoginForm(auto_id=True)
return render_to_response('login.html',locals(),context_instance=RequestContext(request))
This is the login form
class LoginForm (forms.Form):
username = forms.CharField(
label='username')
password =forms.CharField(
label='password',widget = forms.PasswordInput())
captcha = forms.CharField(label='spam chercker')
I get keyerror for captcha1, captcha2, and when I add print request.session['captcha1'], it shows None. That means, when POST, I do not get the django session data, there is no data captcha1 and captcha2
How can I store the data in django session, and pass it to the POST method, and in other views function?
thanks

Instead of taking this approach, you might also want to look at existing Django captcha packages:
https://www.djangopackages.com/grids/g/captcha/
If you're looking for something simple, Django-Simple-Captcha is a great option.

Related

how to check whether user after login has submitted the form one , if yes again if he login he should redirect to form 2 not one again in django

I have an app where user login and after he logins he get redirect to dashboard where appears a form and user fill the form , once user fill the form he redirect to next page where it shows the progress of the form. So if user login again he should automatically redirect to the progress page he should not get the form page again if he has filled it .
Can any one suggest me how to achieve these.
views.py
def create(request):
if request.method == 'POST':
post = AccountProfile()
post.user = request.user
post.name = request.POST['name']
post.email = request.POST['email']
post.mobile = request.POST['mobile']
post.date = request.POST['date']
post.sex = request.POST['sex']
post.save()
return render (request,'posts/dashboard-post-a-job.html')
These is the views where user get redirect after login and fill form.
You should store the progress in the database. If you need to check for only one form, then add a new column in AccountProfile model.
models.py
class AccountProfile(models.Model):
...
form1_submitted = models.BooleanField()
Then, once the form is submitted, you can update this field.
def create(request):
if request.method == 'POST':
post = AccountProfile()
post.user = request.user
post.name = request.POST['name']
post.email = request.POST['email']
post.mobile = request.POST['mobile']
post.date = request.POST['date']
post.sex = request.POST['sex']
post.form1_submitted = True # save the progress
post.save()
return render (request,'posts/dashboard-post-a-job.html')
Now, the progress page can check the value of this field and render the form accordingly.

How to update user profile in django properly

i created a form to update a django profile, i use the default user model, when i submit the form and logout and i tried to login again, the new password is not working, but the old one is.
this is my update view :
def edit_profil_to_base(request):
if not request.user.is_authenticated:
return redirect('authentification')
else:
nom_profil_new = request.POST.get('nom_profil')
nom_profil_old = request.user.username
old_mdp = request.POST.get('old_mdp') # type: object
new_mdp = request.POST.get('new_mdp')
final_mdp = request.POST.get('final_mdp')
mdp = request.user.set_password(new_mdp)
if request.user.check_password(old_mdp) and new_mdp == final_mdp:
User.objects.filter(username=nom_profil_old).update(username=nom_profil_new, password=mdp)
logout(request)
return redirect('authentification')
the new_mdp and final_mdp are the new password and the confirmation of the password
You need to use set_password. You can't do this via update, but you don't need to: you already have the actual object, request.user.
user = request.user
if user.check_password(old_mdp) and new_mdp == final_mdp:
user.username = nom_profil_new
user.set_password(mdp)
user.save()
However, you really should be using a ModelForm for all of this.

How can i capture the secret token to post users tweet - KeyError at / 'oauth_token_secret'

I have built a Django webpage with a text area and I would like a user of the site to be able to tweet the content of the text area.
I have been able to post on my own account (with developer credentials), however I'm having trouble extracting the user's secret token (gained after logging in with python social auth), and without this they cant make a post.
The problem seems to be that the secret token cannot be found in the dictionary that holds this information. Bearing in mind that login via OAuth works correctly; what is it past this point, that I am not doing, or doing incorrectly that means that 'oauth_secret_token' cannot be found/ does not exist?
views.py
def form_handle(request):
form = MyForm()
if request.method=='POST':
form = MyForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
text = cd.get('text')
if 'tweet' in request.POST:
user = request.user
soc = user.social_auth.get(provider='twitter')
access_token = soc.extra_data['access_token']
access_secret = soc.extra_data['oauth_token_secret'] <-- error generated here.
post_tweets().post_my_tweet(text, access_token, access_secret)
form = MyForm()
return render(request, 'hello.html',{'form':form})
else:
form = MyForm()
return render(request, 'hello.html',{'form':form})
twitter_posting.py
from twitter import *
class post_tweets():
ckey= "XXXXXXXXXXXXX"
csecret= "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
def post_my_tweet(self, tweet, atoken, asecret):
t = Twitter(auth=OAuth(atoken, asecret, self.ckey, self.csecret))
t.statuses.update(status= str(tweet))
EDIT:
I have read the Tweepy documentation here: http://docs.tweepy.org/en/v3.2.0/auth_tutorial.html
And Twython documentation here: https://twython.readthedocs.org/en/latest/usage/basic_usage.html#updating-status
I am convinced that both of these libraries would be able to help me, however cant work out how to apply it to my code. Would someone from one of these comunities be able to give me an example of how I can modify this so it tweets from the users account?
The answer is that the oauth token and secret are inside the second dimension of a 2d dictionary. The key to the dictionary is called 'access_token' it holds five KV pairs with keys: 'oauth_token', 'oauth_token_secret', 'x_auth_expires', 'user_id', and 'screen_name'.
This therefore is how you post to twitter from a users account using django:
views.py
def form_handle(request):
form = MyForm()
if request.method=='POST':
form = MyForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
text = cd.get('text')
if 'tweet' in request.POST:
user = request.user
soc = user.social_auth.get(provider='twitter')
access_token = soc.extra_data['access_token'] ['oauth_token'] <-- changed
access_secret = soc.extra_data['access_token']['oauth_token_secret'] <-- changed
post_tweets().post_my_tweet(text, access_token, access_secret)
form = MyForm()
return render(request, 'hello.html',{'form':form})
else:
form = MyForm()
return render(request, 'hello.html',{'form':form})
twitter_posting.py is unchanged from the question above. If you would like to view the twitter data returned upon login you can create a custom pipeline that prints out all the data (this is how I solved the problem). Without turning this into a pipeline tutorial I've added some helpful links below.
http://psa.matiasaguirre.net/docs/pipeline.html
https://github.com/omab/python-social-auth/tree/master/social/pipeline

Using twython-django to authenticate a user when they submit a form

I'm building a Django app and am trying to use twython-django to authenticate a Twitter user when they submit a form. I have tried to edit my views.py, urls.py and models.py files as suggested by this example https://github.com/ryanmcgrath/twython-django/tree/master/twython_django_oauth but I'm simply guessing at it so I'm sure that's why it isn't working.
Could you please help me out with how to get this working? I'm completely new to Twitter wrappers so any help would very much be appreciated.
The flow I'm trying to achieve:
User submits a message through the form
User is asked to authenticate their Twitter account on hitting "Submit" button
User's message, Twitter name, Twitter screen_name, profile_image_url and followers_count are saved in the database (I'm using Heroku Postgres)
User's profile image, name, screen_name and message are printed to index.html in a (Twitter-like) feed.
My views.py:
def logout(request, redirect_url=settings.LOGOUT_REDIRECT_URL):
django_logout(request)
return HttpResponseRedirect(request.build_absolute_uri(redirect_url))
def submit(request):
twitter = Twython(
twitter_token=settings.TWITTER_KEY,
twitter_secret=settings.TWITTER_SECRET,
callback_url=request.build_absolute_uri(reverse('alpha.views.submit'))
)
auth_props = twitter.get_authentication_tokens()
request.session['request_token'] = auth_props
return HttpResponseRedirect(auth_props['auth_url'])
form = MessageForm(request.session.get('message'))
if form.is_valid():
new_message = form.save()
return HttpResponseRedirect('/')
else:
request.session['message'] = request.POST
twitter = Twython(
twitter_token = settings.TWITTER_KEY,
twitter_secret = settings.TWITTER_SECRET,
oauth_token = request.session['request_token']['oauth_token'],
oauth_token_secret = request.session['request_token']['oauth_token_secret'],
)
authorized_tokens = twitter.get_authentication_tokens()
try:
user = User.objects.get(username = authorized_tokens['screen_name'])
except User.DoesNotExist:
user = User.objects.create_user(authorized_tokens['screen_name'], authorized_tokens['oauth_token_secret'])
profile = Message()
profile.user = user
profile.name = name
profile.profile_image_url = profile_image_url
profile.oauth_token = authorized_tokens['oauth_token']
profile.oauth_secret = authorized_tokens['oauth_token_secret']
profile.save()
user = authenticate(
username = authorized_tokens['screen_name'],
password = authorized_tokens['oauth_token_secret']
)
login(request, user)
return HttpResponseRedirect(redirect_url)
Disclaimer: I'm a newbie so the above code is probably a complete mess!
Yes, your use-case is different from that intended by twython-django, but that doesn't mean it's not going to work in your case, and you can use the library as it stands with your flow. After setting up everything as described on the main page, you'll need something like this for your views.py:
from django.shortcuts import redirect, reverse
def submit(request):
# initial form submission, first check if we're authenticated
# if we are, process as normal, otherwise redirect to the login
# page. If you've set up twython-django correctly, it'll redirect
# to twitter for the actual login.
if request.method == "POST":
if request.user.is_authenticated():
form = MessageForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
# Modify this to display validation errors
pass
else:
request.session['message'] = request.POST
# the reverse(submit) resolves this view for redirection
# back from the twitter authentication
return redirect(settings.LOGIN_URL, next=reverse(submit))
# A Get request, where we should first check for the message stored
# We then process the form and remove it from session to prevent
# accidental re-use.
else:
if 'message' in request.session and request.user.is_authenticated():
form = MessageForm(request.session['message'])
del request.session['message']
if form.is_valid():
form.save()
return redirect('/')
else:
# Modify this to display validation errors
pass
else:
# handle the case where this is a get request and the variable
# isn't in session
pass
As for loading their profile image and follower count, those are not currently handled at all by twython django. You can either fork it on github and add them to the TwitterProfile model and add the appropriate code to the thanks view to load those too, or you can add a new model to your code which extends TwitterProfile.
from twython_django_oauth.models import TwitterProfile
from django import models
class ExtendedTwitterProfile(models.Model)
profile = models.OneToOne(TwitterProfile, related_name="extended")
avatar = models.CharField(max_length=255)
followers = models.IntegerField()
And add the code into the submit view to add/update the profile as needed.
extended_profile = ExtendedTwitterProfile.objects.get_or_create(profile=request.user.twitterprofile)
extended_profile.avatar = avatarurl
extended_profile.followers = followercount
extended_profile.save()
You should be able to access those details via
user.twitterprofile.extended.avatar
Although, I have in the past used a url to get the avatar, for example:
# avatar redirection urls
url(r'^avatar/(?P<userid>[0-9A-Za-z_]+)$', redirect_to,
{ 'url' : 'http://api.twitter.com/1/users/profile_image/%(userid)s.json' }, name='avatar' ),
url(r'^avatar/(?P<userid>[0-9A-Za-z_]+)/(?P<size>[a-z]+)$', redirect_to,
{ 'url' : 'http://api.twitter.com/1/users/profile_image?screen_name=%(userid)s&size=%(size)s' } ),
In a template where you want to display the avatar, you simply use and img tag using the url template tag to do the reverse url resolution, like so:
<img src="{% url avatar userid=request.user.username %}" />
As a further pointer, you can also request all of the users' basic details via Twitter's json API
https://twitter.com/users/zandeez.json
For example, will get you my public profile in a form you can use either in python using urllib or even javascript/ajax depending on what you want to do with the follower count.
Hopefully that should get you sorted, if you need any more help fell free to ask.

Save a form using django's authentication framework?

I'd like to be able to save data submitted by the form based on the user that is signed in (instead of having the user to write his/her name through a textbox). I am using django's built-in authentication system. Any thoughts on how I can accomplish this?
#login_required
def add_review(request, product_id):
p = get_object_or_404(Productbackup, pk=product_id)
if request.method == 'POST':
form = ReviewbackupForm(request.POST)
if form.is_valid():
review = form.save(commit=False)
review.product = p
#how to save user as well? review.user = user
review.save()
return HttpResponseRedirect(reverse('reserve.views.view_reviews', kwargs={'product_id':p.id}))
else:
form = ReviewbackupForm()
variables = RequestContext(request, {'form': form, 'product_id': product_id})
return render_to_response('reserve/templates/create_review.html', variables)
You've using save with commit=False so you're almost there. You can get the logged in user from the request object.
if form.is_valid():
review = form.save(commit=False)
review.product = p
review.user = request. user
review.save()
For more details, see the Django docs for user authentication.