how do i use values of if-block outside if-block? [duplicate] - python

This question already has answers here:
Python: Assign Value if None Exists
(9 answers)
Closed 1 year ago.
I want to access couple of variables from if-block, outside in the function
eg: i want to use signin, user
#app.route('/signup', methods=['GET', 'POST'])
def register():
form1 = Signup()
if form1.validate_on_submit():
signin = auth_py.create_user_with_email_and_password(form1.email_address.data, form1.password.data)
user = auth_py.send_email_verification(signin['idToken']) # for email verification
name = form1.name.data
username = form1.username.data
email_address = form1.email_address.data
return redirect(url_for('home_page'))
if form1.errors != {}: # if no errors occur from validators
for err_msg in form1.errors.values():
print(f'there was an error creating the user {err_msg}')
database(username, name, email_address) # problem is here
return render_template('sign-up.html', form1=form1)
I want to use name, username and email_address from form1.validate_on_submit() inside database() and i don't know how can i do that.
NOTE: there is some code yet to be written in main program so I cannot call database() function inside form1.validate_on_submit()

signin = None;
user = None;
def register():
form1 = Signup()
if form1.validate_on_submit():
signin = auth_py.create_user_with_email_and_password(form1.email_address.data, form1.password.data)
user = auth_py.send_email_verification(signin['idToken']) # for email verification
name = form1.name.data
username = form1.username.data
email_address = form1.email_address.data
return redirect(url_for('home_page'))
if form1.errors != {}:`enter code here`
Define variable outside your if-block, this way you can use the
variables outside the if-block.

Related

Name of a dictionary is not defined accessing through console

In my routes.py I set a variable to the converted dictionary generated from SQLAlchemy tuples right after the form validation statement.
When typing from routes import *
dict(Book.query.with_entities(Book.username, Book.choice).all()) in console i get the correct dictionary as wanted {'user1': 'choice1', 'user2': 'choice2'}
If I type the name of the variable dict_of_users assiged to this dictionary I get: NameError: name 'dict_of_users' is not defined
Why it does not recognise that variable since it is in the code?
The logic behind I want to achieve:
If the user select one choice from available in the list, that user and its choice are added as key and value in the dictionary, otherwise the dictionary is empty.
My routes.py:
#app.route("/booking", methods=['POST', 'GET'])
def booking():
session.permanent = True
app.permanent_session_lifetime = timedelta(seconds=5)
form = BookingForm()
if form.validate_on_submit():
book = Book(username=current_user.username, choice=form.book.data)
db.session.add(book)
db.session.commit()
flash('Your choice is registered', 'success')
dict_of_users = dict(Book.query.with_entities(Book.username, Book.choice).all())
return render_template('booking.html', title='Booking', form=form, dict_of_users=dict_of_users)
If it's only inside of the function, you can't access it outside of the function. Since the variable is only defined in the function, you get the NameError message. A fix is to define the variable in the global scope.
EDIT:
As a response to your comment:
if you want to access the dict_of_users variable, declare it outside of the function. Then the variable will contain the value of it's latest use in the global scope, and thus accesible outside of the function.
Something like this should do the trick:
dict_of_users = None
#app.route("/booking", methods=['POST', 'GET'])
def booking():
session.permanent = True
app.permanent_session_lifetime = timedelta(seconds=5)
form = BookingForm()
if form.validate_on_submit():
book = Book(username=current_user.username, choice=form.book.data)
db.session.add(book)
db.session.commit()
flash('Your choice is registered', 'success')
dict_of_users = dict(Book.query.with_entities(Book.username, Book.choice).all())
return render_template('booking.html', title='Booking', form=form, dict_of_users=dict_of_users)

Instanceof - using classes to simulate system access

