Different Languages for django username - python

How to enable users to use other languages such as Chinese in username field using the usercreation form?
The methods I have tried:
modify the regex field of username field, failed
What it tells me: the validation is not with the field, but the user model itself
encode the incoming input using encode("utf-8")
What it tells me: the data i
client side utf transform...
This is the code in view:
def register_user(request):
currentPath = request.POST.get('currentPath', '')
currentPath = currentPath.replace("invalid/", "").replace("registered/", "")
username=request.POST.get('email')
password=request.POST.get('password1')
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
if "log" in currentPath:
return HttpResponseRedirect(currentPath)
else:
return HttpResponseRedirect('/register_success')
elif "log" in currentPath:
return HttpResponseRedirect(currentPath + "registered")
else:
form = MyRegistrationForm()
form.fields['password1'].label = "密码"
form.fields['password2'].label = "再次输入密码"
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('register.html', args)
I think the form.save() is where the problem come from... that the validator automatically validates the field no matter what and chinese characters fail the validation.
And the following is the customized registration form, I have tried to override regex field with an username field but it doesn't work.
my_default_errors = {
'required': '这个格子是必填的',
'invalid': '请输入符合要求的值',
}
class MyRegistrationForm(UserCreationForm):
error_messages = {
'duplicate_username': ("同样的用户名已经被注册了"),
'password_mismatch': ("和上次输入的不一样,请重新输入!"),
}
# this variable defines a field in the customized form, not a model datafield
username = forms.RegexField(label = "用户名(其他所有人可见,请使用英文)", required=True, max_length=30,
regex=r'^[\w.#+-\/\\]+$',
error_messages=my_default_errors,)
email = forms.EmailField(label="邮箱(用于登录)" ,required=True, max_length = 75, error_messages = my_default_errors, )
password1 = forms.CharField(label= "密码", required=True, widget=forms.PasswordInput, error_messages = my_default_errors,)
password2 = forms.CharField(label= "请再次输入", required=True, widget=forms.PasswordInput, error_messages = my_default_errors,)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
def clean_email(self):
email = self.cleaned_data["email"]
try:
user = User.objects.get(email=email)
raise forms.ValidationError("这个邮箱地址已被注册,是否忘记了密码?")
except User.DoesNotExist:
return email
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
user.email = self.cleaned_data["email"]
user.is_active = True # change to false if using email activation
if commit:
user.save()
return user

Related

How to use authenticate method with AbstractUser model django

