2

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?

Community
  • 1
  • 1
wong2
  • 34,358
  • 48
  • 134
  • 179

3 Answers3

6

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
Simon Kagwi
  • 1,636
  • 2
  • 19
  • 25
  • It seems that before I type user.save(), the new user already appears in database and django admin....and I tried to type user.save(), it works without any error – wong2 Dec 11 '11 at 13:35
  • The new user does not appear in the DB until you do user.save(). See this explanation in Django docs [ https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model ]. If you look at the model definition for the User model, none of the fields have `null=True` and thus for `CharField` fields such as username and password, an empty string is used when you save the user instance created using `user = User()`. All other fields have defaults, hence the `user` object actually results in a valid DB entry. – Simon Kagwi Dec 11 '11 at 13:51
  • @SimonKagwi is right and you (@wong2) are wrong (sorry for this). And then use `my_user.get_profile()` to access to the `Profile` model. – Stan Dec 11 '11 at 16:06
0

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.

Ilya
  • 1,349
  • 11
  • 16
0

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)
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284