John Rogerson
John Rogerson

Reputation: 1183

Django Integrity Error- Unique Constraint Failed

Trying to create a simple launch page for my website to collect email addresses. When the user goes to submit, it is providing the following error (traceback below)--Unique Constraint Failed---accounts.user.username. I figured maybe this has to do with the email address entered overlapping with username, but as you can see in my accounts model--the username is created from the email. (Note the entire User and User Profile models are not being utilized throughout my site yet, but just preparing for future usage). Any help is appreciated. Thanks

Traceback (most recent call last):
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\handlers\base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\crstu\PycharmProjects\dealmazing\dealmazing\views.py", line 15, in newsletter_signup
    instance.save()
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\contrib\auth\base_user.py", line 74, in save
    super(AbstractBaseUser, self).save(*args, **kwargs)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\base.py", line 708, in save
    force_update=force_update, update_fields=update_fields)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\base.py", line 736, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\base.py", line 820, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\base.py", line 859, in _do_insert
    using=using, raw=raw)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\manager.py", line 122, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\query.py", line 1039, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\sql\compiler.py", line 1060, in execute_sql
    cursor.execute(sql, params)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\backends\utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\utils.py", line 95, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\utils\six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Users\crstu\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\backends\sqlite3\base.py", line 323, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: accounts_user.username

my Accounts app model below:

from django.contrib.auth.models import (
    AbstractBaseUser,
    BaseUserManager,
    PermissionsMixin
)
from django.db import models
from django.utils import timezone
from django.conf import settings
from django.db.models.signals import post_save
import os


def avatar_upload_path(instance, filename):
    return os.path.join('avatars', 'user_{0}', '{1}').format(
        instance.user.id, filename)


class UserManager(BaseUserManager):
    def create_user(self, email, username=None, password=None):
        if not email:
            raise ValueError("Users must have an email address")

        if not username:
            username = email.split('@')[0]

        user = self.model(
            email=self.normalize_email(email),
            username=username,
        )
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email,
            username,
            password,
        )
        user.is_staff = True
        user.is_superuser = True
        user.save()
        return user


class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=40, unique=True, default='')
    date_joined = models.DateTimeField(default=timezone.now)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()

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

    def __str__(self):
        return "@{}".format(self.username)

    def get_short_name(self):
        return self.username

    def get_long_name(self):
        return "@{} ({})".format(self.username, self.email)


class UserProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True, related_name='profile')
    first_name = models.CharField(max_length=40, default='', blank=True)
    last_name = models.CharField(max_length=40, default='', blank=True)
    bio = models.TextField(blank=True, default='')
    avatar = models.ImageField('Avatar picture',
                               upload_to=avatar_upload_path,
                               null=True,
                               blank=True)

    def __str__(self):
        return self.user.username

    @property
    def get_avatar_url(self):
        if self.avatar:
            return '/media/{}'.format(self.avatar)
        return 'http://www.gravatar.com/avatar/{}?s=128&d=identicon'.format(
            '94d093eda664addd6e450d7e9881bcad'
        )


def create_profile(sender, **kwargs):
    if kwargs['created']:
        user_profile = UserProfile.objects.create(user=kwargs['instance'])

post_save.connect(create_profile, sender=User)

and here's the view for my actual newsletter that is collecting email address. note i'm just temporarily redirecting to google for now as a test:

from django.shortcuts import render, redirect
from newsletters.forms import NewsletterUserSignUpForm
from accounts.models import User


def newsletter_signup(request):
    if request.method == "POST":
        form = NewsletterUserSignUpForm(request.POST)

        if form.is_valid():
            instance = form.save(commit=False)
            if User.objects.filter(email=instance.email).exists():
                print("Sorry this email already exists")
            else:
                instance.save()
                return redirect("http://www.google.com")

    else:
        form = NewsletterUserSignUpForm()

    template = "newsletters/sign_up.html"
    return render(request, template, {'form': form})

sign up html form looks like this:

  <div class="col-lg-6 offset-lg-3">
      <form method="POST">
        {% csrf_token %}
         <div class="form-group">
           <div class="col-xs-6 col-xs-offset-3">
          {{ form.email}}
        <button class="btn btn-primary" type="submit">Sign Up!</button>
           </div>
         </div>
      </form>
        </div>
    </div>

Upvotes: 1

Views: 6853

Answers (3)

Okram jimmy
Okram jimmy

Reputation: 1

In your Accounts app model try this user.save(using=self._db) , this might help you

Upvotes: 0

badiya
badiya

Reputation: 2257

since you are using username = email.split('@')[0] to get the username for the user. It is possible that two different email would give you same value for the username. For example [email protected] and [email protected]. What you need to do is figure out some other algorithm to set the username or a good idea can be to user the email as username.

Upvotes: 2

Arpit Solanki
Arpit Solanki

Reputation: 9921

Your User model has a username field which requires unique=True which is the cause of your problem. Now you might be having a user having a username field as '' which is default. Since you already have one user with this username you can't have another user with this field. You should check that user already exists in the db or not also you have to enter some username with a user don't use default with unique=True its a really bad design and always fails.

Upvotes: 3

Related Questions