@magine
2014-11-24T09:16:50.000000Z
字数 5617
阅读 2700
Django 翻译
创建一个基于User的代理Model。
允许的行为包括默认的ordering,custom managers,或者 custom model methods 。
如果你想存储与User有关的信息,可以使用一个OneToOneField字段关联到一个存储额外信息的Model。
这一Model通常被称为一个profile model模型,它可以用来存储一些非验证所需的信息。例如,你可以创建一个Model:
from django.contrib.auth.models import Userclass Employee(models.Model):user = models.OneToOneField(User)department = models.CharField(max_length=100)
访问:
>>> u = User.objects.get(username='fsmith')>>> freds_department = u.employee.department
如果需要将profile model的字段添加到admin管理界面的user页面上,需要在应用app的admin.py中定义InlineModelAdmin:
from django.contrib import adminfrom django.contrib.auth.admin import UserAdminfrom django.contrib.auth.models import Userfrom my_user_profile_app.models import Employee# Define an inline admin descriptor for Employee model# which acts a bit like a singletonclass EmployeeInline(admin.StackedInline):model = Employeecan_delete = Falseverbose_name_plural = 'employee'# Define a new User adminclass UserAdmin(UserAdmin):inlines = (EmployeeInline, )# Re-register UserAdminadmin.site.unregister(User)admin.site.register(User, UserAdmin)
这些profile models并不特别,只是与User Model有一个OneToOne链接。
所以当一个user实例创建时,profile model并不会自动创建。
但是你可以通过django.db.models.signals.post_save来解决这个问题。
有时候User Model并不适合你的网站,比如你要将email而不是username作为认证标识,这时候就需要重写User Model。
首先,需要将settings中的默认User Model覆盖:
AUTH_USER_MODEL = 'myapp.MyUser'
如果AUTH_USER_MODEL已被重设,那当User Model通过ForeignKey或者ManyToManyField访问时,不能直接访问,而是要通过AUTH_USER_MODEL来访问:
from django.conf import settingsfrom django.db import modelsclass Article(models.Model):author = models.ForeignKey(settings.AUTH_USER_MODEL)
最简单的定制一个User Model的方法是继承用户类AbstractBaseUser。
from django.db import modelsfrom 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 ofbirth 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 userdef create_superuser(self, email, date_of_birth, password):"""Creates and saves a superuser with the given email, date ofbirth and password."""user = self.create_user(email,password=password,date_of_birth=date_of_birth)user.is_admin = Trueuser.save(using=self._db)return userclass 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 addressreturn self.emaildef get_short_name(self):# The user is identified by their email addressreturn self.emaildef __unicode__(self):return self.emaildef has_perm(self, perm, obj=None):"Does the user have a specific permission?"# Simplest possible answer: Yes, alwaysreturn Truedef has_module_perms(self, app_label):"Does the user have permissions to view the app `app_label`?"# Simplest possible answer: Yes, alwaysreturn True@propertydef is_staff(self):"Is the user a member of staff?"# Simplest possible answer: All admins are staffreturn self.is_admin
添加到admin管理界面:
from django import formsfrom django.contrib import adminfrom django.contrib.auth.models import Groupfrom django.contrib.auth.admin import UserAdminfrom django.contrib.auth.forms import ReadOnlyPasswordHashFieldfrom customauth.models import MyUserclass UserCreationForm(forms.ModelForm):"""A form for creating new users. Includes all the requiredfields, plus a repeated password."""password1 = forms.CharField(label='Password', widget=forms.PasswordInput)password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)class Meta:model = MyUserfields = ('email', 'date_of_birth')def clean_password2(self):# Check that the two password entries matchpassword1 = 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 password2def save(self, commit=True):# Save the provided password in hashed formatuser = super(UserCreationForm, self).save(commit=False)user.set_password(self.cleaned_data["password1"])if commit:user.save()return userclass UserChangeForm(forms.ModelForm):"""A form for updating users. Includes all the fields onthe user, but replaces the password field with admin'spassword hash display field."""password = ReadOnlyPasswordHashField()class Meta:model = MyUserdef 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 valuereturn self.initial["password"]class MyUserAdmin(UserAdmin):# The forms to add and change user instancesform = UserChangeFormadd_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',)}),('Important dates', {'fields': ('last_login',)}),)# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin# overrides get_fieldsets to use this attribute when creating a user.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)