Im trying to register users hashing their passwords before add to database as follows
settings.py
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.MD5PasswordHasher',
)
Models.py
from django.contrib.auth.models import AbstractBaseUser
class Users(AbstractBaseUser):
name = models.CharField(max_length=200)
email = models.CharField(max_length=200)
password = models.CharField(max_length=255)
Views.py
name = form.cleaned_data.get('name')
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password')
date_joined = date.today()
if Users.objects.filter(email=email).exists() and Users.objects.filter(name=name).exists() :
messages.info(request, 'User already exists')
else:
Users.objects.create(name=name, email=email, password=set_password(password), date_joined=date_joined)
but when i actually trying to create the user i get Python : name 'set_password' is not defined
What is wrong? do i need to import something at Views.py?
You must use set_password() on a user instance, not when creating a user.
Try this:
user = Users.objects.create(first_name=name, email=email, date_joined=date_joined)
user.set_password(password)
user.save()
I can see you are extending the user model. I'd have a look at some articles for ways to do this, I recommend this article.
Related
I've created a custom user abstract model and profile model to collect additional information once the user registers.
I am collecting "User type: Employer/employee" at the time of registration but this doesn't seem to be recognized in the profile view. Despite the user being correctly added into the DB (I checked via Admin).
For example, I created user: asus23910 (employer user type). But when I login and redirect to http://127.0.0.1:8000/employer_profile/asus23910/, I get following error:
'User' object has no attribute 'user_type'C:\Users\ASUS\PycharmProjects\Content\content\content\views.py, line 112, in employer_profile_view
1. Here's my employer_profile_view.py code:
def employer_profile_view(request, username):
user = User.objects.get(username=username)
if user.user_type != User.EMPLOYER:
# Redirect to the correct profile page if the user type is not employer
return redirect('employee_profile', username=request.user.username)
if request.method == 'POST':
form = EmployerProfileForm(request.POST, instance=user.employerprofile)
if form.is_valid():
employer_profile = form.save(commit=False)
employer_profile.user = user
employer_profile.save()
return redirect('employer_profile', username=request.user.username)
else:
form = EmployerProfileForm(instance=user.employerprofile)
context = {
'form': form,
'username': username,
}
return render(request, 'employer_profile.html', context)
2. Employer Profile model and connector
class EmployerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
user_type = models.CharField(
max_length=10,
choices=User.USER_TYPE_CHOICES,
default=User.EMPLOYER
)
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
title = models.CharField(max_length=255)
company_name = models.CharField(max_length=255)
company_logo = models.ImageField(upload_to='company_logos/')
company_location = models.CharField(max_length=255)
company_website = models.URLField()
company_twitter = models.URLField()
#one-2-one connector
#receiver(post_save, sender=User)
def create_employer_profile(sender, instance, created, **kwargs):
if created:
EmployerProfile.objects.create(user=instance, user_type=instance.user_type)
print('Employer Profile created')
#receiver(post_save, sender=User)
def save_employer_profile(sender, instance, **kwargs):
instance.employerprofile.user_type = instance.user_type
instance.employerprofile.save()
print('Employer Profile saved')
3. User model
#model one to store the user into db
class User(AbstractUser):
EMPLOYER = "employer"
EMPLOYEE = "employee"
USER_TYPE_CHOICES = [
(EMPLOYER, "Employer"),
(EMPLOYEE, "Employee"),
]
user_type = models.CharField(
max_length=10,
choices=USER_TYPE_CHOICES,
default=EMPLOYEE
)
email = models.EmailField(default='example#example.com')
username = models.CharField(max_length=150, default='example_user')
password = models.CharField(max_length=128, default='!')
groups = models.ManyToManyField(
Group,
blank=True,
related_name='content_groups'
)
user_permissions = models.ManyToManyField(
Permission,
blank=True,
related_name='content_user_permissions'
)
`
**
What I've tried:**
Flushing and starting new DB (as I used in-built Django user model before and some old users weren't fairing well with the new user-type field).
Adding the user type with default employer option to employer view and fetching the usertype from user model.
**
What I expect:**
The profile view to connect with the custom user model and allow the user to add additional information to their user profile. And ofcourse the profile page to have the user-type attribute as initially stored from user class.
You probably import User not from your models file, but from django.
Anyway I highly recommend (if you overwrote AUTH_USER_MODEL) using built-in get_user_model() method from Django e.g.:
from django.contrib.auth import get_user_model
def employer_profile_view(request, username):
user = get_user_model().objects.get(username=username)
if user.user_type != User.EMPLOYER:
...
And don't use User name for model, I prefer to use CustomUser by myself but you can name it differently, just to avoid mistakes.
I have the sign up form in django through which I am taking the entry for the new user. The data can be saved using the u_form.save method but I also need the plain password that the user has entered as that password will be needed to create account in other website through the REST API and hence both password needs to be same. I am able to access the password from the form but when I receive it Django has already encrypted it. How can I get the original plain password?
This is what I have tried :
views.py
from users.forms import SignUpForm, ProfileForm
def create(request):
context = {}
if(request.method == 'POST'):
u_form = SignUpForm(request.POST) # fill it with user details
p_form = ProfileForm(request.POST, request.FILES)
if u_form.is_valid() and p_form.is_valid():
user = u_form.save()
email = user.email
username = user.username
first_name = user.first_name
# Accessing plain password
password = user.password
Profile.objects.filter(user=user).delete()
profile = p_form.save(commit=False)
profile.user = user
profile.save()
messages.success(request, f'Account Created')
# LOGIC TO CREATE MANTIS ACCOUNT THROUGH THE REST API WITH SAME USERNAME AND PASSWORD AS OF MY DJANGO WEBSITE
return render(request, 'mainapp/homepage.html', context)
forms.py
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
from .models import Profile
class SignUpForm(UserCreationForm):
email = forms.EmailField(required=True,
label='Email',
error_messages={'exists': 'Oops'},
widget=forms.TextInput(attrs={'readonly':'readonly'}))
username = forms.Field(widget=forms.TextInput(attrs={'readonly':'readonly'}))
first_name = forms.Field(widget=forms.TextInput(attrs={'readonly':'readonly'}))
readonly_fields = ('username', 'first_name', 'email')
class Meta:
model = User
fields = ("username", "first_name", "email", "password1", "password2")
class ProfileForm(forms.ModelForm):
emp_type = forms.Field(widget=forms.TextInput(attrs={'readonly':'readonly'}))
pay_type = forms.Field(widget=forms.TextInput(attrs={'readonly':'readonly'}))
class Meta:
model = Profile
fields = ['pay_type', 'emp_type', 'contact', 'whatsapp', 'gender', 'avatar']
In the views.py password = user.password here I am trying to get the password but it gives me the encrypted one and not the plain password. Is there any way to achieve this?
Note : I know about the security threat in order to achieve this. I just want to know how can I achieve this?
Building on Daniel Roseman reply, Yes we can access the plain password field using the .cleaned_data attribute. Here is how you would do it.
password = u_form.cleaned_data['password']
I'm trying to log users in with django authenticate. It returns nothing even when the email and password are correct. It just reloads the page and doesn't do anything. I have checked and the email and password I used are stored in the database, so the account exist but login doesn't do anything. I am using django 2.
Views.py
def signup(request):
if request.method == "POST":
firstname = request.POST.get('firstname')
lastname = request.POST.get('lastname')
email = request.POST.get('email')
password = request.POST.get('password')
passwordagain = request.POST.get('passwordagain')
areacode = request.POST.get('areacode')
number = request.POST.get('number')
userdetails = CustomUser(firstname=firstname,lastname=lastname,email=email,password=password, areacode=areacode, number=number)
userdetails.save()
return render(request, 'main/accountconfirmationpage.html')
else:
return render(request,'main/signup.html')
def login(request):
email=request.POST.get('email')
password=request.POST.get('password')
user = authenticate(request, email=email, password=password)
if user is not None:
if user.is_active:
login(request, user)
return render(request,'main/dashboard.html')
else:
return render(request, 'main/login.html')
from django.db import models
Models.py
# Create your models here.
class CustomUser(models.Model):
firstname = models.CharField(max_length=30)
lastname = models.CharField(max_length=30)
email = models.EmailField(max_length=30)
password = models.CharField(max_length=100)
areacode = models.CharField(max_length=4)
number = models.CharField(max_length=30)
I think the problem is with your signup. You are not storing password properly in signup view.
userdetails = CustomUser(firstname=firstname,lastname=lastname,email=email,password=password, areacode=areacode, number=number) # <-- Here
userdetails.save()
As you are not storing the password properly(currently it is being stored as plaintext rather than hashed), that is why authenticate function is not able to get the user.
So, you need to set password like this:
userdetails = CustomUser(firstname=firstname,lastname=lastname,email=email, areacode=areacode, number=number)
userdetails.set_password(password)
userdetails.save()
For more details, please check here on set_password function.
You need to extend the Django User Model like this:
Models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
#this will extend User model with your own model
class CustomUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# all the other fields you mentioned except areacode and number
# are already in User model so don't need to add them here
areacode = models.CharField(max_length=4)
number = models.CharField(max_length=30)
# Below code will hook the create_custom_user and save_custom_user methods
# to the User model, whenever a save event occurs
#receiver(post_save, sender=User)
def create_custom_user(sender, instance, created, **kwargs):
if created:
CustomeUser.objects.create(user=instance)
#receiver(post_save, sender=User):
def save_custom_user(sender, instance, **kwargs):
instance.customeuser.save()
Now you can create the user with your CustomModel in views like this:
Views.py
from django.contrib.auth.models import User
def signup(request):
if request.method == "POST":
# I would suggest to use django forms
# instead of getting the values directly from request.POST
user = User(firstname=firstname, lastname=lastname, email=email)
user.customuser.areacode = areacode
user.customuser.number = number
user.set_password(password)
user.save()
# rest of the code
doc for forms in django
Also for login the user with email instead of username you need to write an authentication backend for that and register it in your settings.py take a look here
I have created an Update Profile page. So the fields are: Email, First Name, Last Name.
In the validation, I'm trying to exclude logged user's email address, and also I'm filtering other user's email addresses. I think if you see the code you will understand what I'm talking about.
I read several questions here but couldn't find something. Some users had the same issue.
So with the code below, the issue I'm getting is:
type object 'User' has no attribute 'email'.
I tried many ways to get the current user's email address(before I save the form) but still nothing.
forms.py
class UpdateProfile(forms.ModelForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
class Meta:
model = User
fields = ('email', 'first_name', 'last_name')
def clean_email(self):
email = self.cleaned_data.get('email')
current_user_email = User.email
if User.objects.filter(email__iexact=email).exclude(email__iexact=current_user_email).count() > 0:
raise forms.ValidationError('This email address is already in use.'
'Please supply a different email address.')
return email
def save(self, commit=True):
user = super(UpdateProfile, self).save(commit=False)
if commit:
user.save()
return user
I suppose that in line current_user_email = User.email "User" isn't really a actual user instance, it is a model class which you imported for setting model = User in Meta.
If you want to use this form only for editing user data You should do something like this:
urls.py
urlpatterns = patterns('project.apps.app_name.views',
url(r'^edit-user/(?P<pk>\d+)/?$','edit_user',name='edit_user'),
)
app_name/views.py:
def edit_user(request,pk):
user_instance = User.objects.get(pk=pk)
form = UpdateProfile(request.POST, instance=user_instance)
.... more code ....
And in forms.py you should change line from:
current_user_email = User.email
to:
current_user_email = self.instance.email
But the proper way to do that (if you use django >1.6) would be to create custom User model, and set email field attribute unique=True.
Quick (probably foolish) question. This is the flow of my site: User logs in and is redirected to a custom admin page. On this admin page they have the ability to make a 'Profile'. I want to associate the Profile they create with their User data such that 1 User associates to 1 Profile.
For some reason the following isn't working (simply trying to associate
UserAdmin.Models
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
username = models.ForeignKey(User)
firstname = models.CharField(max_length=200)
lastname = models.CharField(max_length=200)
email = models.EmailField(max_length=200)
def __unicode__(self):
return self.username
UserAdmin.Views
def createprofile(request):
user = User.objects.get(id=1)
profile = Profile(username=user, firstname='Joe', lastname='Soe', email='Joe#Soe.com')
profile.save()
I keep getting: table useradmin_profile has no column named username_id
Any ideas? Appreciated.
EDIT:
Deleted my db and ran a fresh syncdb, changed to username = models.OneToOneField(User). Now I cam getting Cannot assign "u'superuser'": "Profile.username" must be a "User" instance.
UserAdmin.Models
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User)
def __unicode__(self):
return self.user.get_full_name()
UserAdmin.Views
def createprofile(request):
user_ = User.objects.get(pk=1)
profile = Profile(user=user_)
profile.user.first_name = 'Joe'
profile.user.last_name = 'Soe'
profile.user.email = 'Joe#Soe.com'
profile.user.save()
profile.save()
You syncdb'ed the Profile model before you had a username ForeignKey field. Django will only create tables but will not alter them once they have been created. Here an answer listing your options:
https://stackoverflow.com/a/7693297/990224.
And you should think about renaming username to user.