I am trying to simulate a system access portal using classes and methods. I want to be able to ask the user for their username using input(), check if that input is an object of class User and if so, check if the password is correct for the username. When I use instance of it is returning false. How can I modify this to work?
class User():
def __init__(self, username, password):
self.username = username
self.password = password
def change_pw(self, new_password):
self.password = new_password
jshannon = User("jshannon","AbC!23")
print(jshannon.username)
print(jshannon.password)
jshannon.change_pw("(i*u&y1")
print(jshannon.password)
input_user = input("What is your username? ")
print(isinstance(input_user, User))
User inputs are strings. Always. Period. So you can not "check if that input is an object of class User" - it will never be.
The solution here is to maintain a collection of User instances, and use the input string to search for a matching user.
class UsersCollection(object):
def __init__(self):
# we store users in a dict, with user.usernale as key
self._users = {}
def add(self, user):
if user.username in self._users:
raise ValueError("username '{}' already in used".format(user.username))
self._users[user.username] = user
def get(self, username):
return self._users.get(username)
users = UsersCollection()
users.add(User("jshannon","AbC!23"))
input_user = input("What is your username? ").strip()
userfound = users.get(input_user)
if userfound:
# you can do something with your user
else:
print("sorry, we don't know you")
Note that this is only suitable as a toy project of course.
If you are using Python 3.x (which I'm going to assume), input returns a string so isinstance(input_user, User) will always be False.
You will need to keep track of all User objects created and search for the object with the inputted name.
There are several different ways to do that. I'm going to assume that usernames are unique so I will use them in a shared set:
class User:
users = set()
def __init__(self, username, password):
self.username = username
self.password = password
self.users.add(username)
def change_pw(self, new_password):
self.password = new_password
jshannon = User("jshannon", "AbC!23")
print(jshannon.username)
print(jshannon.password)
jshannon.change_pw("(i*u&y1")
print(jshannon.password)
input_user = input("What is your username? ")
print(input_user in User.users)
# will output True if input_user is jshannon, otherwise False
Note that this is just an example, and it is not bullet-proof nor the best design (one may argue if the users set even belongs to the User class Hint: probably not). If an object's username changes after the initialization the set will not be updated and you may get wrong results. This particular problem can be solved by changing self.username to a property but I suppose that is out of scope of this Q&A.
I am not sure if this is what you want to do but you cant try this
add a list to your class list_of_usernames = []
and then in __init__() append username to the list_of_usernames and at the end
print(input_user in User.list_of_usernames)
so your code will look like this
class User():
list_of_usernames = []
def __init__(self, username, password):
self.username = username
self.password = password
self.list_of_usernames.append(username)
def change_pw(self, new_password):
self.password = new_password
jshannon = User("jshannon","AbC!23")
print(jshannon.username)
print(jshannon.password)
jshannon.change_pw("(i*u&y1")
print(jshannon.password)
input_user = input("What is your username? ")
print(input_user in User.list_of_usernames)

How to create a unique random username for django?

I want visitors of my page to be able to create entries without registering first. When they register later I want everything they have created within that session to belong to their user account.
To achieve that I just want to create blank users with random usernames when entries from non users are made.
What is the most elegant way to create a unique username randomly avoiding any collision?
Should I just make a while loop that generates usernames and tries to save them to the db with a break upon success or is there a better way?
Most scripts I've seen just create a random string, but that has the danger of a collision. Is there any Django function that creates random usernames based on which usernames are already taken?
No, django doesn't have such function. So you have to check for the existence of the generated username in the loop.
I created a mixin that creates a random username based on firstname, lastname and makes sure this username doesnt already exist in db User model:
random_username_mixin.py
import random
import string
from core.models import CustomUser
class RandomUsernameMixin:
"""
using firstname & lastname
create a random username (all lower case)
that doesnt already exist in db
"""
num_of_random_letters = 3
num_of_random_numbers = 2
user_model = CustomUser
def get_username(self, firstname=None, lastname=None):
username = ''
if firstname and lastname \
and firstname != '' and lastname != '':
username = firstname[0] + lastname[0]
while True:
random_letters = string.ascii_lowercase
random_numbers = string.digits
username += self.get_random_char(
random_letters, self.num_of_random_letters
)
username += self.get_random_char(
random_numbers, self.num_of_random_numbers
)
if self.username_exist_in_db(username) is False:
return username
def username_exist_in_db(self, username):
"""
:return: True if username already exist in db
else False
"""
q = self.user_model.objects.filter(username=username)
return q.exists()
def get_random_char(self, ip_str, n):
return (''.join(
random.choice(ip_str)
for i in range(n)
))
Following is the testing code. It tests the above code:
test_random_username_mixin.py
from django.test import TestCase
from miscellaneous.mixins.random_username_mixin import RandomUsernameMixin
class TestRandomUsernameMixin(RandomUsernameMixin,
TestCase):
def test_username_with_fn_ln(self):
fn = 'aseem'
ln = 'hegshetye'
username = self.get_username(
firstname=fn, lastname=ln
)
len_of_initials = 2
len_of_username = self.num_of_random_numbers + \
self.num_of_random_letters + \
len_of_initials
self.assertEqual(len(username), len_of_username)
print(username)
def test_username_without_fn_ln(self):
username = self.get_username()
len_of_initials = 0
len_of_username = self.num_of_random_numbers + \
self.num_of_random_letters + \
len_of_initials
self.assertEqual(len(username), len_of_username)
print(username)

Validating captcha in Flask

I am creating a captcha just for an exercise. The creation of the captcha images seem fine. But every time I try validating the captcha challenge entered by the user, the validation is done against the next captcha. I am stuck at how to go with this.
Function for creating captcha images- captcha.py
import random
import Image
import ImageFont
import ImageDraw
import ImageFilter
import JpegImagePlugin
import PngImagePlugin
def gen_captcha(text, fnt, fnt_sz, file_name, fmt='JPEG'):
fgcolor = random.randint(0,0xff0000)
bgcolor = fgcolor ^ 0xffffff
font = ImageFont.truetype(fnt,fnt_sz)
dim = font.getsize(text)
im = Image.new('RGB', (dim[0]+5,dim[1]+5), bgcolor)
d = ImageDraw.Draw(im)
x, y = im.size
r = random.randint
for num in range(100):
d.rectangle((r(0,x),r(0,y),r(0,x),r(0,y)),fill=r(0,0xffff00))
d.text((3,3), text, font=font, fill=fgcolor)
im = im.filter(ImageFilter.EDGE_ENHANCE_MORE)
im.save(file_name)
signup function from views.py
#app.route('/signup', methods = ['GET', 'POST'])
def signup():
if g.user is not None and g.user.is_authenticated():
return redirect(url_for('index'))
words = open('app/corncob_caps.txt').readlines()
captcha_word = words[random.randint(1,len(words))]
captcha_filename = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(10)) + '.jpg'
captcha.gen_captcha(captcha_word.strip(), 'app/os.ttf', 25, 'app/static/' + captcha_filename + '')
form = SignUpForm(captcha_word)
if form.validate_on_submit() == False:
return render_template('signup.html', form = form, filename = captcha_filename)
else:
user = User(form.email.data, form.password.data)
db.session.add(user)
db.session.commit()
flash('You have successfully signed up.')
flash('You may login now.')
return redirect(url_for('login'))
return render_template('signup.html', form = form, filename = captcha_filename)
I am passing the captcha_word to my form class. The form class is:
class SignUpForm(Form):
email = EmailField('Email Address', validators = [email()])
password = PasswordField('Password', validators = [Required('Please enter a valid password between 8 and 30 characters.'), Length(min = 8, max = 30)])
captcha = TextField('Captcha', validators = [Required('You must enter the challenge captcha.')])
submit = SubmitField('Create Account')
captcha_word = ''
def __init__(self, word, *args, **kwargs):
Form.__init__(self, *args, **kwargs)
self.get_word(word)
def get_word(self, word):
self.captcha_word = word
def validate(self):
if not Form.validate(self):
return False
elif self.captcha_word != self.captcha.data.upper():
print self.captcha_word
print self.captcha.data.upper()
self.captcha.errors.append("Wrong captcha!")
return False
user = self.get_user()
if user:
self.email.errors.append("That email is already taken.")
return False
else:
return True
def get_user(self):
return User.query.filter_by(email = self.email.data.lower()).first()
I inserted the two print statements inside to see why the comparison was coming wrong. The first print showed the next captcha whereas the print self.captcha.data.upper() displayed the user entered data.
I am not sure, but it seems the signup route is being called twice. But I don't know how to fix this. Any ideas?
If you need to use a captcha, you can use the feature that's already built into Flask-WTF and save yourself reinventing the wheel.
If you do want to reinvent the wheel, then the main problem you're having is that you're recreating the captcha when the user submits the form, you have no way to remember and refer to the old value.
So this is how it's working at the moment:
User goes to sign in, you generate a captcha, then because they haven't submitted a form, it shows the sign in form including the captcha picture.
User fills in the form and hits the submit button- this loads the signup view again,creates a new random captcha, then goes down the form submitted
logic path, so when you compare the user captcha data to the current captcha data, it doesn't match.
So you're missing persistence, the captcha you generate the first time round doesn't get held anywhere, so when the user submits you've got no way to refer back to it. So you need to store that captcha word somewhere. You could simply just store that captcha word in the user's session and use that to validate against when you need to, or perhaps sign it with itsdangerous and store it in the form itself as a hidden field?
Code Example:
This just takes your code and adjusts it a little to store the value in the session-- not tested, and can definitely been improved, but should work:
#app.route('/signup', methods = ['GET', 'POST'])
def signup():
if g.user is not None and g.user.is_authenticated():
return redirect(url_for('index'))
if request.method == 'post':
captcha_word = session["captcha"]
else:
words = open('app/corncob_caps.txt').readlines()
captcha_word = words[random.randint(1,len(words))]
session["captcha"] = captcha_word
captcha_filename = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(10)) + '.jpg'
captcha.gen_captcha(captcha_word.strip(), 'app/os.ttf', 25, 'app/static/' + captcha_filename + '')
form = SignUpForm(captcha_word)
if form.validate_on_submit() == False:
return render_template('signup.html', form = form, filename = captcha_filename)
else:
user = User(form.email.data, form.password.data)
db.session.add(user)
db.session.commit()
flash('You have successfully signed up.')
flash('You may login now.')
return redirect(url_for('login'))
return render_template('signup.html', form = form, filename = captcha_filename)

Using selfmade functions in Google App Engine

I'm trying to make a function that checks if the user is logged in. I've placed the function outside of the mainpage class and it gives no errors until I try to use it insie the def get(self) within the MainPage class. The function looks like this:
def LoginCheck():
username = self.request.cookies.get('username')
password = self.request.cookies.get('password')
if username and password:
checkq = db.GqlQuery("SELECT * FROM Users WHERE username = :1 AND password = :2", username, password)
checkresult = checkq.get()
if checkresult is None:
self.redirect("/wrong")
else:
self.redirect("/wrong2")
and When I try to use it it returns:
line 14, in LoginCheck
username = self.request.cookies.get('username')
NameError: global name 'self' is not defined
What am I doing wrong?
You'll have to add "self" to your function definition. See section 9.3.2 of python's tutorial.
def LoginCheck(self):
username = self.request.cookies.get('username')
password = self.request.cookies.get('password')
if username and password:
checkq = db.GqlQuery("SELECT * FROM Users WHERE username = :1 AND password = :2", username, password)
checkresult = checkq.get()
if checkresult is None:
self.redirect("/wrong")
else:
self.redirect("/wrong2")

Categories