custmized my Users model and create a sign up form, but cannot find password2 in cleaned_data
Models.py
class Users(AbstractUser):
bio = models.TextField(verbose_name="Bio", null=True)
form:
class MyUserCreationForm(UserCreationForm):
class Meta:
model=models.Users
fields = ("username",)
views.py:
class UserCreation(View):
def get(self,request):
content=homeforms.MyUserCreationForm()
return render(request,'user_create.html',{'form':content})
def post(self,request):
result = homeforms.MyUserCreationForm(data=request.POST)
if result.is_valid():
result.save()
username=result.cleaned_data.get("username")
raw_password=result.cleaned_data.get('password1')
user=authenticate(username=username, password=raw_password)
login(request,user)
return redirect('/book/')
print( str(result.cleaned_data['password1'])+" and "+ str(request.POST.get('password2')))
return render(request, "user_create.html",{'form':result})
The result as below:
444 and : None
{'password_mismatch': 'The two password fields didn’t match.'}
I'm a beginner of Django. According to django documents said a clean_password2() function in UserCreationForm should be called when I run form.is_valid. Is something went wrong in that part? Thanks a lot!
class UserCreationForm(forms.ModelForm):
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise ValidationError(
self.error_messages["password_mismatch"],
code="password_mismatch",
)
return password2
Related
This my models.py file
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
class UserAccountManager(BaseUserManager):
def create_user(self, name, email, password, **other_fields):
if not email:
raise ValueError('Users must have an email adress')
email = self.normalize_email(email)
user = self.model(name=name, email=email, password=password)
user.set_password(password)
user.save()
return user
def create_superuser(self, name, email, password = None, **other_fields):
other_fields.setdefault('is_staff', True)
other_fields.setdefault('is_superuser', True)
other_fields.setdefault('is_active', True)
return self.create_user(name=name, email=email, password = password, is_superuser=True)
class UserAccount(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=355, unique=False)
is_superuser = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
objects = UserAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def __str__(self):
return str(self.id)
I have a foreign key on my comment model, I tested this on django admin and it works fine, but with my comment form, the foreign key isn't populating, i just get "null value in column "user_id" violates not-null constraint", I dont know what im doing wrong
class Comment(models.Model):
comment = models.CharField(max_length=250)
user = models.ForeignKey(UserAccount, on_delete=models.CASCADE)
def __str__(self):
return str(self.user.id)
serializers.py
from djoser.serializers import UserCreateSerializer
from django.contrib.auth import get_user_model
from rest_framework.serializers import ModelSerializer
from accounts.models import Comment
User = get_user_model()
class UserCreateSerializer(UserCreateSerializer):
class Meta(UserCreateSerializer.Meta):
model = User
fields = ('id', 'name', 'email', 'password')
I am reffering my foreign key user as a field, i'm not sure if that is correct.
class CommentSerializer(ModelSerializer):
class Meta:
model = Comment
fields=('id', 'comment', 'user')
viewsets.py
from rest_framework import viewsets
from . import models
from . import serializers
class CommentViewset(viewsets.ModelViewSet):
queryset = models.Comment.objects.all()
serializer_class = serializers.CommentSerializer
router.py
from accounts.viewsets import CommentViewset
from rest_framework import routers
router = routers.DefaultRouter()
router.register('comment', CommentViewset)
You need to add user_id field for writing in the serializer.
class CommentSerializer(ModelSerializer):
class Meta:
model = Comment
fields=('id', 'comment', 'user')
extra_kwargs = {
'user': { 'read_only': True }
}
def create(self, validated_data):
new_comment = Comment(**validated_data)
new_comment.user_id = self.context['request'].user.id
new_comment.save()
return new_comment
After I added user and date_added in the Photo models, when I add post from admin its throws me an error saying: str returned non-string (type Category), when I click on the addpost link in the home template its throw another error: 'tuple' object has no attribute 'name'. how can I solve that ?
the models.py:
from django.db import models
from cloudinary.models import CloudinaryField
from django.contrib.auth.models import User
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=100, null=False, blank=False)
def __str__(self):
return self.name
class Photo(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True,
blank=True)
image = CloudinaryField('image')
description = models.TextField(null=True)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.category
the view.py file:
def home(request):
category = request.GET.get('category')
if category == None:
photos = Photo.objects.all()
else:
photos = Photo.objects.filter(category__name=category)
categories = Category.objects.all()
context = {'categories': categories, 'photos': photos}
return render(request, 'home.html', {'categories': categories, 'photos': photos} )
def viewPhoto(request, pk):
photo = Photo.objects.get(id=pk)
return render(request, 'photo.html', {'phpto': photo})
class PostCreativeView(LoginRequiredMixin, CreateView):
model = Photo, Category
fields = ['description', 'image', 'category', 'name']
template_name = 'post_create.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super (PostCreativeView, self).form_valid(form)
Well it has to do with your category name and model you added into post create view.py and so you
have do something like this:
views.py
class PostCreativeView(LoginRequiredMixin, CreateView):
model = Photo
fields = ['description', 'image', 'category']
template_name = 'post_create.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super (PostCreativeView, self).form_valid(form)
#.......
# Models.py
class Photo(models.Model):
#>>>...
def __str__(self):
return str(self.category)
You should return the str(…) of the category, so:
class Photo(models.Model):
# …
def __str__(self):
return str(self.category)
I created AbstractBaseUser model and a BaseManager.
the model.py is given below
GENDER_CHOICES = (('M', 'Male'),('F', 'Female'))
class AccountManager(BaseUserManager):
def create_user(self,email,username,phone,gender,password=None,**extrafields):
if not email:
raise ValueError("email is needed")
if not username:
raise ValueError("uname is needed")
if not phone:
raise ValueError("Phone is needed")
if not gender:
raise ValueError("gender is needed")
user= self.model(
email=self.normalize_email(email),
username=username,
phone=phone,
gender=gender,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self,email,username,phone,gender,password,**extrafields):
user=self.create_user(
email=self.normalize_email(email),
password=password,
username=username,
phone=phone,
gender=gender,
)
user.is_admin=True
user.is_staff=True
user.is_superuser=True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
ACCTYPE = (
('Student', 'Student'),
('Staff', 'Staff')
)
email=models.EmailField(verbose_name='E-mail', max_length=30, unique=True)
username=models.CharField(verbose_name='Username', max_length=30, unique=True)
last_login=models.DateTimeField(verbose_name='Last Login', auto_now=True)
phone=models.CharField(verbose_name='Phone', max_length=50)
gender= models.CharField(choices=GENDER_CHOICES, max_length=128)
acctype = models.CharField(max_length=16, choices=ACCTYPE)
is_admin=models.BooleanField(default=False)
is_active=models.BooleanField(default=True)
is_staff=models.BooleanField(default=False)
is_superuser=models.BooleanField(default=False)
USERNAME_FIELD ='username'
REQUIRED_FIELDS=['email','phone','gender']
objects=AccountManager()
def __str__(self):
return self.username
def has_perm(self,perm,obj=None):
return self.is_admin
def has_module_perms(self, app_lebel):
return True
And I am also tried to extend this user model Into StudentAccnt and StaffAccnt.
class StudentAccnt(models.Model):
user=models.OneToOneField(Account,on_delete=models.CASCADE)
reg_number=models.CharField(verbose_name='Reg NO', max_length=10,unique=True)
class StaffAccnt(models.Model):
user=models.OneToOneField(Account,on_delete=models.CASCADE)
id_number=models.CharField(verbose_name='Id NO', max_length=10,unique=True)
I want to create user using UserRegistrarionForm and add to StudentAccnt and StaffAccnt tables by checking acctype.
how to do this??
Finally, I got a solution.
it can be created using signals
When I create views for this custom user registration form, it simultaneously creates a corresponding instance.
we need to import these
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.db import models
add this at end of the view
#receiver(post_save,sender=Account)
def create_usersaccnt(sender,instance,created,**kwrags):
if created and (instance.acctype=='Student'):
StudentAccnt.objects.create(user=instance)
elif created and (instance.acctype=='Staff'):
StaffAccnt.objects.create(user=instance)
#receiver(post_save,sender=Account)
def save_usersaccnt(sender,instance,created,**kwrags):
if instance.acctype=='Student':
instance.studentaccnt.save()
elif instance.acctype=='Staff':
instance.staffaccnt.save()
you can also specify it through additional python file called signals.py
Is there a way to stop a model in django allowing an empty model to be saved?
e.g. I have a simple contact form
class Contact(models.Model):
alphabetical = RegexValidator(r'^[a-zA-Z]*$', 'Only alphabetical characters
are allowed', 'Invalid input')
name = models.CharField(max_length=200, validators=[alphabetical])
email = models.EmailField(validators=[EmailValidator, ])
subject = models.CharField(max_length=200)
message = models.CharField(max_length=250)
created_date = models.DateTimeField(auto_now_add=True)
How can I prevent an empty model being saved? e.g. in the django shell I can do
contact = Contact()
contact.save()
This gives a model with all blank values saved.
for validation you have to use django.forms. django forms will manage the validation part:
for eg: if your model.py is:
class Contact(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
subject = models.CharField(max_length=200)
message = models.CharField(max_length=250)
created_date = models.DateTimeField(auto_now_add=True)
now create a view in views.py :
from django.forms import modelformset_factory
from django.shortcuts import render
from myapp.models import Contact
def manage_contacts(request):
ContactFormSet = modelformset_factory(Contact, fields=('name', 'email', 'subject', 'message'))
if request.method == 'POST':
formset = ContactFormSet(request.POST)
if formset.is_valid(): # check the validation for blank fields
formset.save()
# do something.
else:
formset = ContactFormSet()
return render(request, 'manage_contacts.html', {'formset': formset})
create a template in templates/manage_contacts.html:
<form method="post">
{{ formset }}
</form>
I need to add a custom field called phone_number to the default django user table
Everything work fine but the phone_number field and value does not save in Table Django User.
Here is my custom form code
class SignUpForm(UserCreationForm):
username = forms.EmailField(label="Email Address", max_length=254, help_text='Required a valid email address.')
phone_number = forms.CharField(max_length=30, help_text='Required.')
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'phone_number', 'password1', 'password2')
Here is my view code for user registration
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.is_active = False
user.save()
current_site = get_current_site(request)
mail_subject = 'Activate Your Account.'
message = render_to_string('app/account_activation_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'token': account_activation_token.make_token(user),
})
to_email = form.cleaned_data.get('username')
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()
return render(request, 'app/account_confirm_message.html')
else:
form = SignUpForm()
return render(request, 'app/signup.html', {'form': form})
My Model is here
class Profile(models.Model):
STUDENT = 1
TEACHER = 2
ROLE_CHOICES = (
(STUDENT, 'Student'),
(TEACHER, 'Teacher'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
email_confirmed = models.BooleanField(default=False)
role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, null=True, blank=True)
# this method called for admin panel
class Meta:
verbose_name = 'profile'
verbose_name_plural = 'profiles'
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()