Py学习  »  Django

django(v1.5) 自定义用户基础

frikyskice • 12 年前 • 12047 次点击  
#这是v1.5中新增加的功能
#本文由frikyskice 根据官方Docs自行描述,请以原文档为准
#https://docs.djangoproject.com/en/dev/topics/auth/customizing/#substituting-a-custom-user-model
#本文目的给英文不好的筒子们一个参考,不代表其正确性
#frikyskice授权任何个人或组织直接传播本文,但不包括此情况(以本文进行非公益性质的商业盈利)


#本人不专业,拒绝回答技术问题,以免误人误己

通过定义AUTH_USER_MODEL 可对User模型进行自定义扩展 例如:

AUTH_USER_MODEL = 'myapp.MyUser'

扩展的app必须装入INSTALLED_APPS中

如果你已经定义AUTH_USER_MODEL,系统中原有的User模型不能直接使用

以下均以已经定义AUTH_USER_MODEL作为假设

get_user_model() 该函数用以返回正在使用的自定义的User模型(注意不是系统中自带的那个User) 使用方法: django.contrib.auth.get_user_model() ‘’‘ 对于原有的外键及多对多关系,你需要使用宏的模式进行处理,如下:

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

’‘’

如何自定义你的User模型 自定义User模型需要满足以下基本条件

  1. 模型必须有一个主键,并且是integer模型(建议不要在此做花样,直接autoXXXX,你懂的)
  2. 模型必须能有一个字段进行唯一性区分(注意不能是1中的东西),什么字段都可以
  3. 提供特定的方式以便于程序可以找到这个User(非系统自带),长短两个名称的form(这句大约就是这个意思)#in a “short” and “long” form#

当然这里最简单的方式是直接继承 AbstractBaseUser ,这样上面3个你可以不用管, AbstractBaseUser 就相当于djangoV1.4里面的User,如果你继承 AbstractBaseUser ,需要做以下内容:(我写的好啰嗦…………)

USERNAME_FIELD

例如:

class MyUser(AbstractBaseUser):
        identifier = models.CharField(max_length=40, unique=True, db_index=True)
        ...
        USERNAME_FIELD = 'identifier'

这里注意 identifier 中的unique=True 必须显示的标明,对应上面3条中的二条(麻将?)

REQUIRED_FIELDS

例如:

class MyUser(AbstractBaseUser):
        ...
        date_of_birth = models.DateField()
         height = models.FloatField()
         ...
         REQUIRED_FIELDS = ['date_of_birth', 'height']

**#这里是一个list,告诉系统那些是必须填的字段**

is_active

AbstractBaseUser 中默认的初始化为True,自己看着办吧

后面就是两函数,对应三条,嗯,你懂得,返回个字符串就行,啥啥的没关系,自己看着办

get_full_name()  |   get_short_name()

以下为AbstractBaseUser的其他一些方法,同v1.4中的User,不用重载,重载你也不用看我写的了

class models.AbstractBaseUserget_username()
    is_anonymous()
    is_authenticated()
    set_password(raw_password)
    check_password(raw_password)
    set_unusable_password()
    has_usable_password()

这里提一下,创建用户模型的时候最好加上username和email两个字段,这样你可以直接使用django自带的UserManager,如果没有,自己写一个吧,基类为 BaseUserManager, 必须提供以下两个方法

def create_user(self, email, date_of_birth, password=None):
    # create user here
    ...

def create_superuser(self, email, date_of_birth, password):
    # create superuser here
    ...

BaseUserManager也提供其他方法,自己查文档,不浪费口水了,当然你可以根据需要自己定义

以下为如何扩展django自己的User模型 如果django自带的User能满足你的要求,你可以简单的继承 django.contrib.auth.models.AbstractUser,并加入自己需要增加的简单字段。 凡是User模型提供的功能,AbstractUser都默认提供。 如果User模型不能满足你的要求,你需要完全自己定义相应的描述,并提供相应的功能来达到你的要求(包括相应的Forms)。

UserCreationForm

依赖User模型,任何自定义的模型都必须重载

UserChangeForm

依赖User模型,任何自定义的模型都必须重载

AuthenticationForm

与AbstractBaseUser的子类协同工作,与子类中的USERNAME_FIELD申明的字段相符,就是USERNAME_FIELD定义的啥,依据啥来验证用户

PasswordResetForm

原文举了个例子,自己去看吧,不过和密码相关的几个都不用重载

SetPasswordForm
PasswordChangeForm
AdminPasswordChangeForm

如何定义自定义User的admin功能 必须自己定义一个ModelAdmin的继承至django.contrib.auth.admin.UserAdmin的子类,这个很绕口,不过后面的例子一看就能明白,不做赘述。

由于本文用以扫盲,因此中间有几个话题略过

以下为Docs中的一个完整的例子: Filenames:models.py

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)


class MyUserManager(BaseUserManager):
    def create_user(self, email, date_of_birth, password=None):
        """
        Creates and saves a User with the given email, date of
        birth and password.
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=MyUserManager.normalize_email(email),
            date_of_birth=date_of_birth,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, date_of_birth, password):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(email,
            password=password,
            date_of_birth=date_of_birth
        )
        user.is_admin = True
        user.save(using=self._db)
        return user


class MyUser(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=


    
255,
        unique=True,
        db_index=True,
    )
    date_of_birth = models.DateField()
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['date_of_birth']

    def get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __unicode__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin

Filenames:admin.py

from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField

from customauth.models import MyUser


class UserCreationForm(forms.ModelForm):
    """A form for creating new users. Includes all the required
    fields, plus a repeated password."""
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

    class Meta:
        model = MyUser
        fields = ('email', 'date_of_birth')

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserChangeForm(forms.ModelForm):
    """A form for updating users. Includes all the fields on
    the user, but replaces the password field with admin's
    password hash display field.
    """
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = MyUser
        fields = 


    
['email', 'password', 'date_of_birth', 'is_active', 'is_admin']

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]


class MyUserAdmin(UserAdmin):
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('email', 'date_of_birth', 'is_admin')
    list_filter = ('is_admin',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('date_of_birth',)}),
        ('Permissions', {'fields': ('is_admin',)}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'date_of_birth', 'password1', 'password2')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()

# Now register the new UserAdmin...
admin.site.register(MyUser, MyUserAdmin)
# ... and, since we're not using Django's builtin permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)

最后,你需要更改settings.py 文件

AUTH_USER_MODEL = 'customauth.MyUser'
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/133
 
12047 次点击  
文章 [ 1 ]  |  最新文章 12 年前