Django: creating form which has relationship - django

I've prepared a model with a relationship.
I'd like to get a form which will make it possible to create User for that form.
Could someone explain me how it can be resolved?
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True, primary_key=True)
website = models.URLField(null=True, blank=True)
accepted_rules = models.BooleanField(default=False)
accepted_rules_date = models.DateTimeField(auto_now_add=True)
class UserProfile(ModelForm):
class Meta:
model = UserProfile
#csrf_protect
def register(request):
if request.method == "POST":
form = UserProfile(request.POST or None)
if form.is_valid():
website = form.cleaned_data['website']
accepted_rules = form.cleaned_data['accepted_rules']
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
form.save()
print "All Correct"
return TemplateResponse(request, 'base.html', {
'form':form,
}
)

Here is one way I would consider. First of all, I would name the form UserProfileForm so that it's name doesn't conflict with the model. Add extra fields to your UserProfile form for the fields required to create a new user. Create the new User instance. Use form.save(commit=False) so that you can add the newly created User instance to the UserProfile instance and save it. There may be a more elegant way.
from django import forms
class UserProfileForm(forms.ModelForm):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput())
email = forms.EmailField()
class Meta:
model = UserProfile
from django.contrib.auth.models import User
#csrf_protect
def register(request):
if request.method == "POST":
form = UserProfileForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = User(username=username, email=email)
user.set_password(password)
user.save()
user_profile = form.save(commit=False)
user_profile.user = user
user_profile.save()
print "All Correct"
return TemplateResponse(request, 'base.html', {'form':form})

Related

Django form : Setting the user to logged in user

I am trying to create an address book website where logged in user is able to fill in a form and store contact information. I was able to implement the login and logout functionality. But the problem is that I am not able to set the username to current logged in user. Here is what I have implemented so far:
Models.py
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
#additional
def __str__(self):
return self.user.usernname
class UserContacts(models.Model):
current_user = models.ForeignKey(User,on_delete=models.CASCADE)
first_name = models.CharField(max_length = 150)
last_name = models.CharField(max_length = 150)
phone_number = models.CharField(max_length = 150)
email_address = models.CharField(max_length = 150)
street_address = models.CharField(max_length = 350)
def __str__(self):
return '{}'.format(self.first_name)
Forms.py
class UserForm(forms.ModelForm):
password = forms.CharField(widget = forms.PasswordInput())
class Meta():
model = User
fields = ('username','email','password')
class UserContactForm(forms.ModelForm):
class Meta():
model = UserContacts
fields = "__all__"
views.py:
#login_required
def new_contact(request):
form = UserContactForm()
current_user = request.user.get_username()
user = User.objects.filter(username=current_user).first()
output = UserContacts.objects.filter(current_user_id=user.id).first()
if request.method == "POST":
form = UserContactForm(request.POST)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print('Error Form Invalid')
return render(request,'basic_app/contact.html',{'form':form})
Here is how the output looks like when the logged in user tries to enter contact information details:
Updating contact screenshot. As you can see the current user has to select his username to fill out the contact information.
How to overcome this and by default set the username in the form to the current logged in user
Change your UserContactForm to include an extra perameter in __init__, and set the initial value on the user field:
class UserContactForm(forms.ModelForm):
class Meta():
model = UserContacts
fields = "__all__"
def __init__(self, *args, **kws):
# To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
self.user = kws.pop('user')
super().__init__(*args, **kws)
self.fields['user'].initial = self.user
Then change you view to add in the request.user to the form construction:
#login_required
def new_contact(request):
form = UserContactForm(user=request.user)
current_user = request.user.get_username()
user = User.objects.filter(username=current_user).first()
output = UserContacts.objects.filter(current_user_id=user.id).first()
if request.method == "POST":
form = UserContactForm(request.POST, user=request.user)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print('Error Form Invalid')
return render(request,'basic_app/contact.html',{'form':form})
You could probably remove the:
current_user = request.user.get_username()
user = User.objects.filter(username=current_user).first()
output = UserContacts.objects.filter(current_user_id=user.id).first()

How to update django auth User using a custom form

