[关闭]
@magine 2014-11-24T09:16:50.000000Z 字数 5617 阅读 2529

Django自定义用户认证系统

Django 翻译


扩展已有的用户模型

不改变字段,只改变Model的行为

创建一个基于User的代理Model。
允许的行为包括默认的orderingcustom managers,或者 custom model methods

改变字段

如果你想存储与User有关的信息,可以使用一个OneToOneField字段关联到一个存储额外信息的Model。
这一Model通常被称为一个profile model模型,它可以用来存储一些非验证所需的信息。例如,你可以创建一个Model:

  1. from django.contrib.auth.models import User
  2. class Employee(models.Model):
  3. user = models.OneToOneField(User)
  4. department = models.CharField(max_length=100)

访问:

  1. >>> u = User.objects.get(username='fsmith')
  2. >>> freds_department = u.employee.department

如果需要将profile model的字段添加到admin管理界面的user页面上,需要在应用app的admin.py中定义InlineModelAdmin

  1. from django.contrib import admin
  2. from django.contrib.auth.admin import UserAdmin
  3. from django.contrib.auth.models import User
  4. from my_user_profile_app.models import Employee
  5. # Define an inline admin descriptor for Employee model
  6. # which acts a bit like a singleton
  7. class EmployeeInline(admin.StackedInline):
  8. model = Employee
  9. can_delete = False
  10. verbose_name_plural = 'employee'
  11. # Define a new User admin
  12. class UserAdmin(UserAdmin):
  13. inlines = (EmployeeInline, )
  14. # Re-register UserAdmin
  15. admin.site.unregister(User)
  16. admin.site.register(User, UserAdmin)

这些profile models并不特别,只是与User Model有一个OneToOne链接。
所以当一个user实例创建时,profile model并不会自动创建。
但是你可以通过django.db.models.signals.post_save来解决这个问题。

重写User模型

有时候User Model并不适合你的网站,比如你要将email而不是username作为认证标识,这时候就需要重写User Model。
首先,需要将settings中的默认User Model覆盖:

  1. AUTH_USER_MODEL = 'myapp.MyUser'

引用

如果AUTH_USER_MODEL已被重设,那当User Model通过ForeignKey或者ManyToManyField访问时,不能直接访问,而是要通过AUTH_USER_MODEL来访问:

  1. from django.conf import settings
  2. from django.db import models
  3. class Article(models.Model):
  4. author = models.ForeignKey(settings.AUTH_USER_MODEL)

定制

最简单的定制一个User Model的方法是继承用户类AbstractBaseUser。

  1. from django.db import models
  2. from django.contrib.auth.models import (
  3. BaseUserManager, AbstractBaseUser
  4. )
  5. class MyUserManager(BaseUserManager):
  6. def create_user(self, email, date_of_birth, password=None):
  7. """
  8. Creates and saves a User with the given email, date of
  9. birth and password.
  10. """
  11. if not email:
  12. raise ValueError('Users must have an email address')
  13. user = self.model(
  14. email=MyUserManager.normalize_email(email),
  15. date_of_birth=date_of_birth,
  16. )
  17. user.set_password(password)
  18. user.save(using=self._db)
  19. return user
  20. def create_superuser(self, email, date_of_birth, password):
  21. """
  22. Creates and saves a superuser with the given email, date of
  23. birth and password.
  24. """
  25. user = self.create_user(email,
  26. password=password,
  27. date_of_birth=date_of_birth
  28. )
  29. user.is_admin = True
  30. user.save(using=self._db)
  31. return user
  32. class MyUser(AbstractBaseUser):
  33. email = models.EmailField(
  34. verbose_name='email address',
  35. max_length=255,
  36. unique=True,
  37. db_index=True,
  38. )
  39. date_of_birth = models.DateField()
  40. is_active = models.BooleanField(default=True)
  41. is_admin = models.BooleanField(default=False)
  42. objects = MyUserManager()
  43. USERNAME_FIELD = 'email'
  44. REQUIRED_FIELDS = ['date_of_birth']
  45. def get_full_name(self):
  46. # The user is identified by their email address
  47. return self.email
  48. def get_short_name(self):
  49. # The user is identified by their email address
  50. return self.email
  51. def __unicode__(self):
  52. return self.email
  53. def has_perm(self, perm, obj=None):
  54. "Does the user have a specific permission?"
  55. # Simplest possible answer: Yes, always
  56. return True
  57. def has_module_perms(self, app_label):
  58. "Does the user have permissions to view the app `app_label`?"
  59. # Simplest possible answer: Yes, always
  60. return True
  61. @property
  62. def is_staff(self):
  63. "Is the user a member of staff?"
  64. # Simplest possible answer: All admins are staff
  65. return self.is_admin

添加到admin管理界面:

  1. from django import forms
  2. from django.contrib import admin
  3. from django.contrib.auth.models import Group
  4. from django.contrib.auth.admin import UserAdmin
  5. from django.contrib.auth.forms import ReadOnlyPasswordHashField
  6. from customauth.models import MyUser
  7. class UserCreationForm(forms.ModelForm):
  8. """A form for creating new users. Includes all the required
  9. fields, plus a repeated password."""
  10. password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
  11. password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
  12. class Meta:
  13. model = MyUser
  14. fields = ('email', 'date_of_birth')
  15. def clean_password2(self):
  16. # Check that the two password entries match
  17. password1 = self.cleaned_data.get("password1")
  18. password2 = self.cleaned_data.get("password2")
  19. if password1 and password2 and password1 != password2:
  20. raise forms.ValidationError("Passwords don't match")
  21. return password2
  22. def save(self, commit=True):
  23. # Save the provided password in hashed format
  24. user = super(UserCreationForm, self).save(commit=False)
  25. user.set_password(self.cleaned_data["password1"])
  26. if commit:
  27. user.save()
  28. return user
  29. class UserChangeForm(forms.ModelForm):
  30. """A form for updating users. Includes all the fields on
  31. the user, but replaces the password field with admin's
  32. password hash display field.
  33. """
  34. password = ReadOnlyPasswordHashField()
  35. class Meta:
  36. model = MyUser
  37. def clean_password(self):
  38. # Regardless of what the user provides, return the initial value.
  39. # This is done here, rather than on the field, because the
  40. # field does not have access to the initial value
  41. return self.initial["password"]
  42. class MyUserAdmin(UserAdmin):
  43. # The forms to add and change user instances
  44. form = UserChangeForm
  45. add_form = UserCreationForm
  46. # The fields to be used in displaying the User model.
  47. # These override the definitions on the base UserAdmin
  48. # that reference specific fields on auth.User.
  49. list_display = ('email', 'date_of_birth', 'is_admin')
  50. list_filter = ('is_admin',)
  51. fieldsets = (
  52. (None, {'fields': ('email', 'password')}),
  53. ('Personal info', {'fields': ('date_of_birth',)}),
  54. ('Permissions', {'fields': ('is_admin',)}),
  55. ('Important dates', {'fields': ('last_login',)}),
  56. )
  57. # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
  58. # overrides get_fieldsets to use this attribute when creating a user.
  59. add_fieldsets = (
  60. (None, {
  61. 'classes': ('wide',),
  62. 'fields': ('email', 'date_of_birth', 'password1', 'password2')}
  63. ),
  64. )
  65. search_fields = ('email',)
  66. ordering = ('email',)
  67. filter_horizontal = ()
  68. # Now register the new UserAdmin...
  69. admin.site.register(MyUser, MyUserAdmin)
  70. # ... and, since we're not using Django's builtin permissions,
  71. # unregister the Group model from admin.
  72. admin.site.unregister(Group)
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注