Django form initial value changes after save - django

I use a custom form inherited from django's UserCreationForm to add user. How ever i have to set different initial value for username field.It works perfectly but after hitting save button the user get saved with a different username than the initial value shown in the form.You can find the code below
from django.contrib.auth.forms import UserCreationForm
class AdminUserCreationForm(UserCreationForm):
"""
AdminForm for creating an instance of custom USER_MODEL.
"""
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email")
field_classes = {'username': UsernameField}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.initial['username'] = random_username_generator()
self.fields['username'].disabled = True
self.fields['password1'].required = False
self.fields['password2'].required = False
def clean_username(self):
username = self.cleaned_data['username'].lower()
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError('A user with username {} already exists'.format(username))
def clean_email(self):
email = self.cleaned_data['email'].lower()
try:
User.objects.get(email=email)
except User.DoesNotExist:
return email
raise forms.ValidationError('A user with email {} already exists'.format(email))
def save(self, commit=True):
import ipdb; ipdb.set_trace();
user = super(AdminUserCreationForm, self).save(commit=False)
# user = self.instance
qb = QuickBlox()
qb_password = reset_password_generator()
user.qb_password = qb_password + 'vx'
user.save()
attempt = LoginAttempts()
attempt.user = user
attempt.save()
send_invite_mail(user)
return user

Related

Drf how to: simple-jwt authenticating without the USERNAME_FIELD