I`m wrirting site on Django and I need to make a system for registration and authorization of work peepers, for this I use the Django AbstractUser model, registration works well, but authorization does not work, and the authenticate method returns None
Here is my JobseekerRegsiterInfo model:
class JobseekerRegisterInfo(AbstractUser):
username = first_name = last_name = None
id = models.BigAutoField(primary_key=True)
phone_number = PhoneNumberField()
email = models.EmailField(unique=True)
full_name = models.CharField(max_length=120)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['phone_number', 'full_name', 'hashed_password']
def __str__(self):
return self.full_name
My login form:
class JobseekerLoginForm(forms.Form):
email = forms.EmailField(label='Введіть ваш Email: ',
widget=forms.EmailInput(attrs={'class': 'form-control'}))
password = forms.CharField(label='Ваш пароль: ',
widget=forms.PasswordInput(attrs={'class': 'form-control'}))
def clean_email(self):
email = self.cleaned_data['email']
# if not select_field_value_from_model(JobseekerRegisterInfo, 'email', email):
if not JobseekerRegisterInfo.objects.filter(email=email):
raise forms.ValidationError('Неправильно введені email або пароль')
return email
and view function:
def jobseeker_login_view(request):
title = 'Авторизація'
context = {'title': title}
if request.method == 'POST':
form = JobseekerLoginForm(request.POST)
context['form'] = form
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(request, email=email, password=password)
print(generate_password_hash(password))
if user:
print(user)
else:
print('USER IS NONE')
else:
form_errors = form.errors.as_data()
custom_error = custom_error_service(form_errors)
context['list_first_error'] = custom_error
else:
form = JobseekerLoginForm()
context['form'] = form
return render(request, template_name='jobseeker/jobseeker_login.html', context=context)
But only USER IS NONE is displayed in the console, no matter what I do
Tell me, please, how to use authenticate correctly in my case

User Login Authentication using Django Model and form

I am trying to setup user authentication for the login page using forms and comparing it to my database value but it does not work. I also tried using this particular questions User Login Authentication using forms and Django logic to solve my problem but it didn't help.
Models.py
from django.db import models
from django.contrib.auth.password_validation import validate_password
class student(models.Model):
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
matric_number = models.CharField(max_length=9)
email = models.EmailField(max_length=50)
password1 = models.CharField(max_length=255, validators=[validate_password])
password2 = models.CharField(max_length=255)
def __str__(self):
return (self.matric_number)
This view saves user info to database
def student(request):
if request.method == 'POST':
form = studentForm(request.POST)
if form.is_valid():
sign_up = form.save(commit=False)
#sign_up.password1 = make_password(form.cleaned_data['password1'])
#sign_up.password2 = make_password(form.cleaned_data['password2'])
sign_up.status = 1
sign_up.save()
user = form.cleaned_data.get('matric_number')
messages.success(request, "Account was created for "+str(user))
return redirect(signin)
else:
form = studentForm()
return render(request, 'Student.html',{
"form": form
})
This is the signin view
def signin(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
try:
student = student.object.get(username=username, password=password)
return redirect(files)
except:
messages.success(request, "Error")
else:
form = LoginForm()
return render(request, "SignIn.html",{
"form":form
})
This is my form.py
class studentForm(forms.ModelForm):
class Meta:
model=student
fields="__all__"
widgets={
'first_name':forms.TextInput(attrs={'placeholder': 'Enter Your First Name'}),
'last_name':forms.TextInput(attrs={'placeholder': 'Enter Your Last Name'}),
'matric_number':forms.TextInput(attrs={'placeholder': 'Enter Your Matric Number'}),
'email':forms.EmailInput(attrs={'placeholder': 'abc#example.com'}),
'password1':forms.PasswordInput(attrs={'placeholder': 'Enter Your Preferred Password','id':'password'}),
'password2':forms.PasswordInput(attrs={'placeholder':'Confirm Your Password', 'id':'password1'})
}
def clean(self):
super(studentForm, self).clean()
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
matric_number = self.cleaned_data.get('matric_number')
email = self.cleaned_data.get('email')
try:
if password1 != password2:
self.errors[''] = self.error_class(["The two password fields must match"])
elif len(matric_number) != 9:
self.errors[''] = self.error_class(["You have entered an invalid matric number"])
elif len(matric_number) == 9:
matric_number = int(matric_number)
except ValueError:
self.errors[''] = self.error_class(["You have entered an invalid matric number"])
for instance in student.objects.all():
if instance.matric_number == str(matric_number):
self.errors[''] = self.error_class(["Matric number already exist"])
elif instance.email == email:
self.errors[''] = self.error_class(["E-mail address already exist"])
class LoginForm(forms.Form):
matric_number = forms.CharField(max_length=9, widget=forms.TextInput(attrs={'id': 'username', 'placeholder': 'Enter Your Staff Id Or Matric Number'}))
password1 = forms.CharField(max_length=9, widget=forms.PasswordInput(attrs={'id': 'password', 'placeholder':'Enter Your password'}))
Stop reinventing the wheel. Also, class names are supposed to be named with PascalCase.
Use AbstractUser model:
from django.contrib.auth.models import AbstractUser
class Student(AbstractUser):
...
and in your main urls.py:
from django.contrib.auth import views as auth_views
urlpatterns = [
...
path('login/', auth_views.LoginView.as_view(), name='login'),
...
]
It is much faster and SAFER way to create new user.
So I figured out out how to solve my problem. By using the AbstractUser model,i was able to create a custom user and then create another model which i extended a ForeignKey on the User model therefore allowing me to tie every user to their profile.
Here is my models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
pass
def __str__(self):
return self.username
class UserProfile(models.Model):
"""
This is the one for model.py
"""
username = models.ForeignKey(User, on_delete=models.CASCADE, null=True, default="")
profile_picture = models.ImageField(blank=True, null=True, default="")
matricno = models.CharField(max_length=9, default="", primary_key=True)
email = models.EmailField(default="")
first_name = models.CharField(max_length=200, default="")
last_name = models.CharField(max_length=255, default="")
class Meta:
verbose_name_plural = "Users Profile"
def __str__(self):
return self.first_name+ " "+self.last_name
And here is my views.py
def signup(request):
if request.method == "POST":
form = Signup(request.POST)
if form.is_valid():
username = request.POST["username"]
email = request.POST["email"]
password = request.POST["password"]
password2 = request.POST["password2"]
user = User.objects.create_user(
username=username,
password=password,
email=email,
)
user.save()
login(request, user)
messages.success(request, "Account Created successfully for " + username)
return redirect(details)
else:
form = Signup()
return render(request, "accounts/register.html", {"form": form})
def details(request, username):
user = User.objects.get(username=username)
form = Details()
if request.method == "POST":
form = Details(request.POST, request.FILES)
if form.is_valid():
detail = form.save(commit=False)
detail.username = request.user
detail.save()
return redirect(success, pk=detail.pk)
else:
form = Details(initial={"matricno":request.user.username})
return render(request, "details.html", {"form":form})
And finally my forms.py that i use in creating a signup form and perfoming validation
class Signup(forms.Form):
username = forms.CharField(
max_length=9,
widget=forms.TextInput(attrs={"placeholder": "Enter Your Matric Number"}),
)
email = forms.EmailField(
max_length=255,
widget=forms.EmailInput(attrs={"placeholder": "Enter Your E-mail Address"}),
)
password = forms.CharField(
max_length=255,
widget=forms.PasswordInput(
attrs={"placeholder": "Enter Your Password", "id": "password"}
),
)
password2 = forms.CharField(
max_length=255,
widget=forms.PasswordInput(
attrs={"placeholder": "Confirm Your Password", "id": "password2"}
),
)
def clean(self):
super(Signup, self).clean()
password = self.cleaned_data.get("password")
password2 = self.cleaned_data.get("password2")
username = self.cleaned_data.get("username")
email = self.cleaned_data.get("email")
if password != password2:
self.errors[""] = self.error_class(["The two password fields must match"])
for instance in User.objects.all():
if instance.username == str(username):
self.errors[""] = self.error_class(["User already exist"])
elif instance.email == email:
self.errors[""] = self.error_class(["E-mail already in use"])
else:
pass
return self.cleaned_data

Understanding the def clean(self) method inside custom login form class

Django Version = 2.2.2.
Does it not make sense to take out the def clean(self) method from class LoginForm(form.ModelForm)
class LoginForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
class Meta:
model = Account
fields = ['email', 'password']
def clean(self):
if self.is_valid():
email = self.cleaned_data['email']
password = self.cleaned_data['password']
if not authenticate(email=email, password=password):
raise forms.ValidationError('Invalid login')
and put it inside the view function for login:
def login_screen_view(request):
context = {}
if request.POST:
form = LoginForm(request.POST)
if form.is_valid():
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user:
login(request, user)
return redirect('home')
else:
form = LoginForm()
context['login_form'] = form
return render(request, 'account/login.html', context)
So that the above two blocks of code becomes now this:
class LoginForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
class Meta:
model = Account
fields = ['email', 'password']
def login_screen_view(request):
context = {}
if request.POST:
form = LoginForm(request.POST)
if form.is_valid():
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user:
login(request, user)
return redirect('home')
else:
raise forms.ValidationError('Invalid login') #i added this line
else:
form = LoginForm()
context['login_form'] = form
return render(request, 'account/login.html', context)
The reason why I say all this is because in the def clean(self) method aren't you basically checking if the form is valid? We also check if the form is valid in the view as well. So why repeat the logic? Then if we cannot authenticate the user we raise a ValidationError which I think can be added in the view definition.

How can I replace the forms with my serializer in django

Model.py
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,default='')
# user = models.OneToOneField(User, on_delete=models.CASCADE)
phone_no = models.CharField(max_length=13,unique=True)
registered = models.BooleanField(default=False)
spam = models.BooleanField(default=False)
def __str__(self):
return self.user.username
Serializer.py
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField()
class Meta():
model = User
fields = ('username','email','password')
class UserProfileSerializer(serializers.ModelSerializer):
class Meta():
model = UserProfileInfo
fields = ('phone_no',)
views.py
def register(request):
registered = False
if request.method == 'POST':
user_serializer = UserSerializer(data=request.POST)
profile_serializer = UserProfileSerializer(data=request.POST)
if user_serializer.is_valid() and profile_serializer.is_valid():
user = user_serializer.save()
user.set_password(user.password) #saving hash value of password
user.save()
profile = profile_serializer.save(commit=False)
profile.user = user
profile.registered = True
profile.save()
registered = True
else:
print(user_serializer.errors)
else:
user_serializer = UserSerializer
profile_serializer = UserProfileSerializer
return Response(request,'basic_app/registration.html',{
'user_serializer':user_serializer,
'profile_form':profile_form,
'registered':registered
})
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
print(username,password)
user = authenticate(username=username, password=password)
print(user)
if user:
if user.is_active:
login(request,user)
return render(request,'basic_app/search.html')
else:
return HttpResponse('Account not active!')
else:
# print(username,password)
return HttpResponse('Login credentials not correct!')
else:
return render(request,'basic_app/login.html')
Now I need to make changes to my views.py such that I can parallely populate the user and the profile model having one to one field. I was using the form which was working well but now I need to convert the code to rest API. Please help how I can keep the same functionality using the above serializer class. My aim is to register and login the user.
First, c method in the serializer like my simple code:
(I used to write this class in my REST project for register student)
class StudentRegistrationSerializer(serializers.ModelSerializer):
password = serializers.CharField(style={'input_type': 'password'}, required=True)
password2 = serializers.CharField(style={'input_type': 'password'}, required=True)
class Meta:
model = Student
fields = ['phone_number', 'password', 'password2', 'name', 'family']
extra_kwargs = {
'password': {'write_only': True}
}
def save(self, **kwargs):
phone_number = self.validated_data.get('phone_number')
name = self.validated_data.get('name')
family = self.validated_data.get('family')
password = self.validated_data.get('password')
password2 = self.validated_data.get('password2')
not_active = User.objects.filter(username=phone_number, is_active=False)
is_active = User.objects.filter(username=phone_number, is_active=True)
if password != password2:
raise serializers.ValidationError({'error': 'password not matched'})
if is_active:
raise serializers.ValidationError({'error': 'username already exist'})
if not_active:
raise serializers.ValidationError({'error': 'username already exist active your account'})
user = User(username=phone_number, password=password, is_active=False)
user.set_password(password)
user.save()
student = Student(phone_number=phone_number, user=user, name=name, family=family)
student.save()
return student
and return the saved object here is student
and I recommend you to use build-in LoginView in the third-party library like "rest_auth" this library handles Token
after installing "rest_auth" using :
pip install django-rest-auth
in the url file just import :
from rest_auth.views import LoginView
and use it without any complexity

Django - How to create a user-owned group when registering?

I'm using Django. User registration form contains fields such as username, e-mail, password. I want the user to create their own group when registering. How do I add this field?
forms.py
class RegisterForm(forms.ModelForm):
username = forms.CharField(max_length=100, label='Kullanıcı Adı')
email = forms.EmailField(max_length=200, help_text='Required')
password1 = forms.CharField(max_length=100, label='Parola', widget=forms.PasswordInput)
password2 = forms.CharField(max_length=100, label='Parola Doğrulama', widget=forms.PasswordInput)
class Meta:
model = User
fields = [
'username',
'email',
'password1',
'password2',
]
def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Parolalar eşleşmiyor!")
return password2
def clean_email(self):
email = self.cleaned_data.get('email')
lenghtw = len(User.objects.filter(email=email))
if lenghtw > 0 :
raise forms.ValidationError('Bu email adresine sahip bir kullanıcı zaten var.')
return email
views.py
def register_view(request):
form = RegisterForm(request.POST or None)
if form.is_valid():
user = form.save(commit=False)
password = form.cleaned_data.get('password1')
user.set_password(password)
#user.is_staff = user.is_superuser = True
user.save()
new_user = authenticate(username=user.username, password=password)
login(request, new_user)
return redirect('home')
return render(request, 'accounts/form.html', {'form': form, 'title': 'Üye Ol'})
The screenshot OP gave as a comment is more explicit than his/her question, which should be edited :-)
As a summary:
thanks to a view + form, you want to create a new user and a new group (Grup Name field),
when your user is created, you want your user to automatically belong to your new group.
A few issues I see in your approach:
you are coding a form which already exists in Django (UserCreationForm from django.contrib.auth.forms), with unnecessary checks (as for password validation: it has already been done by Django),
your field Grup name is not in your form by the way, did you forget it?
your user needs to be saved to database already, so it can have a pk and be added to a group.
We could also use signals to do so, but let's go with your own approach:
# forms.py
from django.contrib.auth.forms import UserCreationForm
class RegisterForm(UserCreationForm):
new_group_name = forms.CharField(max_length=100, label='Grup Name')
def clean_new_group_name(self):
# if you need to check the name of the group name
[...]
# views.py
def register_view(request):
form = RegisterForm(request.POST or None)
if form.is_valid():
user = form.save() # <--- ! don't use commit=False here
password = form.cleaned_data.get('password1')
new_group_name = form.cleaned_data['new_group_name']
new_group, created = Group.objects.update_or_create(name=new_group_name)
user.groups.add(Group.objects.get(name=new_group_name)
user.save()
new_user = authenticate(username=user.username, password=password)
login(request, new_user)
return redirect('home')
return render(request, 'accounts/form.html', {'form': form, 'title': 'Üye Ol'}
Could you try if that works for you?

Categories

Resources