I am trying to write login app using flask.
My View.py look like
#lm.user_loader
def load_user(id):
if id is None or id == 'None':
id =-1
print 'ID: %s, leaving load_user' % (id)
return Users.query.get(int(id))
and another login method is
#app.route('/login',methods=['GET','POST'])
def login():
form = LoginForm()
if request.method == 'GET':
return render_template('login.html',
title = 'Sign In',\
form = form)
username = form.username
password = form.password
user = Users(nickname = form.username, email = 'sanjeev_yadav248#yahoo.com', role =
ROLE_USER)
if user is None:
flash('Username or Password is invalid' , 'error')
return redirect(url_for('login'))
remember_me = False
if 'remember_me' in session:
remember_me = session['remember_me']
session.pop('remember_me', None)
login_user(user)
flash("Logged in successfully.")
return redirect(request.args.get("next") or url_for("index"))
My model(model.py) class is
class Users(db.Model):
id = db.Column(db.Integer, primary_key = True)
nickname = db.Column(db.String(64), unique = True)
email = db.Column(db.String(120), index = True, unique = True)
role = db.Column(db.SmallInteger, default = ROLE_USER)
posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return unicode(self.id)
def __repr__(self):
return '<User %r>' % (self.nickname)
My databsase users table is having id,nickname,emailid and role.
This nick name is having sanjeev as a value and associated id with it for example 3. But when I run it, load_user() method id is not populated. i.e it is 'None'. When I hardcode id in load_user method its work fine. for example if I put return Users.query.get(3). Let me know if you guys have any clue in this regard.
Related
I am trying to generate a token for users requesting for forget password. I have a model to handle and store this.
models.py
class ForgetPassword(models.Model):
user = models.ForeignKey(CustomUser, on_delete= models.CASCADE)
forget_password_token = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add= True)
def __str__(self):
return self.user.email
The view functions that handles the request are below
views.py
def forget_password(request):
try:
if request.method == 'POST':
user_email = request.POST.get('email')
if CustomUser.objects.filter(email = user_email).exists():
user_obj = CustomUser.objects.get(email = user_email)
name = user_obj.full_name
plan = user_obj.plan
print("\n this is the user : ", user_obj, " this is its name : ", name,"\n")
token = str(uuid.uuid4())
fp = ForgetPassword.objects.get(user = user_obj)
fp.forget_password_token = token
fp.save()
forget_password_mail.delay(user_email, name, token)
messages.info(request, 'An email has been sent to your registered email.')
return redirect('forget-password')
else:
messages.info(request, 'User does not exist')
return redirect('forget-password')
except Exception as e:
print("\nthe exception is comming from forget_password : ", e, "\n")
return render(request, 'fp_email_form.html')
So, here I am trying to get the user first in user_obj from my CustomUser model and then I am trying to get the same user in the ForgetPassword model and store the token against that user. But I am getting the below exception
ForgetPassword matching query does not exist.
Please suggest or correcct me where I am wrong.
You do not have a ForgetPassword object associated with the user object you are trying to fetch at,
fp = ForgetPassword.objects.get(user = user_obj)
Instead, you should use get_or_create.
reference link
I have a flask app that connects to a MySQL DB and retrieves the data but it cannot insert anything into it. I am using flask-SQLAlchemy and the form is generated using flaskwtforms. Below is the model
class Name(db.Model):
__tablename__ = 'names'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(45), nullable=False)
password = db.Column(db.String(45), nullable=False)
def __init__(self, id, name, password):
self.id = id
self.name = name
self.password = password
def __rep__(self):
return '<User %r>' % self.username
Below is the form itself
class AddUser(FlaskForm):
name = StringField(label= 'username', validators = [InputRequired('Username is required')])
password = StringField(label = 'password', validators = [InputRequired('Password is required')])
Below is the view function
#app.route('/add_user', methods=['GET','POST'])
def add_user():
form = AddUser()
if request.method == 'POST' and form.validate_on_submit():
name = form.name.data
password = form.password.data
name = Name(name,password)
db.session.add(name)
db.session.commit()
return render_template('add-user.html')
else:
return render_template('add-user.html', form=form)
I found the solution to my problem. So in my database, the id is set as the primary key and is auto-generated hence it does not need to be passed in the constructor since my query would also require me to pass an id.
I this in my forms.py
from django.contrib.auth.models import User
from .models import DirectReferral, IndirectReferral
class RegistrationForm(forms.Form):
username = forms.RegexField()
referrer = forms.CharField()
def clean_username(self):
try:
user = User.objects.get(username__iexact=self.cleaned_data['username'])
except User.DoesNotExist:
return self.cleaned_data['username']
raise forms.ValidationError(_("The username already exists."))
How do I check if the referrer instance exist in User Database?
I did the code below but it has an error of TypeError at /register/
def clean_referrer(self):
try:
user = User.objects.get(username__iexact=self.cleaned_data['referrer'])
except User.DoesNotExist:
raise forms.ValidationError(_("User does not exist."))
return self.cleaned_data['referrer']
I did also try to do this but I get an error of string indices must be integers.
def clean(self):
if 'referrer' in self.cleaned_data:
if User.objects.filter(username=self.cleaned_data['referrer']).exists():
return self.cleaned_data['referrer']
else:
raise forms.ValidationError(_("Referrer doesn't exist!"))
Here is my models.py
from django.contrib.auth.models import User
class DirectReferral(models.Model):
name = models.OneToOneField(User, primary_key=True)
referrer = models.ForeignKey(User, related_name="direct_referrals")
def __str__(self):
return self.name.username
class IndirectReferral(models.Model):
name = models.OneToOneField(User, primary_key=True)
referrer = models.ForeignKey(User, related_name="indirect_referrals")
def __str__(self):
return self.name.username
How do I get the referrer instance data?
Here is my views.py (Updated)
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username']
)
ref_user = User.objects.get(
username=form.cleaned_data['referrer'])
direct = DirectReferral.objects.create(
name = user,
referrer = ref_user
)
if DirectReferral.objects.filter(referrer=user).exists():
indirect = IndirectReferral.objects.create(
name = user,
referrer = ref_user
)
return HttpResponseRedirect('/register/success/')
This is what you need:
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
)
# Assuming form.cleaned_data['referrer'] has usernames.
# If it has pks then just use pk=form.cleaned_data['referrer']
# You should wrap this in a try-except
dr_user = User.objects.get(username=form.cleaned_data['referrer'])
direct_referral = DirectReferral.objects.create(
user=user,
referrer=dr_user,
)
# Wrap this in try-except as well.
ir_user = dr_user.direct_referral.referrer
indirect_referral = IndirectReferral.objects.create(
user=user,
referrer=ir_user,
)
return HttpResponseRedirect('/register/success/')
Also, this looks like a job for post_save signals. Check them out here: https://docs.djangoproject.com/es/1.9/ref/signals/#post-save
I think the problem is here
DirectReferral.name = username,
DirectReferral.referrer = referrer,
IndirectReferral.name = username,
IndirectReferral.referrer = referrer,
you have to create objects first and than assign the values like this:
direct_referal = DirectReferral()
direct_referal.name=....
....
direct_referal.save()
also from your code, it seems that you are assigning string to user object:
DirectReferral.name = username
here username is string and DirectReferral.name is User object. You have to get this user object first and than assign to referral's name.
direct_referal = DirectReferral()
direct_referal.name=User.objects.get(username=username)
....
direct_referal.save()
I create an userprofile as following:
class UserProfile(models.Model):
# This field is required:
user = models.OneToOneField(User, related_name="User can view study permission")
# Other fields:
phone = models.CharField(max_length=20)
disease = models.ManyToManyField(Disease)
date_assigned = models.DateTimeField("Date Assigned")
query = models.ManyToManyField(Query, blank=True)
def __unicode__(self):
studies = ', '.join(study.name for study in self.disease.all())
return "%s can view %s" % (self.user, studies)
It's extended information for users.
Now I am creating a admin page by myself to allow the admin to update the users account information which included the above user profile.
The form and code for this is as following:
def edit(request, user_id):
"""Edit a user's details"""
try:
user = User.objects.get(id=user_id)
except User.DoesNotExist:
user = None
# user exists:
if user:
# Initial form field data:
initial={'user_id': user_id,
'username': user.username,
'fname': user.first_name,
'lname': user.last_name,
'email': user.email,
'phone': user.get_profile().phone,
'groups': user.groups.all(),
'studies': user.get_profile().disease.all(),
'is_admin': user.is_staff,
'is_active': user.is_active
}
request.breadcrumbs(
(_("Home"), reverse('home')),
(_("All Users"), reverse('all users')),
(_("User Details"), reverse('user details', args=[user_id])),
)
if request.method == "GET":
form = UserProfileEditForm(initial=initial,extra=request.user.id)
response = {'heading': 'Edit', 'form': form}
return render_to_response('accounts/edit.html',
response,
context_instance=RequestContext(request)
)
elif request.method == "POST":
form = UserProfileEditForm(request.POST,extra=request.user.id)
if form.is_valid():
Log().add(request, "Edit", "W", "userprofile", user_id)
if form.cleaned_data['password1'] and form.cleaned_data['password2']:
user.set_password(form.cleaned_data['password1'])
user.username = form.cleaned_data['username']
user.first_name = form.cleaned_data['fname']
user.last_name = form.cleaned_data['lname']
user.email = form.cleaned_data['email']
user.groups = form.cleaned_data['groups']
user.is_staff = form.cleaned_data['is_admin']
user.is_active = form.cleaned_data['is_active']
user.save()
# Oddly to make the extra fields found in UserProfile are saved, you
# have to call get_profile().ATTRIBUTE, assign a value, then call
# get_profile().save(). Calling user.save() as the last step won't
# save any changes made to UserProfile:
disease_pks = form.cleaned_data['studies']
user.get_profile().disease = Disease.objects.filter(pk__in=disease_pks)
user.get_profile().phone = form.cleaned_data['phone']
user.get_profile().save()
return HttpResponseRedirect("/accounts/view/%s" % user_id)
else:
# form is not valid:
return render_to_response("accounts/edit.html",
{'form': form, 'heading': 'Edit'},
context_instance=RequestContext(request)
)
# user does not exist:
else:
error = "User #%s cannot be found. Press the 'BACK' button on your browser." % user_id
return HttpResponseRedirect(reverse('DigitalRecords.views.error', args=(error,)))
class UserProfileEditForm(forms.Form):
user_id = forms.IntegerField(widget=forms.HiddenInput())
username = forms.CharField(label=_("Username"))
password1 = forms.CharField(label=_("Password"),
widget=forms.PasswordInput(),
required=False
)
password2 = forms.CharField(label=_("Password (again)"),
widget=forms.PasswordInput(),
required=False
)
fname = forms.CharField(label=_("First name"))
lname = forms.CharField(label=_("Last name"))
email = forms.EmailField()
phone = forms.CharField(label=_("Phone"))
is_admin = forms.BooleanField(label=_("Is an administrator?"), required=False)
is_active = forms.BooleanField(label=_("Is an active user?"), required=False)
groups = forms.ModelMultipleChoiceField(queryset=Group.objects.all(),
widget=forms.CheckboxSelectMultiple()
)
#Attach a form helper to this class
helper = FormHelper()
helper.form_id = "edituserprofile"
helper.form_class = "userprofile"
#Add in a submit and reset button
submit = Submit("Save", "Save Changes")
helper.add_input(submit)
reset = Reset("Reset", "Reset")
helper.add_input(reset)
def __init__(self, *args,**kwargs):
extra = kwargs.pop('extra')
super(UserProfileEditForm, self).__init__(*args, **kwargs)
self.fields["studies"] = forms.ModelMultipleChoiceField(queryset=User.objects.get(id=extra).get_profile().disease.all(),
widget=forms.CheckboxSelectMultiple()
)
def clean_username(self):
"""Check if the username does not already exist"""
username = self.cleaned_data['username']
user_id = self.cleaned_data['user_id']
# handle:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
return self.cleaned_data['username']
else:
if user.id == user_id:
return self.cleaned_data['username']
else:
raise forms.ValidationError('User "%s" already exists' % username)
def clean_fname(self):
fname = self.cleaned_data['fname']
# Remove any diacritics/accented characters:
fname = strip_diacritic(fname).strip()
# Match names that may have hyphens, apostrophes, or periods in them.
# example: John Doe, O'Brien, Leroy-Brown, Cpt. James T. Kirk
pattern = '^([a-zA-Z]+(?:\.)?(?:[\-\' ][a-zA-Z]+(?:\.)?)*)$'
# match the regex to the input string.
results = re.match(pattern, str(fname))
if results == None:
raise ValidationError(u'%s is not a valid name' % fname)
return fname
def clean_lname(self):
"""
Determine if the patient's name is valid. It removed any accented/diacritic
characters and replaces them with the base character for simplicity. Names with
hyphens and/ore apostrophes like Hanna-Barbara and O'Brien are allowed. If the
check fails a validation error is raised.
"""
lname = self.cleaned_data['lname']
# Remove any diacritics/accented characters:
lname = strip_diacritic(lname).strip()
# Match names that may have hyphens, apostrophes, or periods in them.
# example: John Doe, O'Brien, Leroy-Brown, Cpt. James T. Kirk
pattern = '^([a-zA-Z]+(?:\.)?(?:[\-\' ][a-zA-Z]+(?:\.)?)*)$'
# match the regex to the input string.
results = re.match(pattern, str(lname))
if results == None:
raise ValidationError(u'%s is not a valid name' % lname)
return lname
def clean(self):
"""Check if password1 and password2 match"""
cleaned_data = self.cleaned_data
password1 = cleaned_data.get('password1')
password2 = cleaned_data.get('password2')
# Notice it's an 'or' condition because a password change is optional:
if password1 or password2:
if password1 != password2:
msg = "Passwords do not match"
self._errors['password1'] = self.error_class([msg])
self._errors['password2'] = self.error_class([msg])
del cleaned_data['password1']
del cleaned_data['password2']
return cleaned_data
return self.cleaned_data
It works fine if an administrator trying to edit other user's account information.
However, when an administrator tried to update his own account. The disease field will always be blank whatever this field was changed or not.
Does anyone the reason and how should I change my code?
Thank you very much.
I'm not sure about other code, but these lines in your view does not seem appropriate.
user.get_profile().disease = Disease.objects.filter(pk__in=disease_pks)
user.get_profile().phone = form.cleaned_data['phone']
user.get_profile().save()
You are getting new profile object each time by calling user.get_profile() and updating it. Not saving it, instead a new object. So change it to
profile = user.get_profile()
profile.disease = Disease.objects.filter(pk__in=disease_pks)
profile.phone = form.cleaned_data['phone']
profile.save()
I've been trying to figure this out for hours, and believe me, I really looked everywhere on Stack Overflow.
In my UserProfile, I have a ForeignKey reference to another model (called "Company"), and upon registration, I create a new Company and point my UserProfile ForeignKey to that Company.
models.py is as follows:
class UserProfile(models.Model):
company = models.ForeignKey(Company)
title = models.CharField(max_length = 50, default = '')
user = models.OneToOneField(User, default = 0, null = True)
class Company(models.Model):
"""A company profile."""
name = models.CharField(max_length = 50)
I use a Form to do the signing up. Here's the form:
class SignupForm(ModelForm):
name = forms.CharField(label = "Name")
company = forms.CharField(max_length = 50)
email = forms.EmailField(label = "Email")
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ("name", "company", "email", "password")
def save(self, commit=True):
user = super(SignupForm, self).save(commit=False)
name = self.cleaned_data["name"].split()
if len(name) == 1:
# User did not enter a last name.
user.first_name = name
else:
user.first_name, user.last_name = name
user.email = self.cleaned_data["email"]
user.set_password(self.cleaned_data["password"])
user.username = user.email
if commit:
user.save()
return user
and here's the signup view:
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
# Check if email has already been used for an account.
email = request.POST['email']
existing_account = User.objects.filter(email = email)
if existing_account:
form = SignupForm()
return render_to_response('registration/signup.html',
{ 'form': form,
'error': 'duplicate_email',
})
# Otherwise, save the form and create a new user.
new_user = form.save()
company = Company(name=request.POST['company'])
company.save()
user_profile = new_user.get_profile()
user_profile.company = company
user_profile.save()
new_user = authenticate(
username = email,
password = request.POST['password']
)
# Log the user in automatically.
login(request, new_user)
# Redirect user to Thank You page.
return HttpResponseRedirect('/thanks')
else:
form = SignupForm()
return render_to_response('registration/signup.html', {
'form': form,
})
The error I am getting is telling me that company_id cannot be null. I clearly add a new Company. Please let me know what you think might be wrong.
Thanks
I've had this exact error today, with no reason, except that it was caused by SQLite. With SQLite, the id field of one table went from INTEGER PRIMARY KEY to INTEGER. If you're using SQLite, try deleting the offending table and recreate it with a syncdb.
What is the value of
user_profile = new_user.get_profile()
?
Not sure if this feels too hackish for your tastes but perhaps you could create/save the Company object and pass it in to your SignupForm.save() method as a positional/keyword argument.
The issue you'd get there is that you'd be expecting a CharField and you'd be passing in a company object. So you'd probably want to give company.pk to the company field in your form.