DJANGO: Trying to save POST data to Student model - IntegrityError - python

Hi I am trying to save data from a form to Student model; abstract User model.
Please help!
PROBLEM: IntegrityError at /register/ UNIQUE constraint failed:
accounts_students.username
Not sure what the problem, in the view i am trying to clean the data and save it to the database.
Interestingly, the data is being saved, just the page is not being
redirected!
from .models import *
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from betterforms.multiform import MultiModelForm
from django.contrib.auth.forms import UserCreationForm
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = Students
fields = (
'username',
'first_name',
'last_name',
'email',
'password1',
'password2',
'bio',
'location',
'birth_date',
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
models.py
class Students(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
views.py
from django.shortcuts import render
from django.shortcuts import redirect
from accounts.forms import RegistrationForm, EditProfileForm
from django.contrib.auth.models import User
from accounts.models import Students
from django.contrib.auth.forms import UserChangeForm
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
# Create your views here.
# def login(request):
# return render(request, 'accounts/login.html')
def home(request):
return render(request, 'accounts/home.html')
def login_redirect(request):
return redirect('/login/')
def register(request):
# Once register page loads, either it will send to the server POST data (if the form is submitted), else if it don't send post data create a user form to register
if request.method == "POST":
form = RegistrationForm(request.POST)
if form.is_valid():
bio = form.cleaned_data['bio']
location = form.cleaned_data['location']
birth_date = form.cleaned_data['birth_date']
form.save()
Students.objects.create(bio=bio, location=location, birth_date=birth_date)
# Students.objects.create(user=user)
return redirect('../home/')
else:
# Create the django default user form and send it as a dictionary in args to the reg_form.html page.
form = RegistrationForm()
args = {'form': form}
return render(request, 'accounts/reg_form.html', args)
#login_required
def view_profile(request):
args = {'user': request.user}
return render(request, 'accounts/profile.html', args)
#login_required
def edit_profile(request):
# Handle post request - if the user submits a form change form details and pass the intance user
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('../profile')
# Handles the get request - if no post info is submitted then get the form and display it on the edit profile page.
else:
form = EditProfileForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/profile_edit.html', args)

Related

user created with no password Django (users can't log in)

Im registering succesfully user, but when ot redirects me to login page I'm 100% sure password is correct, but it is not login me in, so I checked the admin page for that particular user, username exists, but it says that the password is not created yet.
this is my views.py
#from selectors import EpollSelector
from django.shortcuts import render, redirect
from django.contrib import messages
from django.http import HttpResponseRedirect
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
from django.contrib.auth.decorators import login_required
# Create your views here
def register(request):
if request.method == "POST":
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get("username")
messages.success(request, f'You are now able to log in!')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'Users/register.html', {'form': form})
#login_required
def profile(request):
if request.method == "POST":
u_form = UserUpdateForm(request.POST, instance = request.user)
p_form = ProfileUpdateForm(request.POST,
request.FILES,
instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f'You account has been updated!')
return redirect('profile')
else:
u_form = UserUpdateForm(instance = request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)
context = {
'u_form' :u_form,
'p_form' :p_form
}
return render(request, 'Users/profile.html', context)
and this is my forms.py code
from socket import fromshare
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserChangeForm
from .models import Profile
class UserRegisterForm(UserChangeForm):
email = forms.EmailField()
password1 = forms.CharField(label = "Password", widget = forms.PasswordInput)
password2 = forms.CharField(label = "Repeat password", widget = forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']
Please suggest some solution. I was following Corey Schafer tutorial.
Try to read about django.contrib.auth and passwords.
https://docs.djangoproject.com/en/4.1/topics/auth/default/#changing-passwords
Django don't change password to hash, you should do it yourself before user.save()
in your case:
... # your staff
form = UserRegisterForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(form.cleaned_data['password'])
user.save()
username = user.username
messages.success(request, f'You are now able to log in!')
... # other staff

Hash a password field outside of the User model - Django

I am trying to have a user register, and then log in. Once they are logged in they specify their WiFi name, followed by a wifi password, and their choice of a VPN. The problem I am having is hashing the wifi_password field upon saving it to the database. I am trying to hash the password within the edit function in views.py. I have posted the entirety of my models, forms, and views. The code is still sloppy, and will need some cleaning up when I can achieve functionality. Thanks.
models.py
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
vpn_choices = [
('openvpn', 'Open VPN'),
('pia', 'Private Internet Access'),
('expressvpn', 'Express VPN'),
]
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete = models.CASCADE,
null = True)
wifi = models.CharField(max_length = 128)
wifi_password = models.CharField(max_length = 128)
vpn_choice = models.CharField(max_length = 20, choices = vpn_choices)
def __str__(self):
return f'self.user.username {self.user.username}'
forms.py
from django import forms
from django.contrib.auth.models import User, AbstractUser
from django.contrib.auth import get_user_model
from server.models import Profile
from django.forms import ModelForm
vpn_choices = [
('openvpn', 'Open VPN'),
('pia', 'Private Internet Access'),
('expressvpn', 'Express VPN'),
]
class LoginForm(forms.Form):
username = forms.CharField(max_length = 126)
password = forms.CharField(max_length = 126, widget = forms.PasswordInput)
class UserRegistrationForm(forms.ModelForm):
password = forms.CharField(label = 'Password',
widget = forms.PasswordInput)
password2 = forms.CharField(label = 'Repeat Password',
widget = forms.PasswordInput)
class Meta:
model = User
fields = ('username',)
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords don\'t match.')
return cd['password2']
class ProfileEditForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('wifi', 'wifi_password', 'vpn_choice')
labels = {
'wifi': ('WiFi'),
'wifi_password': ('WiFi Password'),
'vpn_choice': ('VPN Choice'),
}
widgets = {
'wifi_password': forms.PasswordInput
}
views.py
from django.shortcuts import render, redirect, reverse
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponse, HttpResponseRedirect
from .forms import LoginForm, UserRegistrationForm, ProfileEditForm
from django.contrib.auth.decorators import login_required
from server.models import Profile
from django.contrib.auth.hashers import make_password
def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(request,
username = cd['username'],
password = cd['password'])
if user is not None:
if user.is_active:
login(request, user)
return HttpResponse('Authenticated '\
'successfully')
else:
return HttpResponse('Disabled account')
else:
return HttpResponse('Invalid Login')
else:
form = LoginForm()
return render(request, 'login.html', {'form': form})
def index(request):
return render(request, 'index.html')
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid():
# Create a new user object but avoid saving it yet
new_user = user_form.save(commit = False)
# Set the chosen password
new_user.set_password(
user_form.cleaned_data['password'])
# Save the User object
new_user.save()
# Create the user profile
Profile.objects.create(user = new_user)
return render(request,
'register_done.html',
{'new_user': new_user})
else:
user_form = UserRegistrationForm()
return render(request,
'register.html',
{'user_form': user_form})
#login_required
def user_logout(request):
logout(request)
return HttpResponseRedirect(reverse('index'))
#login_required
def edit(request):
if request.method == 'POST':
profile_form = ProfileEditForm(instance = request.user.profile,
data = request.POST)
if profile_form.is_valid():
settings = profile_form.save(commit = False)
password = make_password('wifi_password')
settings.save()
else:
profile_form = ProfileEditForm()
return render(request, 'edit.html',
{'profile_form': profile_form})
But if you will hash the password yourself, you will need to override authenticate as well as the Django won't be able to regenerate the hash to find the user record

How do I show model field values in HTML page, in Django for this particular case?

I need to display the details of the user on the profilepage. But in the following situation, I am unable to render phone number and flag(attributes of SpecialUser model) on my profile page. I was asked to implement an extended model for the User model in Django auth for an application. I introduced 2 new fields i.e, phonenumber(charfield), flag(booleanfield). My form is able to take both the inputs. But I couldn't render these values again into my HTML file. Could someone help me out!
models.py
# accounts.models.py
from django.db import models
from django.contrib.auth.models import User
class SpecialUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
flag = models.BooleanField(verbose_name="Special User", default=False)
phonenumber = models.CharField(max_length=10, verbose_name="phonenumber")
def __str__(self):
return self.user.username
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import SpecialUser
class RegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ["username", "email", "password1", "password2"]
class SuperUserForm(forms.ModelForm):
class Meta:
model = SpecialUser
fields = ["flag", "phonenumber"]
views.py
from accounts.models import SpecialUser
from django.shortcuts import render, redirect
from .forms import RegisterForm, SuperUserForm
from django.contrib import messages
from django.contrib.auth.models import auth
def register(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
sp_form = SuperUserForm(request.POST)
if form.is_valid() and sp_form.is_valid():
user = form.save()
sp_form = sp_form.save(commit=False)
sp_form.user = user
sp_form.save()
messages.success(request, 'Account created!')
return redirect('login')
else:
form = RegisterForm(request.POST)
sp_form = SuperUserForm(request.POST)
messages.warning(request, 'Your account cannot be created.')
return render(request, 'register.html', {'form': form, 'sp_form': sp_form})
def login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
data = SpecialUser.objects.all()
dt = {"all": data}
return render(request, "profilepage.html", dt)
else:
messages.info(request, 'invalid credentials')
return redirect('login')
else:
return render(request, 'login.html')
def logout(request):
auth.logout(request)
return redirect('login')
profilepage.html
<h1>{{user.username}}</h1>
<h4>Email : {{user.email}}</h4>
<h5>Phone Number : {{all.phonenumber}}</h5>
{%if user.flag %}
<button>Special User</button>
{%endif%}
here is the correct html you need to see your data
{%for d in all%}
{%ifequal d.user user%}
<h1>{{d.user.username}}</h1>
<h4>Email : {{d.user.email}}</h4>
<h5>Phone Number : {{d.phonenumber}}</h5>
{%if d.flag %}
<button>Special User</button>
{%endif%}
{%endifequal%}
{%endfor%}

How do I pass the users model as the ForeignKey value while saving a ModelForm in Django?

The models file:
from django.db import models
from django.conf import settings
class Book(models.Model):
rel_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name="Posted By")
title = models.CharField(max_length=256, verbose_name="Title")
description = models.TextField(verbose_name="Description")
price = models.IntegerField(verbose_name="Price")
state = models.CharField(max_length=256, verbose_name="State")
city = models.CharField(max_length=256, verbose_name="City")
neighbourhood = models.CharField(max_length=256, verbose_name="Neighbourhood")
phone = models.IntegerField(verbose_name="Phone Number")
def __str__(self):
return self.title + f" ({self.rel_user.username})"
The forms file:
from django.forms import ModelForm
from Books.models import Book
class BookForm(ModelForm):
class Meta:
model = Book
fields = ['title', 'description', 'price', 'state', 'city', 'neighbourhood', 'phone']
The views file:
from django.shortcuts import render, redirect
from Books.forms import BookForm
from django.contrib import messages
def sell(request):
if request.method == "GET":
form = BookForm()
else:
form = BookForm(request.POST, )
if form.is_valid():
form.save()
messages.success("Successfully added!")
return redirect('sell')
else:
messages.error("Please fill in all the fields.")
return render(request, 'Books/sell.html', {"form": form})
Every time a user submits the form, I want the ForeignKey's value to be filled with that users model. How do I do this?
So suppose user "John" has filled the form. When he clicks submit, the details he enters + his user model should go into the database for that entry.
def sell(request):
if request.method == "POST":
form = BookForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.rel_user = request.user
instance.save()
messages.success("Successfully added!")
return redirect('sell')
else:
messages.error("Please fill in all the fields.")
else:
form = BookForm()
return render(request, 'Books/sell.html', {"form": form}
request.user can be assigned to rel_user as above
You can assign the user to the instance of the form:
from django.shortcuts import render, redirect
from Books.forms import BookForm
from django.contrib import messages
def sell(request):
if request.method == 'GET':
form = BookForm()
else:
form = BookForm(request.POST)
form.instance.rel_user = request.user
if form.is_valid():
form.save()
messages.success('Successfully added!')
return redirect('sell')
else:
messages.error('Please fill in all the fields.')
return render(request, 'Books/sell.html', {'form': form})

Log in automatically after registering [duplicate]

This question already has answers here:
How to automatically login a user after registration in django
(6 answers)
Closed 7 years ago.
In django 1.9, how do you automatically log in the user after they have registered?
I followed the answer from this question, but I get this error when trying it out.
I added AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) to settings.py
Here is my views.py:
from django.shortcuts import render
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .models import UserProfile
from django.contrib.auth.models import User
from .forms import UserForm
from .forms import UserProfileForm
from django.http import HttpResponseRedirect
from django.contrib.auth import authenticate, logout, login
# Create your views here.
def RegisterView(request):
registration_success = False
if request.method == 'POST':
user_form = UserForm(request.POST, prefix='uf')
profile_form = UserProfileForm(request.POST, request.FILES, prefix='upf')
if user_form.is_valid() and profile_form.is_valid():
user_atr = user_form.save()
user_atr.set_password(user_atr.password)
user_atr.save()
profile = profile_form.save(commit=False)
profile.user = user_atr
profile.avatar = request.FILES.get('avatar')
profile.save()
registration_success = True
user_atr = authenticate(username=request.POST['username'],
password=request.POST['password'])
login(request, user_atr)
return HttpResponseRedirect("/")
else:
print (user_form.errors, profile_form.errors)
else:
user_form = UserForm(prefix='uf')
profile_form = UserProfileForm(prefix='upf')
return render(request, 'profile/register.html', {'profile_form': profile_form, 'user_form': user_form})
And my forms.py:
class UserForm(ModelForm):
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'field-input-element'
confirm_password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
widgets = {
'password': forms.PasswordInput(),
}
class UserProfileForm(ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'field-input-element'
class Meta:
model = UserProfile
fields = ('display_name', 'avatar', 'birthday', 'usertype', 'daw', 'usergenre', 'gender')
widgets = {
'birthday': AdminDateWidget(),
}
You are using a prefix for your form, so the data will be posted as uf-username and uf-password. Therefore request.POST['username'] gives a KeyError.
It's not normally a good idea to fetch data directly from request.POST anyway. Fetch it from the form's cleaned data instead, and let Django take care of the prefix and validation.
user_atr = authenticate(username=user_form.cleaned_data['username'],
password=user_form.cleaned_data['password'],
)

Categories