I am using Django's built in authentication to manage users on a social media website. I am using a one-to-one relationship to attach a profile to each user. I can update all the parts of the profile I have attached using an UpdateView. However I don't know how to do that with Django's built in User. So I created a form that uses the _meta class. I have gotten to the point where my form will add a new user instead of update the current one. I was hoping one of you could help me fix my code. Thanks in advance for any help you can offer
views.py
class PrivProfileUpdate(View):
form_class = UserUpdateForm
template_name = 'user/user_form.html'
#display a blank form
def get(self, request, pk):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
#proces form data
def post(self, request, pk):
form = self.form_class(request.POST)
user = User.objects.get(pk=pk)
if form.is_valid():
user = form.save(commit=True)
print("we are trying to save")
#cleaned (normalized) data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
email = form.cleaned_data['email']
user.set_password(password) #this is the only way to change a password because of hashing
user.save()
return render(request, self.template_name,{'form': form})
forms.py
class UserUpdateForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password', 'first_name', 'last_name']
SOLUTION:
in views.py
class PrivProfileUpdate(UpdateView):
model = User
form_class = UserUpdateForm
template_name = 'user/user_form.html'
def form_valid(self, form):
user = form.save(commit=True)
password = form.cleaned_data['password']
user.set_password(password)
user.save()
return redirect('user:index')
There's nothing special about the User class here. Just as with any other model, to update an existing instance you pass it as the instance argument to the form.
However, you do not actually need to do this at all yourself. You should be using an UpdateView, which does this for you; then you do not need to define get and post. The only method you need to define here is form_valid, to set the password:
class PrivProfileUpdate(UpdateView):
form_class = UserUpdateForm
template_name = 'user/user_form.html'
def form_valid(self, form):
user = form.save(commit=True)
password = form.cleaned_data['password']
user.set_password(password)
user.save()
return HttpResponseRedirect(self.get_success_url())

RelatedObjectDoesNotExist while using custom User model in Django

I have an account app in which I have created a Profile model by extending the custom user model. I have created a view which allows the user to edit his profile info and also I have corresponding UserEditForm and ProfileEditForm. As of now, no user has a profile so when I open the edit form I get an error: "RelatedObjectDoesNotExist at /account/edit/".
" User has no profile "
I tried to create the profile using admin , then the error goes away. How can I correct this in my views.py file.
views.py
#login_required
def edit(request):
if request.method =='POST':
user_form = UserEditForm(instance=request.user,data=request.POST)
profile_form = ProfileEditForm(instance=request.user.profile,data=request.POST,files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request,'Profile updated successfully')
else:
messages.error(request,'Error updating your profile')
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
context = {
'user_form':user_form,
'profile_form': profile_form
}
return render(request,'account/edit.html',context)
models.py
CATEGORY_CHOICES = (
('SA','School Admin'),
('T','Teacher'),
('S','Student'),
('P','Parent'),
)
class Profile(models.Model):
eduser = models.OneToOneField(settings.AUTH_USER_MODEL)
photo = models.ImageField(upload_to='users/%Y/%m/%d',blank=True)
about_me = models.TextField(max_length=200,blank=True)
category = models.CharField(max_length=1,choices=CATEGORY_CHOICES,blank=True)
date_of_birth = models.DateField(blank=True,null=True)
def __str__(self):
return 'Profile for user {}'.format(self.eduser.username)
forms.py
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name','last_name','email')
class ProfileEditForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('category','date_of_birth','about_me','photo')
You need to catch the error. You can do it at the top of the function:
try:
profile = request.user.profile
except ObjectDoesNotExist:
profile = Profile(user=request.user)
and pass that profile into the ProfileEditForm in both if branches.

check_password always returning false even if the password is correct?

