I am unable to create a new custom user in Django - django

I tried creating a new user but it didn't work, I have tried debugging it but don't get a way about this. I have a User Model but want to try and create different user types like students, teachers something like that which would all be in the user user model as well as their various user models.
View.py
def AddCustomerManager(request):
if request.method == "POST":
email = request.POST.get('email')
username = request.POST.get('username')
password = request.POST.get('password')
try:
user = User.objects.create_user(email=email, username=username, password=password, user_type=2)
user.save()
messages.success(request, "Customer Manager Added Successfully")
except:
messages.error(request, "Failed to Add Customer Manager")
return render(request, "pusheat_admin/addcm.html")
models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
user_type_choice = ((1, "SuperUser"), (2, "CustomerManager"))
user_type = models.CharField(default=1, choices=user_type_choice, max_length=10)
objects = UserManager()
class CustomerManager(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
fullname = models.CharField(max_length=50, blank=False)
email = models.EmailField()
password = models.CharField(max_length=32)
addcm.html
<form role="form" method="POST">
{% csrf_token %}
<div class="card-header"><h4>Add Customer Manager</h4></div>
<div class="card-body">
<div class="form-group">
<label>Email address</label>
<input type="email" class="form-control" name="email" placeholder="Enter email">
</div>
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" name="username" placeholder="Username">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" name="password" placeholder="Password">
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary">Add Customer Manager</button>
</div>
</form>

Change this line in models.py:
user_type = models.CharField(default=1, choices=user_type_choice, max_length=10)
to:
user_type = models.PositiveSmallIntegerField(default=1, choices=user_type_choice, max_length=10)

Related

Django authenticate user does not work after logging in

I'm trying to create a custom session-based login in Django using a custom user model and a custom login template.
For some reasons it worked at first but now the authenticate method from django.contrib.auth is not authenticating user. When it did work, the login and signup button were hidden.
users/urls.py
app_name = 'users'
urlpatterns = [
path('login/', login_user, name='login_user'),
path('logout/', logout_user, name='logout_user'),
]
users/views.py
app_name = 'users'
def login_user(request):
django_logout(request)
message = ''
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
user = authenticate(request, email=email, password=password)
if user is not None:
django_login(request, user)
return redirect('homepage')
else:
message = "Log in failed!"
messages.error(request, message)
return redirect('users:login_user')
else:
return render(request, 'users/login.html')
#login_required(login_url='users/login/')
def logout_user(request):
django_logout(request)
templates/users/login.html
<form class="bg-white rounded-5 shadow-5-strong p-5" method="post" action="/">
{% csrf_token %}
<!-- Email input -->
<div class="form-outline mb-4">
<label class="form-label" for="form1Example1">Email address</label>
<input type="email" name="email" id="form1Example1" class="form-control" />
</div>
<!-- Password input -->
<div class="form-outline mb-4">
<label class="form-label" for="form1Example2">Password</label>
<input type="password" type="password" id="form1Example2" class="form-control" />
</div>
<!-- Submit button -->
<button type="submit" class="btn btn-primary btn-block">Sign in</button>
</form>
users/models.py
class CustomUserManager(BaseUserManager):
def create_superuser(self, email, password):
if email is None:
raise TypeError('Users should have an Email')
if password is None:
raise TypeError('Password should not be none')
user = self.create_user(email, password)
user.is_superuser = True
user.is_staff = True
if user.is_superuser is not True:
raise ValueError(
'Superuser must be assigned to is_staff=True.')
if user.is_staff is not True:
raise ValueError(
'Superuser must be assigned to is_superuser=True.')
user.save()
return user
def create_user(self, email, password):
if email is None:
raise TypeError('Users should have an Email')
if password is None:
raise TypeError('Users must have a password')
email = self.normalize_email(email)
user = self.model(email=email)
user.set_password(password)
user.save()
return user
AUTH_PROVIDERS = {'facebook': 'facebook', 'google': 'google',
'twitter': 'twitter', 'email': 'email'}
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True, db_index=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
about = models.TextField(_(
'about'), max_length=500, blank=True)
auth_provider = models.CharField(
max_length=255, blank=False,
null=False, default=AUTH_PROVIDERS.get('email'))
USERNAME_FIELD = 'email'
objects = CustomUserManager()
def __str__(self):
return self.email
My sign in button in homepage.html
<a href="{% url 'users:login_user' %}">
<button type="button" class="btn btn-link px-3 me-2">
Login
</button>
</a>
Could you show me the way to solve this? Thank you!
Change your form like this
<form class="bg-white rounded-5 shadow-5-strong p-5" method="post" action="{% url 'users:login_user' %}">
{% csrf_token %}
<!-- Email input -->
<div class="form-outline mb-4">
<label class="form-label" for="form1Example1">Email address</label>
<input type="email" name="email" id="form1Example1" class="form-control" />
</div>
<!-- Password input -->
<div class="form-outline mb-4">
<label class="form-label" for="form1Example2">Password</label>
<input type="password" name="password" type="password" id="form1Example2" class="form-control" />
</div>
<!-- Submit button -->
<button type="submit" class="btn btn-primary btn-block">Sign in</button>
</form>
MultiValueDictKeyError at /users/login/ 'password'
this is because you're trying to access password value from request like this request.POST['password'] but you've not set name to your input(password) that's why it is giving you an error

Using Dropdown values to set user ranks on creation

I have a user creation form in my Django web application. I am able to create a user normally.
I have a model in my application called user_type, which has the is_admin field, is_manager field and the user field linked to the User Foreign Key. I have added a dropdown in my user creation form to enable the Admin create a user and as well assign the user_type of the user using the dropdown.
I am now confused of how to grab the admin choice and enable the user_type depending on that.
models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
# CUSTOM USER FIELDS
firstname = models.CharField(max_length=30, blank=True, null=True)
lastname = models.CharField(max_length=30, blank=True, null=True)
telephone = models.IntegerField(blank=True, null=True)
address = models.CharField(max_length=300)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
updated_at = models.DateTimeField(auto_now=True, blank=True, null=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
class user_type(models.Model):
is_admin = models.BooleanField(default=False)
is_manager = models.BooleanField(default=False)
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
if self.is_manager == True:
return User.get_email(self.user) + " - is_manager"
else:
return User.get_email(self.user) + " - is_admin"
views.py
def AddUser(request):
if request.method == "POST":
email = request.POST.get('email')
telephone = request.POST.get('telephone')
firstname = request.POST.get('firstname')
lastname = request.POST.get('lastname')
address = request.POST.get('address')
zipcode = request.POST.get('zipcode')
city = request.POST.get('city')
region = request.POST.get('region')
country = request.POST.get('country')
password = User.objects.make_random_password()
# is_manager = request.POST.get('is_manager')
try:
user = User.objects.create_user(email=email, telephone=telephone, firstname=firstname, password=password,
lastname=lastname, address=address, zipcode=zipcode, city=city, country=country)
user.send_welcome_mail(new_password)
# if is_manager == True:
# user.user_type.is_manager == True
# else:
# user.user_type.is_admin == True
user.save()
messages.success(request, "User Created Successfully!")
return redirect('users')
except Exception as e:
messages.error(request, "Failed to Create User!" + str(e))
return redirect('users')
return render(request, "core/adduser.html")
adduser.html
<form method="POST">
{% csrf_token %}
<div class="row">
<div class="col-md-6 col-sm-12">
<div class="form-group">
<input type="text" name="email" placeholder="Email Address" class="form-control">
</div>
</div>
<div class="col-md-6 col-sm-12">
<div class="form-group">
<input type="text" name="telephone" placeholder="Telephone" class="form-control">
</div>
</div>
<div class="col-md-4 col-sm-12">
<div class="form-group">
<input type="text" name="firstname" placeholder="Firstname" class="form-control">
</div>
</div>
<div class="col-md-4 col-sm-12">
<div class="form-group">
<input type="text" name="lastname" placeholder="Lastname" class="form-control">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<select class="custom-select2 form-control" name="user_type" style="width: 100%; height: 38px;">
<optgroup label="Select User Type">
<option value="M" name="is_manager">Manager</option>
<option value="A" name="is_admin">Admin</option>
</optgroup>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-sm-12">
<div class="form-group">
<textarea name="address" placeholder="Address" class="form-control"></textarea>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Create User</button>
</form>
Few changes to code style before explaining:
Rename user_type to UserType as it is suggested in Django Models.
Rename the view AddUser to add_user as it is suggested in PEP8 for function names.
In your add_user view:
if request.method == "POST":
# ...get your fields from the form
user_type = request.POST.get("user_type")
# ...create your user here
# assign default values first
is_admin = False
is_manager = False
# parse value from the form input
if user_type == "M":
is_manager = True
elif user_type == "A":
is_admin = True
# now create 1-to-1 field
user_type = UserType.objects.create(
user=user, is_admin=is_admin, is_manager=is_manager
)
Few more suggestions:
It is better to use user = User.objects.get(email=email) first to check if that user exists and handle that scenario. .get() function will give User.DoesNotExist exeption, handle that one for creating the user. Try to avoid generic Exception class as much as it is possible.
Use a Model Form for checking the input from the client, it will make sure that your inputs are good for the model requirements like required fields, field lengths and etc. before even trying to create that model.

How to save a foreignkey field while saving a HTML form in Django?

I want to save a html form data into django model but it has a foreign key field from another model. How can I save a form which has FK field??
My models:
class Dish(models.Model):
title =models.CharField(max_length=200)
description =models.TextField(blank=True)
price =models.IntegerField()
photo_main= models.ImageField(upload_to="photos/%Y%m%d/")
photo_1= models.ImageField(upload_to="photos/%Y%m%d/", blank= True)
photo_2= models.ImageField(upload_to="photos/%Y%m%d/", blank= True)
def __str__(self):
return self.title
class Order(models.Model):
dishorder= models.ForeignKey(Dish,null=True,on_delete=models.CASCADE)
name = models.CharField(max_length=200,blank=True)
email = models.CharField(max_length=100,blank=True)
phone = models.CharField(max_length=100,blank=True)
quantity =models.IntegerField(blank=True)
def __str__(self):
return self.name
My views:
def order(request):
if request.method == 'POST':
name = request.POST['name']
email = request.POST['email']
phone = request.POST['phone']
quantity = request.POST['quantity']
order= Order(
name=name,
email=email,
phone=phone,
quantity=quantity)
order.save()
messages.success(request, "Your order has been submitted.")
return render(request,"dishes/order.html")
My urls:
urlpatterns = [
path("dish",views.dish,name="dish"),
path("dish/<pk>",views.dishsingle,name="dishsingle"),
path("order",views.order,name="order"),
]
My template dishes/order.html
<form method="POST">
{% csrf_token %}
<div>
<label for="name">Name:</label>
<input type="text" name="name" class="form-control" required>
</div>
<div>
<label for="email">Email:</label>
<input type="email" name="email" class="form-control" required>
</div>
<div>
<label for="phone">Phone:</label>
<input type="number" name="phone" class="form-control" required>
</div>
<div>
<label for="quantity">Quantity:</label>
<input type="number" name="quantity" class="form-control" required>
</div>
<hr>
<input type="submit" value="MAKE AN ORDER">
</form>
While submitting this html form, I would like the foreignkey field dishorder to be saved on the backend as well. When I check the admin page, order is saved but without the name of the dish. How can I resolve this?

How to set image field as optional?

How to set image field as optional? I am trying to set image field as optional(None or selected). Image field is None its throwing "MultiValueDictKeyError" when submit the form. I want to make this image field as None.
models.py
class Profile(models.Model):
first_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255, blank=True, null=True)
image = models.ImageField(upload_to='images', blank=True, null=True)
forms.py
class Meta:
model = Profile
fields = '__all__'
views.py
def profile(request):
if request.method == 'POST':
form = ProfileForm(request.POST)
if form.is_valid:
first_name = request.POST.get('first_name')
last_name = request.POST.get('last_name')
image = request.FILES['images']
file_storage = FileSystemStorage()
obj = Profile(first_name=first_name, last_name=last_name, image=file_storage.save(image.name, image))
return render(request, 'index.html',{})
return render(request, 'index.html',{})
return render(request, 'index.html',{})
index.html
<form action="#" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="text" name="first_name" class="form-control form-control" id="fname">
<input type="text" name="last_name" class="form-control form-control" id="lname">
<input type="file" name="images" class="form-control" id="image">
<button type="submit" class="btn btn-primary mt-5 mb-5">Save</button>
</form>
use the same method you're using in the other fields:
image = request.FILES.get('images')
this will make image = None if it doesn't exist in the request. then:
image_saved = None
if image is not None:
image_saved = FileSystemStorage().save(image.name, image)
obj = Profile(first_name=first_name, last_name=last_name, image=image_saved)

Django custom form registration TypeError at /accounts/register register() missing 1 required positional argument: 'username'

ImproperlyConfigured at /accounts/register
Could not create directory for saving email messages: /home/user/Desktop/emails ([Errno 13] Permission denied: '/home/user')
It points to this line "user.email_user(subject, message, html_message=message)" in views.register in account.
auth.html
<form id='registration-form' method='post' action={% url 'accounts:register' %}>
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control input-upper" id="fullname" placeholder="John Doe" name="fullname" required><br>
<input type="text" class="form-control input-upper" id="username" placeholder="Username" name="username"><br>
<input type="email" class="form-control input-upper" id="email" placeholder="Email" name="email" required><br>
<input type="text" class="form-control input-upper" id="organization" placeholder="Organization" name="organization" required><br>
<input type="password" class="form-control input-upper" id="password" placeholder="Password" name="password1" required><br>
<input type="password" class="form-control input-upper" id="password" placeholder="Confirm Password" name="password2" required><br>
<small>By registering you agree to our terms and conditions</small>
<button type="submit" value='register' id='reg-submit-btn' class="btn btn-primary btn-block btn-signup-form">SIGN UP</button>
<button type="button" class="btn btn-primary btn-block btn-sign-linkedin" href="{% url 'social:begin' 'linkedin-oauth2' %}?next={{ next }}">Sign up with LinkedIn</button>
<p class="text-already">Already have an account? <a href="" >LOGIN</a></p>
</div>
</form>
MOdel Userprofile.py
class UserProfile(models.Model):
""" Profile for the User Model """
user = models.OneToOneField(
User, on_delete=models.CASCADE,
related_name='profile',
verbose_name='other Details',
)
phone = models.CharField(max_length=11, default='', blank=True, null=True)
organization = models.CharField(default='', max_length=300, blank=True)
referral = models.OneToOneField(
Referral, on_delete=models.CASCADE,
related_name='profile', verbose_name='profile Details',
null=True)
email_confirmed = models.BooleanField(default=False)
def __str__(self):
return self.user.username + '\'s profile'
def activate(self):
"""" Activates account after email is confirmed """
self.email_confirmed = True
self.user.is_active = True
self.save()
self.user.save()
Views.py
#transaction.atomic
def register(request):
"""Process registration of new users"""
if request.user.is_authenticated:
return JsonResponse({'status': 'loggedin'})
status = dict()
status['status'] = 'failure'
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
# Save Profile details
user = form.save()
current_site = get_current_site(request)
subject = 'DHIS2 Account Activation'
message = render_to_string(
'registration/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),
},
request=request)
user.email_user(subject, message, html_message=message)
Referral.record_response(request, "REGISTERED")
#return JsonResponse({'status': 'success'})
return redirect('accounts:account_activation_sent')
status = form.errors
status['status'] = 'failure'
return JsonResponse(status)
I get a json response of status:Failure, and password1: "This field is required." and password2:"This field is required.
What could I be doing wrong? Probably the template doesn't save or something. How do i make a custom django form that makes use of the html template.
You don't have fields with names password1 and password2 in your template; you just have two fields named password. You need to give them the correct name attributes.