wong2
wong2

Reputation: 35720

Why didn't auth.User check for required fields?

I'd like to extend django's auth.User, after reading this question,
this is my models.py:

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save  

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    age = models.SmallIntegerField()  

def create_user_profile(sender, instance, created, **kwargs):  
    if created:  
        profile, created = UserProfile.objects.get_or_create(user=instance)    

post_save.connect(create_user_profile, sender=User) 

and I add this line in the bottom of my settings.py:

AUTH_PROFILE_MODULE = 'MYAPP.UserProfile'  

The problem is, when I run python manage.py shell, and type:

from django.contrib.auth.models import User  
user = User()  

It works without problem! why doesn't it give an error that I didn't give a username/password?

Upvotes: 2

Views: 103

Answers (3)

Burhan Khalid
Burhan Khalid

Reputation: 174624

The restrictions are mainly designed for form validation; there are very few restrictions (mainly those that may cause DB problems) that are enforced when you use the API.

You can easily create an empty user (a user with no username):

>>> from django.contrib.auth.models import User
>>> u = User()
>>> u.save()
>>> u
<User: >
>>> u.id
2

However, if you try to create two empty users you'll get an IntegrityError:

>>> u = User()
>>> u.save()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/base.py", line 460, in save
    self.save_base(using=using, force_insert=force_insert, force_update=force_update)
  File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/base.py", line 553, in save_base
    result = manager._insert(values, return_id=update_pk, using=using)
  File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/manager.py", line 195, in _insert
    return insert_query(self.model, values, **kwargs)
  File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/query.py", line 1436, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 791, in execute_sql
    cursor = super(SQLInsertCompiler, self).execute_sql(None)
  File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 735, in execute_sql
    cursor.execute(sql, params)
  File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/backends/util.py", line 34, in execute
    return self.cursor.execute(sql, params)
  File "/Users/burhan/work/projects/foo/env/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 234, in execute
    return Database.Cursor.execute(self, query, params)
IntegrityError: column username is not unique

If you look at the model, you'll see there is a db-level restriction on the username field (unique=True):

`username = models.CharField(_('username'), max_length=30, unique=True...`

This is enforced at the API level, so you cannot have two users with the same username field.

Another example of this is the choices argument. This is used chiefly for presentation. If you have a field with choices=('M','Male'),('F','Female'); using the API you can insert any single character and it will happily accept it.

Options that are enforced at the database level (meaning, you can't "violate" them from the API) are:

  1. unique
  2. max_length
  3. null (do not confuse with blank)

Upvotes: 0

Simon Kagwi
Simon Kagwi

Reputation: 1638

When you run user = User(), all you are doing is creating a new User instance. It will not throw an error until you try to save it with user.save().

To simultaneously create and save a new model instance to the DB:

user = User.objects.create() # should throw an IntegrityError due to required (not NULL) fields not provided

Upvotes: 6

Ilya
Ilya

Reputation: 1399

Please ensure that UserProfile is inside of models.py in MYAPP and MYAPP is registered in INSTALLED_APPS. It seems like your signal doesn't work at all. If it won't help, try that in shell:

from django.contrib.auth.models import User  
from MYAPP.models import UserProfile  
user = User() 

Thus you'll be sure that signal was properly registered.

Upvotes: 0

Related Questions