Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Red User, Blue User, MyUser, auth.User

Red User, Blue User, MyUser, auth.User

An exploration of one of the banner features of Django 1.5 -- Custom User models. Includes worked examples, a discussion of design decisions that must be made, and a look at the internal architecture that makes it all possible.

Russell Keith-Magee

September 04, 2013
Tweet

More Decks by Russell Keith-Magee

Other Decks in Technology

Transcript

  1. Other tips • Don’t assume a single letter is an

    initial • Be wary of name-part algorithms • Spaces, Apostrophes and Hyphens are all legal characters in names • Don’t require a “family name” • “Previous name”, not “Maiden name” • Honorifics even more complex
  2. 1. Define user model • 2 possible abstract base classes:

    • AbstractBaseUser • AbstractUser • Maybe with PermissionsMixin • Define USERNAME_FIELD • Define REQUIRED_FIELDS • Define get_full_name() and get_short_name()
  3. 2. Define your Manager • Need to describe: • How

    to create users • How to create superusers
  4. 4. Register with admin • Only need to do this

    if you’re using admin • Subclass contrib.admin.UserAdmin • admin.site.register() • Don’t need to unregister default User
  5. Reverse lookup naming class Department(Model): ... class User(AbstractUser): full_name =

    CharField() department = ForeignKey(Department) department = Department.objects.get(...) print department.user_set.all()
  6. Reverse lookup naming class Department(Model): ... class MyUser(AbstractUser): full_name =

    CharField() department = ForeignKey(Department) department = Department.objects.get(...) print department.myuser_set.all()
  7. Reverse lookup naming class Department(Model): ... class MyUser(AbstractUser): full_name =

    CharField() department = ForeignKey(Department, related_name=‘user_set’) department = Department.objects.get(...) print department.user_set.all()
  8. Reverse lookup naming class Department(Model): ... class MyUser(AbstractUser): full_name =

    CharField() department = ForeignKey(Department) department = Department.objects.get(...) attr = “%s_set” % user._meta.object_name print getattr(department,attr).all()
  9. Email-based login • Define a user model with • email

    = EmailField(max_length=254) • USERNAME_FIELD = ‘email’ • Define forms, admin, etc • Set AUTH_USER_MODEL
  10. Kerberos Single Sign-on • “username” is your Kereros token: username@domain

    • Define an authentication backend that converts credentials into users
  11. Authentication Backends • On login, you provide a credentials dict

    • Usually, Username and Password • Can be anything • Authentication backend turns credentials into a validated user • Can have multiple authentication backends.
  12. Option 2: class User(AbstractUser): ... class UserProfile(Model): full_name = CharField()

    user = OneToOneField(User) birth_date = DateField() avatar = FileField()
  13. Option 2: class User(AbstractUser): ... class IdentityProfile(Model): user = OneToOneField(User)

    full_name = CharField() birth_date = DateField() class DisplayProfile(Model): user = OneToOneField(User) avatar = FileField()
  14. Option 3: Hybrid class User(AbstractUser): full_name = CharField() class UserProfile(Model):

    user = OneToOneField(User) birth_date = DateField() avatar = FileField()
  15. How it works • No internal references to auth.User •

    auth.User has a Meta property: swappable = ‘AUTH_USER_MODEL’ • Defines the name of a setting • Inspected at runtime for the “real” class • generates Meta.swapped • The rest is just validation
  16. ForeignKeys + M2M • No new features in ForeignKey or

    M2M • ForeignKey(‘auth.User’) has always worked • Now, we’re just using a setting • Validation that ForeignKey doesn’t point at a “swapped” model.