Extended user model not save password correctly - django

im trying to create a child and parent objects at the same time with same form.
After migrations, i have two tables, user as always and doctor, whith the relationship with user in a extra column called user_ptr_id.
models.py:
class Doctor(User):
collegiated = models.CharField(verbose_name="Nº Colegiado", max_length=20, null=True, blank=True)
phone = models.CharField(verbose_name="Teléfono", max_length=12, null=True, blank=True)
class Patient(User):
age = models.PositiveIntegerField(verbose_name="Edad", blank=True)
forms.py:
class DoctorForm(forms.ModelForm):
class Meta:
model = app_models.Doctor
fields = ['username', 'email', 'password']
view.py:
if request.method == 'POST:
form = DoctorForm(request.POST.copy())
if form.is_valid():
forms.save()
else:
form = DoctorForm()
return ...
The two objects are created, doctor and user, well related with user_ptr_id but the user password appears unencrypted.
¿ How can i integrate UserCreationForm on child models ?
¿ How can i solve this issue ?
Anybody could help me please?
Thanks in advance.

use this in your views.py like this
also import make password
from django.contrib.auth.hashers import make_password
def user_signup(request):
if request.method == "POST":
user_form = userSignup(request.POST)
phone = request.POST['phone']
address = request.POST['address']
pincode = request.POST['pincode']
if user_form.is_valid() :
# Hash password using make_password() function
user = user_form.save(commit=False)
user.password = make_password(user.password)
user.save()
...

Related

Can't get Django forms to save to User and Profile model

I am trying to extend the Django User model by creating a user Profile model. When users register for the site, I want them to be able to select what class period they are in. To do this, I've tried to create a form that alters the User model, and a form that alters the Profile model. The problem is that when I try to put both forms into 'users/register.html' I am getting an error that says 'Anonymous User has to data _meta'. Below is my original code that only has the form for altering the User model in 'users/register.html'. How can I configure the registration so that users are able to save to the User and Profile model when they are first signing up for the site?
models.py
class Profile(models.Model):
'''
periods = [
('-','-'),
('1','1'),
('2','2'),
('3','3'),
('4','4'),
('6','6'),
('7','7'),
]
'''
user = models.OneToOneField(User,on_delete=models.CASCADE)
period = models.IntegerField(default=1)
first_name = models.CharField(max_length=100,default='Home')
last_name = models.CharField(max_length=100,default='Simpson')
def __str__(self):
return f'{self.user.username}'
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email','password1','password2']
class UserProfileForm(forms.ModelForm):
periods = [
(1,1),
(2,2),
(3,3),
(4,4),
(6,6),
(7,7),
]
period = forms.ChoiceField(choices=periods)
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
class Meta:
model = Profile
fields = ['first_name','last_name','period']
signals.py
#receiver(post_save,sender=User)
def create_profile(sender,instance,created,**kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save,sender=User)
def save_profile(sender,instance,**kwargs):
instance.profile.save()
views.py
def login(request):
context = {
'title':'Login',
}
return render(request,'users/login.html',context)
def register(request):
if request.method == "POST":
form = UserRegisterForm(request.POST)
if form.is_valid():
email = form.cleaned_data.get('email')
email_domain = re.search("#[\w.]+", email)
if email_domain.group() == EMAIL_DOMAIN:
form.save()
username = form.cleaned_data.get('username')
messages.success(request,f'Account created for {username}! You are now able to sign in.')
return redirect('users-login')
else:
messages.error(request,f'Sorry. You are not authorized to register.')
else:
form = UserRegisterForm()
context = {
'title':'Register',
'form':form
}
return render(request,'users/register.html',context)
This is happening because you are putting both the forms in the register page . When you have not created any user so how you can create a profile and how would you be able to add or retrieve data from it?
Now the solution for that is ,
1 . You create a page for registering the user say "users/register.html" , when they successfully register there, create a signal for creating the Profile for him , then successfully log the user in . Then redirect the just registered user to the profile change page.
Take both the forms in the user register page but do not validate the profile_change form .Create the user in the view and then reference it to the profile_change_form .
A simple code bit for that .
def registerUser(request) :
if request.method == "POST" :
user_form = UserRegisterForm(request.POST)
if user_form.is_valid():
username = request.POST.get("username")
# fields you require
user = User(username = username , password = password)
user.save()
profile_field_objects = request.POST.get("profile_field_data")
profile = Profile(user = user , profile_field_objects = profile_field_objects)
profile.save()
# rest you can code

