I got suddenly an integrity error: "Duplicate entry 'qw' for key 'username'
from this model. 1062,
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class Customer(User):
slug=models.SlugField(unique=True)
description=models.TextField(null=True)
phone=models.IntegerField(null=True)
id_verified=models.NullBooleanField()
picture=models.ImageField(upload_to='media/customer', null=True)
isWorker=models.BooleanField()
def save(self,*args,**kwargs):
self.slug=slugify(self.username)
super(Customer,self).save(*args, **kwargs)
def __unicode__(self):
return self.username
What's wrong here?
From the docs, about specifying a custom user model:
You must then provide some key implementation details:
USERNAME_FIELD
A string describing the name of the field on the User
model that is used as the unique identifier. This will usually be a
username of some kind, but it can also be an email address, or any
other unique identifier. The field must be unique (i.e., have
unique=True set in its definition).
So username seems to be unique, at least until you set a custom username field.
Read the docs
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model
Related
#models.py
class Mymodel(models.Model):
name = models.CharField(max_length=100,null=False,blank=False)
email = models.EmailField(max_length=100,null=False,blank=False)
password = models.CharField(max_length=120,null=False,blank=False)
email_notification = models.BooleanField()
#views.py
obj=MyModel.objects.create(name="ok",password="dsfdsfdsfdsfsfds",email_notification=1)
even if email was required field,then also object was created when I see in the admin panel.What can be the issue,Why object got created,even if email field was mandatory?
Also if I go in admin panel and open that object and click save then it raises that email is required
Note: You don't to have provide null=False,blank=False in your fields because those are the values used by default.(See the Django Field __int__ signature.).
def __init__(self, verbose_name=None, name=None, primary_key=False,
max_length=None, unique=False, blank=False, null=False,
db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
serialize=True, unique_for_date=None, unique_for_month=None,
unique_for_year=None, choices=None, help_text='', db_column=None,
db_tablespace=None, auto_created=False, validators=(),
error_messages=None):
By default all the fields in database are created with NOT NULL constraint. If you set null=True for a particular field, then django sets NULL on the column in your DB. It’s the database equivalent of Python’s None keyword.
Example with null argument
Assume that I have the following Mymodel in my my_app and I set email field to null=True.
class MyModel(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(max_length=100, null=True)
password = models.CharField(max_length=120)
email_notification = models.BooleanField()
In Shell,
>> from my_app.models import MyModel
>> new = MyModel.objects.create(name="ok",
password="dsfdsfdsfdsfsfds",
email_notification=1)
>> new.email == None
>> True # As you can see Django sets db value
# as NULL and when we query the data it converts back to Python `None` object.
Example without null argument
Assume that I have the following Mymodel in my my_app.(remember null will be False by default)
class MyModel(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(max_length=100)
password = models.CharField(max_length=120)
email_notification = models.BooleanField()
In Shell,
>> from my_app.models import MyModel
>> new_obj = MyModel.objects.create(name="test",
password="test",
email_notification=1)
>> new_obj.email == ''
>> True
Ie,Django CharField and TextField the default values are stored in the DB as an empty string (''). In other words, if you create an object without providing values for a CharField(or a TextField) under the hood Django invokes the get_default method and returns '' (only in this case). This value will be stored in the database.
The following is the source code of get_default method.
def get_default(self):
"""Return the default value for this field."""
return self._get_default()
#cached_property
def _get_default(self):
if self.has_default():
if callable(self.default):
return self.default
return lambda: self.default
if not self.empty_strings_allowed or self.null and not connection.features.interprets_empty_strings_as_nulls:
return return_None
return str # return empty string
Let's answer your question:
Why object got created,even if email field was mandatory?
The answer is EmailField is an instance of CharField Hence default value '' will be used while creating an object in database. That is why you are not getting django.db.utils.IntegrityError.
>> new_obj = Mymodel.objects.create(name='tes1t', password='test1', email_notification=1)
>>> new_obj.email
''
Also if I go to the admin panel and open that object and click save then
it raises an error indicating that email is required
Remember blank is different from null. null is purely database-related, whereas blank is validation-related. So when you create an object directly in Python code, or execute raw SQL yourself, you are actually bypassing all of Django’s input validation. But in admin, Django is validating the input through the model form. Since in your case blank is set to False(blank not allowed), model form will raise Email is required Error.
Here is the relevant Django documentation for blank argument.
Field.blank
If True, the field is allowed to be blank. Default is False. Note
that this is different than null. null is purely database-related,
whereas blank is validation-related. If a field has blank=True, form
validation will allow entry of an empty value. If a field has
blank=False, the field will be required.
Additional resources
Django tips: the difference between ‘blank’ and ‘null’
differentiate null=True, blank=True in django
There is no issue with django you will have to create proper Django Model Form validation so that the empty string isn't ignored and it will raise an error for the blank field.
I have been learning Django for a week, In order to implement authentication system, I have created models.py file as tutorials.
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class User(AbstractBaseUser):
username = models.CharField('username', max_length = 10, unique = True, db_index = True)
email = models.EmailField('email address', unique = True)
joined = models.DateTimeField(auto_now_add = True)
is_active = models.BoolenField(default = True)
is_admin = models.BoolenField(default = False)
USERNAME_FIELD = 'username'
def __unicode__(self):
return self.username
I understand what username, email, joined, is_active, is_admin means, but I can't understand why I use USERNAME_FIELD.
Is username created by models.CharField equal to the 'username' in USERNAME_FIELD?
Why do I have to create USERNAME_FIELD?
What does def __unicode__(self): function mean?
According to the docs, USERNAME_FIELD is:
A string describing the name of the field on the user model that is used as the unique identifier. This will usually be a username of some kind, but it can also be an email address, or any other unique identifier. The field must be unique (i.e., have unique=True set in its definition), unless you use a custom authentication backend that can support non-unique usernames.
So, USERNAME_FIELD specifies which model field is going to be used as the username. If your application uses an email address instead of a username, you would configure that using USERNAME_FIELD.
The __unicode__(self) method returns a string representation of the object. Without it, any time you try to display an object it will look like: <User: User object>. As you have it now, displaying a User object will instead show the User's username. In the Django tutorial part 2 they use the __str__ method in conjunction with the #python_2_unicode_compatible decorator to make it work with Python 2. In Python 3 __str__ is the equivalent of __unicode__ in Python 2.
Check the documentation for your version of Django:
USERNAME_FIELD
A string describing the name of the field on the User model that is used as the unique identifier. This will usually be a username of
some kind, but it can also be an email address, or any other unique
identifier. The field must be unique (i.e., have unique=True set in
its definition).
USERNAME_FIELD defaults to "username" so you can skip setting it in your custom user model if the default works for you.
You can read about __str__() and __unicode__() methods here.
I came across this code:
drinker/models.py:
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
class Drinker(models.Model):
user = models.OneToOneField(User)
birthday = models.DateField()
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
drinker/forms.py:
from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
from drinker.models import Drinker
class RegistrationForm(ModelForm):
username = forms.CharField(label=(u'User Name'))
email = forms.EmailField(label=(u'Email Address'))
password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
password1 = forms.CharField(label=(u'Verify Password'), widget=forms.PasswordInput(render_value=False))
class Meta:
model = Drinker
exclude = ('user',)
def clean_username(self):
username = self.cleaned_data['username']
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError("That username is already taken, please select another.")
def clean(self):
if self.cleaned_data['password'] != self.cleaned_data['password1']:
raise forms.ValidationError("The passwords did not match. Please try again.")
return self.cleaned_data
My Question is about the inner class meta which as two attributes:
model=Drinker
exclude=('user`,)
I have a not-so-clear understanding of how this meta class work. I have read the documentation but I am still confused. Can you kindly explain what those two lines mean and what their purpose is?
Thanks
The exclude attribute tells Django what fields from the model not to include in the form.
Quoting the Selecting fields to use section of the model form documentation:
2. Set the exclude attribute of the ModelForm’s inner Meta class to a list of fields to be excluded from the form.
The model line simply tells Django what model to take the fields from; together the two lines tell Django to give RegistrationForm fields based on all fields on the Drinker model, except 'user'. For the given Drinker model, that's birthday and name.
These fields are added to the other form fields already defined on the form. If the Drinker model gained more fields, those would automatically be part of the form too.
See the Overriding the default fields section of the same chapter:
When you explicitly instantiate a form field like this, it is important to understand how ModelForm and regular Form are related.
ModelForm is a regular Form which can automatically generate certain fields. The fields that are automatically generated depend on the content of the Meta class and on which fields have already been defined declaratively. Basically, ModelForm will only generate fields that are missing from the form, or in other words, fields that weren’t defined declaratively.
The inner Meta class is just a convenient way to create a namespace for such configuration on your form class for the Django framework to find. All Django now has to do is introspect Form.Meta and see what attributes are defined there.
Note that using exclude can lead to security problems. From the same documenation:
It is strongly recommended that you explicitly set all fields that should be edited in the form using the fields attribute. Failure to do so can easily lead to security problems when a form unexpectedly allows a user to set certain fields, especially when new fields are added to a model. Depending on how the form is rendered, the problem may not even be visible on the web page.
The alternative approach would be to include all fields automatically, or blacklist only some. This fundamental approach is known to be much less secure and has led to serious exploits on major websites (e.g. GitHub).
fields = exclude() and fields = '__all__' - means display all the fields
exclude = ('password',) - means exclude password field
fields = ('user','email',) - means display only email field and userfield
in short : fields you want to show up in the form should be mentioned in 'fields' attribute ex:
fields = '__all__' #will show all the fields from the model in the form
'exclude' does the opposite
exclude = ['title'] # don't show the title field
i'm building a web application with Django 1.5. I'm using a custom User model with a custom UserManager.
I followed the instructions and examples of the official Django documentation.
Now, when i'm trying to create a new user via UserManager.create_user(...) i'm getting a NoneType error: It seems the UserManager's attribute models is of type None.
I think i'm setting up the UserManager correctly in the User model ( objects = UserManager() )
I really don't know where i'm making a mistake. Booth my coding partners and i are new to Django. Maybe you can help us out.
Here is the code:
class UserManager(BaseUserManager):
"""
create a new user
#param username: the name for the new user
#param password: the password for the new user. if none is provided a random password is generated
#param person: the corresponding person object for this user
"""
def create_user(self, username, person, password=None):
if not username:
raise ValueError('User must have a valid username')
user = self.model(username=username, created=datetime.now(), must_change_password=True, deleted=False, person=person)
user.set_password(password)
user.save(using=self._db)
return user
class User(AbstractBaseUser):
## the id of the user. unique through the application
user_id = models.AutoField(primary_key=True)
## the name of the user. unique through the application
username = models.CharField(max_length=32, unique=True)
## the date when the user was created
created = models.DateTimeField()
## iff this is true the user must set a new password at next login
must_change_password = models.BooleanField(default=True)
## iff true the user is marked as deleted and can not login
deleted = models.BooleanField(default=False)
## iff true the user is admin and has all permissions. use with care!
is_admin = models.BooleanField(default=False)
## reference to the person entity that is linked to this specific user
person = models.ForeignKey(Person)
## indicates if the user is active or not
active = models.BooleanField(default=True)
## define the user manager class for User
objects = UserManager()
# necessary to use the django authentication framework: this field is used as username
USERNAME_FIELD = 'username'
I'm getting the NoneType Error at line user = self.model(..) in the create_user() method in the UserManager
To create new user you shouldn't call UserManager.create_user(...). Instead you should use :
from django.contrib.auth import get_user_model
get_user_model().objects.create_user(...)
This is how django managers work. You can read docs here
I also had problems saving the custom user model and it took me while to figure it our
I think the important line in your code is:
objects = UserManager()
within the User class, so in order to save the new user you need to call
new_user=User.objects.create_user(args, args, args, etc)
the "objects" is the item that calls the UserManager class and is called a manager in django
Important caveat to update the solutions...
If you're facing this kind of problem, you've probably tried various solutions around the web telling you to add AUTH_USER_MODEL = users.CustomUser to settings.py and then to add the following code to views.py forms.py and any other file that calls User:
from django.contrib.auth import get_user_model
User = get_user_model()
And then you scratch your head when you get the error:
Manager isn't available; 'auth.User' has been swapped for 'users.User'
Anytime your code references User such as:
User.objects.get()
Cause you know you already put objects = UserManager() in your custom user class (UserManager being the name of your custom manager that extends BaseUserManager).
Well as it turns out (thank you to #Aldarund) doing:
User = get_user_model() # somewhere at the top of your .py file
# followed by
User.objects.get() # in a function/method of that same file
Is NOT equivalent to:
get_user_model().objects.get() # without the need for User = get_user_model() anywhere
Perhaps not intuitive, but it turns out that that in python, executing User = get_user_model() once at the time of import does not then result in User being defined across subsequent calls (i.e. it does not turn User into a "constant" of sorts which you might expect if you're coming from a C/C++ background; meaning that the execution of User = get_user_model() occurs at the time of imports, but is then de-referenced before subsequent called to class or function/method in that file).
So to sum up, in all files that reference the User class (e.g. calling functions or variables such as User.objects.get() User.objects.all() User.DoesNotExist etc...):
# Add the following import line
from django.contrib.auth import get_user_model
# Replace all references to User with get_user_model() such as...
user = get_user_model().objects.get(pk=uid)
# instead of user = User.objects.get(pk=uid)
# or
queryset = get_user_model().objects.all()
# instead of queryset = User.objects.all()
# etc...
Hope this helps save others some time...
I had to add an answer as I don't have enough rep to comment. But the link in #Aldarund's answer does not describe the use of get_user_model() at all. However, this link should help...
In my case if you got "manager_method" missing 1 required positional argument: 'self' django err you should notice that
unlike model.Manager the UserManager need to set as blow
from django.contrib.auth.models import AbstractUser, UserManager
from django.db.models import Q
class CostumUserManager(UserManager ):
def authors(self):
return self.filter(Q(is_author=True) | Q(is_superuser=True))
class User(AbstractUser):
is_author = models.BooleanField(default=False, )
objects = CostumUserManager() # Use () in end of it
I am trying to validate the uniqueness of an email address in datastore. The problem is that this does not allow me to edit/update the entry (e.g. if I only want to change the display_name - see models.py below).
I am submitting a form build using djangoforms (with an datastore entry prefilled as I already know the key of the datastore entry):
forms.UserForm(instance=db.get(db.Key(key)))
After submitting the form using POST method I get the details from datastore and associate these with the submitted form:
entry = db.get(db.Key(self.request.get('key')))
data = forms.UserForm(data=self.request.POST, instance=entry)
if data.is_valid():
...
The form then validates using the following form class (in forms.py):
from django import forms
from google.appengine.ext.db import djangoforms
import models
class UserForm(djangoforms.ModelForm):
class Meta:
model = models.AuthorizedUsers
def clean_email(self):
"""Prevent duplicate email addresses."""
if self.Meta.model.all().filter('email =', self.cleaned_data['email']).count():
raise forms.ValidationError('Duplicate Entry: %s.' %
self.cleaned_data['email'])
return self.cleaned_data['email']
Using the following model (in models.py)
class AuthorizedUsers(db.Model):
"""Base model class for storing user permissions."""
email = db.StringProperty()
display_name = db.StringProperty()
Any suggestions what I am missing here? How can I prevent the raising of ValidationError when just updating an entry? Keep in mind that I do want to prevent the adding of a new datastore entry with the same email address.
Thanks in advance for your help!
You can check to see if your email field has changed before checking whether or not to validate it against all previous email addresses. Your clean method would be changed to:
def clean_email(self):
"""Prevent duplicate email addresses."""
if 'email' in self.changed_data:
if self.Meta.model.all().filter('email =', self.cleaned_data['email']).count():
raise forms.ValidationError('Duplicate Entry: %s.' %
self.cleaned_data['email'])
return self.cleaned_data['email']