Reputation: 1183
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
Reputation: 1
In your Accounts app model try this user.save(using=self._db)
, this might help you
Upvotes: 0
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
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