NOT NULL constraint failed: users_details.user_id

I've tried to add another details form that have address and birth date on my registration form page. Every time i tried to sign up i get the NOT NULL constraint failed error.
models.py
class Details(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=60, blank=True)
birth_date = models.DateField(null=True, blank=True)
views.py
def register(request):
if request.method == 'POST':
r_form = UserRegisterForm(request.POST)
o_form = DetailsForm(request.POST)
if r_form.is_valid and o_form.is_valid():
r_form.save()
o_form.save()
username = r_form.cleaned_data.get('username')
messages.success(request, f'Your account has been created!')
return redirect('login')
else:
r_form = UserRegisterForm()
o_form = DetailsForm()
context = {
'r_form' : r_form,
'o_form' : o_form
}
return render(request, 'users/register.html', context)
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email','password1', 'password2']
class DetailsForm(forms.ModelForm):
address = forms.CharField()
birth_date = forms.DateField()
class Meta:
model = Details
fields = ['address', 'birth_date']
ERROR
While extraneous details/profile "sidecar" models are not the best practice since pluggable user models came along, this particular problem is caused by the two models not being associated.
Try
if r_form.is_valid and o_form.is_valid():
user = r_form.save()
o_form.instance.user = user
o_form.save()

Insert the current user when creating an object in Database? [duplicate]

I am writing an application which stores "Jobs". They are defined as having a ForeignKey linked to a "User". I don't understand how to pass the ForeignKey into the model when creating it. My Model for Job worked fine without a ForeignKey, but now that I am trying to add users to the system I can't get the form to validate.
models.py:
from django.db import models
from django import forms
from django.contrib.auth.models import User
class Job(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=50, blank=True)
pub_date = models.DateTimeField('date published', auto_now_add=True)
orig_image = models.ImageField('uploaded image', upload_to='origImageDB/', blank=True)
clean_image = models.ImageField('clean image', upload_to='cleanImageDB/', blank=True)
fullsize_image = models.ImageField('fullsize image', upload_to='fullsizeImageDB/')
fullsize_clean_image = models.ImageField('fullsize clean image', upload_to='fullsizeCleanImageDB/')
regions = models.TextField(blank=True)
orig_regions = models.TextField(blank=True)
class JobForm(forms.ModelForm):
class Meta:
model = Job
In views.py I was creating the objects as follows:
if request.method == 'POST':
form = JobForm(request.POST, request.FILES)
if form.is_valid():
#Do something here
I understand that this passes the form data and the uploaded files to the form. However, I don't understand how to pass in a User to be set as the ForeignKey.
Thanks in advance to anyone who can help.
A typical pattern in Django is:
exclude the user field from the model form
save the form with commit=False
set job.user
save to database
In your case:
class JobForm(forms.ModelForm):
class Meta:
model = Job
exclude = ('user',)
if request.method == 'POST':
form = JobForm(request.POST, request.FILES)
job = form.save(commit=False)
job.user = request.user
job.save()
# the next line isn't necessary here, because we don't have any m2m fields
form.save_m2m()
See the Django docs on the model form save() method for more information.
Try:
if request.method == 'POST':
data = request.POST
data['user'] = request.user
form = JobForm(data, request.FILES)
if form.is_valid():
#Do something here

Error when invoking creation of another form

