Search code examples
pythonhtmldjangodjango-viewsuser-registration

AttributeError: 'NoneType' object has no attribute 'save' python-django


I have a User model. when I go to the signup page and add user details. it gives an error " AttributeError: 'NoneType' object has no attribute 'save' " when I reload the error page it gives another error " UNIQUE constraint failed: accounts_user.username "

Here is my models.py

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
from django.utils import timezone

# Create Your Models Here.

class UserManager(BaseUserManager):

    def _create_user(self, username, password, is_staff, is_superuser, **extra_fields):
        if not username:
            raise ValueError('Users must have an username address')
        now = timezone.now()
        username = self.model.normalize_username(username) 
        user = self.model(
            username=username,
            is_staff=is_staff,
            is_active=True,
            is_superuser=is_superuser,
            last_login=now,
            date_joined=now,
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, username=None, password=None, **extra_fields):
        return self._create_user(username, password, False, False, **extra_fields)

    def create_superuser(self, username, password, **extra_fields):
        user = self._create_user(username, password, True, True, **extra_fields)
        user.save(using=self._db)
        return user


class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=254, unique=True)
    name = models.CharField(max_length=254, null=True, blank=True)
    email = models.EmailField(max_length=254, null=True, blank=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)

    USERNAME_FIELD = 'username'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def get_absolute_url(self):
        return "/users/%i/" % (self.pk)
    def get_username(self):
        return self.username


class user_type(models.Model):
    is_service = models.BooleanField(default=False)
    is_customer = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)

    user = models.OneToOneField(User, on_delete=models.CASCADE)

    def __str__(self):
        if self.is_customer == True:
            return User.get_username(self.user) + " - is_customer"

        if self.is_admin == True:
            return User.get_username(self.user) + " - is_admin"            

        if self.is_service == True:
            return User.get_username(self.user) + " - is_service"

Here is my views.py

from .models import user_type
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from .models import user_type, User
from django.contrib.auth import login as auth_login
from django.contrib.auth import authenticate, login as dj_login
from django.contrib.auth.decorators import login_required

# Create your views here.


def signup(request):
    if (request.method == 'POST'):
        name = request.POST.get('name')
        username = request.POST.get('username')
        email = request.POST.get('email')
        password = request.POST.get('password')
        service = request.POST.get('service')
        customer = request.POST.get('customer')
        admin = request.POST.get('admin')
        
        user = User.objects.create_user(
            name = name, username = username, email = email
        )
        user.set_password(password)
        user.save()

        usert = None
        if service:
            usert = user_type(user=user,is_service=True)
        elif customer:
            usert = user_type(user=user,is_customer=True)
        elif admin :
            usert = user_type(user=user, is_admin=True)
        
        usert.save()
        #Successfully registered. Redirect to homepage
        return redirect('/')
    return render(request, 'registration/register.html')



Here is registration/register.html

{% extends 'adminpanel/base.html' %}

{% block content %}





    <!-- Content Wrapper. Contains page content -->
  <div class="content-wrapper">
    <!-- Content Header (Page header) -->
    <section class="content-header">
      <div class="container-fluid">
        <div class="row mb-2">
          <div class="col-sm-6">
            <h1>Validation</h1>
          </div>
          <div class="col-sm-6">
            <ol class="breadcrumb float-sm-right">
              <li class="breadcrumb-item"><a href="#">Home</a></li>
              <li class="breadcrumb-item active">Validation</li>
            </ol>
          </div>
        </div>
      </div><!-- /.container-fluid -->
    </section>

    <!-- Main content -->
    <section class="content">
      <div class="container-fluid">
        <div class="row">
          <!-- left column -->
          <div class="col-md-12">
            <!-- jquery validation -->
            <div class="card card-primary">
              <div class="card-header">
                <h3 class="card-title">Create Users</h3>
              </div>
              <!-- /.card-header -->
              <!-- form start -->
              <form method ="POST" role="form" id="quickForm">
                {% csrf_token %} 
                <div class="card-body">
                  <div class="form-group">
                    <label for="name">Name</label>
                    <input type="text" name="name" class="form-control" id="exampleInputName" placeholder="Enter Your Name">
                  </div>
                  <div class="form-group">
                    <label for="exampleInputusername">Username </label>
                    <input type="text" name="username" class="form-control" id="exampleInputusername" placeholder="Enter Username">
                  </div>
                  <div class="form-group">
                    <label for="exampleInputEmail1">Email </label>
                    <input type="text" name="email" class="form-control" id="exampleInputEmail1" placeholder="Enter Email">
                  </div>
                  <div class="form-group">
                    <label for="exampleInputPassword">Password</label>
                    <input type="password" name="password" class="form-control" id="exampleInputPassword" placeholder="Enter Password">
                  </div>
                  
                  
                  <div>
                     <label for="role">Role :</label>
                            <select id="cars" name="cars">
                                <option name='service'>Service Provider</option>
                                <option name='customer'>Customer</option>
                                <option name='admin'>Admin</option>

                             </select>
                        </div>    
                </div>
                <!-- /.card-body -->
                <div class="card-footer">
                  <button type="submit" class="btn btn-primary">Submit</button>
                </div>
              </form>
            </div>
            <!-- /.card -->
            </div>
          <!--/.col (left) -->
          <!-- right column -->
          
          <!--/.col (right) -->
        </div>
        <!-- /.row -->
      </div><!-- /.container-fluid -->
    </section>
    <!-- /.content -->
  

{% endblock %}

Solution

  • The problem is how you check for the user roles. You are trying to get the different values as different form names submitted, but in your HTML form, they are submitted as values for the cars field, so you would need to do something like:

    service = request.POST.get('cars') == 'service'
    customer = request.POST.get('cars') == 'customer'
    admin = request.POST.get('cars') == 'admin'
    

    Anyway, I would recommend you to have a look at Django Forms, and use them instead of manually creating your form in HTML and manually getting field values, as this is prone to errors like the one you are having. You can use a ChoiceField for your different roles, and make the code more readable in general.