I have extended the TokenObtainPairSerializer, my user model has the email as the USERNAME_FIELD but this type of user does not have an email instead I want to use an auto-generated unique id to authenticate in place of the email.
class MyTokenStudentSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
user = authenticate()(
student_id=attrs['student_id'], password=attrs['password'])
if user is not None:
if user.is_active:
data = super().validate(attrs)
refresh = self.get_token(self.user)
refresh['student_id'] = self.user.student_id
try:
data["refresh"] = str(refresh)
data["access"] = str(refresh.access_token)
data['student_id'] = self.user.student_id
data['firstname'] = self.user.firstname
data['middlename'] = self.user.middlename
data['lastname'] = self.user.lastname
data['phone'] = self.user.phone
data['last_login'] = self.user.last_login
data['joined_date'] = self.user.joined_date
except Exception as e:
raise serializers.ValidationError(
{'error': 'Something Wrong!'})
return data
else:
raise serializers.ValidationError(
{'error': 'Account is not activated'})
else:
raise serializers.ValidationError({
'error': 'Incorrect student id and password combination!'})
even tho i don't pass an email field this takes email and password, how do i get it to take the student_id instead of the email.
You can override the username_field as follows:
Also be careful of using PasswordField, which trims whitespace by default. You definitely do not want password to be valid.
from rest_framework import serializers
rest_framework_simplejwt.serializers import PasswordField
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class MyTokenStudentSerializer(TokenObtainPairSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['student_id'] = serializers.CharField(required=False)
self.fields['password'] = PasswordField(trim_whitespace=False)
username_field = 'student_id'
auth_fields = ['student_id']

Prevent form refresh on validation error django

I have a RegisterForm that inherits from ModelForm with RegisterView that inherits from FormView. If every field data is valid, the user gets successfully created and is redirected to login page. But if there is a validation error, it shows the field error below that field and the form gets refreshed and all the fields data is lost. How to avoid form refreshing so that user need not to fill the details again and again.
forms.py
class RegisterForm(forms.ModelForm, PasswordValidatorMixin):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField( label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = UserModel
fields = (
'first_name',
'last_name',
'username',
'password1',
'password2',
'current_email',
)
def __init__(self, social_email=None, social_fname=None, social_lname=None,
social_uname=None,*args, **kwargs):
super(RegisterForm, self).__init__(*args, **kwargs)
self.current_email = None
self.social_email = social_email
self.social_fname = social_fname
self.social_lname = social_lname
self.social_uname = social_uname
def clean(self, *args, **kwargs):
username = self.cleaned_data.get('username')
self.current_email = self.cleaned_data.get('current_email')
if self.social_email:
self.current_email = self.social_email
if not username:
raise forms.ValidationError({"username":"Username can't be empty"})
if not self.current_email:
raise forms.ValidationError({"current_email":"Email can't be empty"})
qs = UserModel.objects.filter(username=username)
qs_email = UserModel.objects.filter(current_email=self.current_email)
if qs.exists():
raise forms.ValidationError({"username":"Username is already taken"})
if qs_email.exists():
raise forms.ValidationError({"current_email":"Email has already been registered"})
return self.cleaned_data
def save(self, commit=True):
user = super().save(commit=False)
current_email = self.cleaned_data.get('current_email')
password = self.cleaned_data.get('password1')
user.set_password(password)
if self.social_email:
user.is_active = True
user.save()
return user
views.py
class RegisterView(ContextMixin, FormView):
form_class = RegisterForm
template_name = 'accounts/register.html'
title = 'Register'
#method_decorator(sensitive_post_parameters('password'))
#method_decorator(csrf_protect)
#method_decorator(never_cache)
def dispatch(self, *args, **kwargs):
self.kwargs['social_email'] = SOCIAL_USER_EMAIL
self.kwargs['social_fname'] = SOCIAL_USER_FNAME
self.kwargs['social_lname'] = SOCIAL_USER_LNAME
if SOCIAL_USER_EMAIL:
self.kwargs['social_uname'] = SOCIAL_USER_EMAIL.split('#',1)[0]
return super(RegisterView, self).dispatch(*args, **kwargs)
# Passes view kwargs to html
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if SOCIAL_USER_EMAIL:
context['social_email'] = self.kwargs['social_email']
context['social_fname'] = self.kwargs['social_fname']
context['social_lname'] = self.kwargs['social_lname']
context['social_uname'] = self.kwargs['social_uname']
# context['social_image'] = SOCIAL_USER_IMAGE
return context
# Passes view kwargs to form
def get_form_kwargs(self):
kwargs = super(RegisterView, self).get_form_kwargs()
kwargs.update(self.kwargs)
return kwargs
def form_valid(self, form):
form.save()
if not self.kwargs['social_email']:
return render(self.request, 'accounts/success.html', {
'title':"You've registered successfully",
'body':"You've successfully registered at antef! Please verify the link sent at " +
form.current_email
})
return render(self.request, 'accounts/success.html', {
'title':"You've registered successfully",
'body':"You've successfully registered with your " + self.kwargs['social_email'] + " account."})
First, you don't need validation error for empty inputs, just add required = True in your forms.py or in your model.
Second you are not returning anything after validation error, which making your form empty after refresh.
You can also check email and username separately, for better use,
def clean_email(self):
email = self.cleaned_data.get('email')
if your_condition:
raise forms.ValidationError()
return email
def clean_username(self):
username = self.cleaned_data.get('username')
if your_condition
raise forms.ValidationError
return username

update password only if it is entered while updating user in Django admin

I have custom user in Django, so in user creation form in admin we have password field, and its getting saved while creation, but when I go to change existing user and I am not entering/changing password field , but it getting reflected in database. below is my code
class ChangeClientEmployeeMasterForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ChangeClientEmployeeMasterForm, self).__init__(*args, **kwargs)
self.fields['groups'].label='Roles'
if 'instance' in kwargs and hasattr(kwargs['instance'], 'client_employee_id'):
self.client_employee_id = kwargs['instance'].client_employee_id
def clean(self):
if self.cleaned_data['client_employee_type'] =='imast':
self.cleaned_data['is_superuser'] = True
else :
self.cleaned_data['is_superuser'] = False
return self.cleaned_data
def save(self, commit=True):
user = super(ChangeClientEmployeeMasterForm, self).save(commit=False)
password = self.cleaned_data["password"]
if password:
user.set_password(password)
if commit:
user.save()
return user
class Meta:
model = ClientEmployeeMaster
You try this option, I tried this in Django Admin 1.10. This should work.
def clean(self):
password = self.cleaned_data['password']
if not password and password =='':
del self.cleaned_data['password']
#Add your extra code / statement here, if you need.
return self.cleaned_data

Django - The additional fields from UserProfile don't save

I'm new with Django and Python... I'm trying to do my own registration form for add some additional fields (Following the docs about Profiles)... All fine when I test, but after save, the additional field don't save, without error, just don't save, only the User is created... but If I write manually some values on create_profile function, it's saved correct.. How I can pass fields from my UserCreateForms to create_profile routine?
Sorry for my english, and thanks for your help, I'm involved in a little project for learn and I'm stopped for this detail.. :S
Models
class UserProfile(models.Model):
user = models.OneToOneField(User)
cedula_de_identidad = models.CharField(max_length=9)
def create_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance, cedula_de_identidad='If I write here it's saved correctly')
post_save.connect(create_profile, sender=User)
Forms
class UserCreateForm(UserCreationForm):
email = forms.EmailField(required=True)
cedula_de_identidad = forms.CharField(required=True)
class Meta:
model = User
fields = ("email", "username", "password1", "password2")
def clean_username(self):
username = self.cleaned_data['username']
# if not re.search(r'^\w+$', username):
# raise forms.ValidationError('Username can contain only alphanumeric characters')
try:
User.objects.get(username=username)
except ObjectDoesNotExist:
return username
raise forms.ValidationError('Username is already taken')
def save(self, *args, **kwargs):
user = super(UserCreateForm, self).save(*args, **kwargs)
profile = UserProfile()
profile.user = user
profile.cedula_de_identidad = self.cleaned_data['cedula_de_identidad']
profile.save
return profile
Views
def nuevo_usuario(request):
if request.method == 'POST':
formulario = UserCreateForm(request.POST)
if formulario.is_valid():
formulario.save()
return HttpResponseRedirect('/')
else:
formulario = UserCreateForm()
return render_to_response('nuevousuario.html', {'formulario': formulario}, context_instance=RequestContext(request))
I'm using Python 2.7 and Django 1.4.. Regards,

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