models.py:
from django.db import models
from django.contrib.auth.models import User as BaseUser
CHOICE_GENDER = ((1, 'Male'), (2, 'Female'))
class Location(models.Model):
city = models.CharField(max_length=75)
country = models.CharField(max_length=25)
def __unicode__(self):
return ', '.join([self.city, self.state])
class Users(BaseUser):
user = models.OneToOneField(BaseUser, on_delete=models.CASCADE)
gender = models.IntegerField(choices=CHOICE_GENDER)
birth = models.DateField()
location = models.ForeignKey(Location)
class Meta:
ordering = ('user',)
forms.py:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from .models import Users, Location, CHOICE_GENDER
class LocationForm(forms.ModelForm):
city = forms.CharField(max_length=75)
country = forms.CharField(max_length=25)
class Meta:
model = Location
fields = ('city', 'country',)
class RegistrationForm(UserCreationForm):
email = forms.CharField(max_length=75)
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
gender = forms.ChoiceField(choices=CHOICE_GENDER)
birth = forms.DateField()
location = LocationForm()
class Meta:
model = Users
fields = ('username', 'email', 'first_name', 'last_name', 'gender', 'birth')
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.gender = self.cleaned_data['gender']
user.birth = self.cleaned_data['birth']
if commit:
user.save()
return user
This code in forms.py doesn't work. It doesn't save LocationForm due to these errors:
country - This field is required.
city - This field is required.
I've certainly did something wrong here, but I don't know exactly what. I admit that I've jumbled the code in forms.py, especially in the save method for RegistrationForm because I don't know how to properly invoke the creation of another form and how to make a connection between two of them. I searched the Internet but I couldn't find precise info about that, so I tried to improvise but I've failed, unfortunately.
Could someone help me with this? Thanks in advance!
UPDATE: views.py (currently):
def signup(request):
if request.method == "POST":
reg_form = RegistrationForm(request.POST)
loc_form = LocationForm(request.POST)
if reg_form.is_valid() and loc_form.is_valid():
location = loc_form.save()
reg_form.cleaned_data['location_id'] = location.id
registration = reg_form.save()
else:
pass
else:
reg_form = RegistrationForm()
loc_form = LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form':reg_form})
I've also modified forms.py but I still got the error from above.
Instead of using LocationForm inside RegistrationForm you can handle them seprately in your views.py it will result in a cleaner code and easy to handle.
if request.method == "POST":
reg_form = RegistrationForm(request.POST)
loc_form = LocationForm(request.POST)
if reg_form.is_valid() and loc_form.is_valid():
# since in your case they are dependent on each other
# save location form and get location object
location = loc_form.save()
# now you can use it in your reg_form
reg_form.cleaned_data['location_id'] = location.id
registration = reg_form.save()
else:
# no need to handle this case only for explanation
# use the forms, with valid post data initialized
# at the start of current if block
pass
else:
# create new forms for location and registration
reg_form = RegistrationForm()
loc_form = LocationForm()
return render(request, 'signup.html', {'loc_form': loc_form, 'reg_form':reg_form})
You can read here more on how to handle more than one nested forms in django docs.

How to hash text to md5/sha1 in django?

I want to convert text to sha1 in django. But, i'm not find the way how to do it if field attribut wrapped by the form.
This is my views:
def ubah_password_email(request, pk):
#cek session
if 'username' in request.session and request.session['hak_akses'] == 'user':
user = get_object_or_404(User, pk=pk) #ambil id dengan get
profile = UserProfile.objects.filter(user=user).first()
email_form = EmailForm(data=request.POST, instance=profile) #gunakan instance untuk mengambil data yang sudah ada
users = User.objects.all()
if request.POST:
if email_form.is_valid():
email = email_form.save(commit=False)
email.save()
return redirect('home')
else:
email_form = EmailForm(instance=profile)
data = {
'email_form': email_form,
'object_list': users,
}
return render(request, 'ubah_password_email.html', data)
else:
return HttpResponseRedirect('/simofa/logout')
This is my model
class UserProfile(models.Model):
user = models.OneToOneField(User) #digunakan untuk relasi ke model User (default) alias UserProfile adalah sebagai extending model
CATEGORY_CHOICES = (
('admin','Admin'),
('user','User'),
)
hak_akses = models.CharField(max_length=100, choices = CATEGORY_CHOICES)
password_email = models.CharField(max_length=100, blank=True)
password_pckelas = models.CharField(max_length=100, blank=True)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
This is my forms
class EmailForm(forms.ModelForm):
password_email = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = UserProfile
fields = ('password_email',)
i'm trying using this and this reference. But, i still can't convert text to sha1?
I'm very grateful for your input. So, please help me :)
I'm not sure why you want or need a second password field. But make_password allows you to generate a hashed password:
from django.contrib.auth.hashers import make_password
Docs: https://docs.djangoproject.com/en/1.7/topics/auth/passwords/#django.contrib.auth.hashers.make_password
Source: https://github.com/django/django/blob/master/django/contrib/auth/hashers.py#L58