I am using Django 1.5. I am a custom User model like this:
class User(AbstractBaseUser):
#id = models.IntegerField(primary_key=True)
#identifier = models.CharField(max_length=40, unique=True, db_index=True)
username = models.CharField(max_length=90, unique=True, db_index=True)
create_time = models.DateTimeField(null=True, blank=True)
update_time = models.DateTimeField(null=True, blank=True)
email = models.CharField(max_length=225)
#password = models.CharField(max_length=120)
external = models.IntegerField(null=True, blank=True)
deleted = models.IntegerField(null=True, blank=True)
purged = models.IntegerField(null=True, blank=True)
form_values_id = models.IntegerField(null=True, blank=True)
disk_usage = models.DecimalField(null=True, max_digits=16, decimal_places=0, blank=True)
objects = UserManager()
USERNAME_FIELD = 'email'
class Meta:
db_table = u'galaxy_user'
I have a custom authentication:
class AuthBackend:
def authenticate(self, username=None, password=None):
if '#' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
Even after entering the correct username and password check_password() always returning false so that I can't login. I tried that in terminal too:
user.check_password(password)
is always returning False.
#views.py:
def login_backend(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
state = "Username or Password Incorrect!"
if user is not None:
login(request, user)
return HttpResponseRedirect('/overview/')
else:
return render_to_response('login_backend.html', {'state':state}, context_instance=RequestContext(request))
else:
return render_to_response('login_backend.html', context_instance=RequestContext(request))
The problem is that when you create your CustomUser, you save the password in open-way(without hashing). Can you give me your RegistrationForm code?
In my case:
# forms/register.py
class RegistrationForm(forms.ModelForm):
"""
Form for registering a new account.
"""
class Meta:
model = CustomUser
fields = ['username', 'password', 'email']
Register-handler:
# views.py
def register(request):
"""
User registration view.
"""
if request.method == 'POST':
form = RegistrationForm(data=request.POST)
if form.is_valid():
user = form.save() # Save your password as a simple String
return redirect('/')
else:
form = RegistrationForm()
return render(request, 'news/register.html', {'form': form})
So when you try to login:
if user.check_password(password):
return user
check_password always returns False.
Solution:
To set password properly, you should redefine save() method in RegistrationForm:
# forms/register.py
class RegistrationForm(forms.ModelForm):
"""
Form for registering a new account.
"""
class Meta:
model = CustomUser
fields = ['username', 'password', 'email']
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.set_password(user.password) # set password properly before commit
if commit:
user.save()
return user
Or simply change handler:
def register(request):
"""
User registration view.
"""
if request.method == 'POST':
form = RegistrationForm(data=request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(request.POST["password"])
user.save()
return redirect('/')
else:
form = RegistrationForm()
return render(request, 'news/register.html', {'form': form})

where to create group and pass the permission in django

i need to create group seekers and user register he has to automatically add to seekers
models.py
class Seeker(models.Model):
user = models.OneToOneField(User)
birthday = models.DateField()
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
forms.py
this is the default user for storing the userid & password for my application
class RegistrationForm(ModelForm):
username = forms.CharField(label = (u'User Name'))
email = forms.EmailField(label =(u'Email Address'))
password = forms.CharField(label = (u'Password'),widget = forms.PasswordInput(render_value = False))
password1 = forms.CharField(label =(u'Verify Password'),widget = forms.PasswordInput(render_value = False))
class Meta:
model = Seeker
exclude = ('user',)
def clean_username(self):
username = self.cleaned_data['username']
try:
User.objects.get(username = username)
except User.DoesNotExist:
return username
raise forms.ValidationError("That username is already taken,please select another.")
def clean(self):
if self.cleaned_data['password'] != self.cleaned_data['password1']:
raise forms.ValidationError("The Password did not match please try again.")
return self.cleaned_data
views.py
i am using default user for creating the user
def SeekersRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == "POST":
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(username = form.cleaned_data['username'], email = form.cleaned_data['email'], password =form.cleaned_data['password'])
user.save()
seekers = Seeker(user =user, name = form.cleaned_data['name'],birthday = form.cleaned_data['birthday'])
seekers.save()
return HttpResponseRedirect('/profile/')
else:
return render_to_response('register.html',{'form':form},context_instance = RequestContext(request))
else:
'''user is not submitting the form, show them a blank registration form'''
form = RegistrationForm()
context = {'form':form}
return render_to_response('register.html',context,context_instance = RequestContext(request))
Use signals
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=User)
def add_user_to_specific_group(instance, created, **kwargs):
if created:
# assign user to group