實(shí)現(xiàn)django的自定義用戶認(rèn)證1

要想自定義用戶認(rèn)證的話垄开,首先UserProfile賬戶表不能再與django的User表OneToOne關(guān)聯(lián)了希柿,djangoproject網(wǎng)址提供了我們重新自定義的實(shí)現(xiàn)方法等孵,先來到這個(gè)網(wǎng)站https://docs.djangoproject.com/en/2.1/topics/auth/customizing/窘疮,ctrl+F找到 MyUser這個(gè)類

image.png
必須得把整個(gè)類都復(fù)制下來鲫忍,我們可以把 MyUser 改成自己的 UserProfile,這里 email 就是登陸的賬號鸠儿,你也可以改成其它的如姓名屹蚊,這里我們就用email了,date_of_birth 字段可以刪掉进每,作用不大汹粤,為了好區(qū)分,我們還可以加上一個(gè) name 字段田晚。 is_active 代表賬戶是不是活躍的嘱兼,is_admin代表賬戶是不是管理員,objects 可以先不用看把它注釋贤徒,不過由于前面把date_of_birth換成了name芹壕,這個(gè)類里所有的date of birth都得換了,整理后就是這樣

class UserProfile(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )

    name = models.CharField(max_length=32)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = UserProfileManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

    def __str__(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

如果你的數(shù)據(jù)庫前面已經(jīng)有數(shù)據(jù)了接奈,那就得先刪庫了(目前只會的操作)哪雕。刪完庫后開始makemigrations二連,現(xiàn)在就可以創(chuàng)建一個(gè)超級用戶進(jìn)入admin了鲫趁。但是斯嚎,,挨厚,點(diǎn)擊 UserProfile 表報(bào)錯(cuò)堡僻,沒找到,

是因?yàn)閐jango不知道哪個(gè)是賬戶表疫剃,可能有人說UserProfile不是繼承了一個(gè) AbstractBaseUser 類嗎钉疫?AbstractBaseUser也僅僅只是一個(gè)model類,沒法做到這個(gè)巢价,現(xiàn)在我們要去settings里明確地告訴 django 牲阁,哪個(gè)是我的用戶表固阁。在settings最末尾加上AUTH_USER_MODEL = 'crm.UserProfile'就可以了,crm是app名字

現(xiàn)在我們再重新來一遍migrate,會報(bào)出下面的警告城菊,意思是需不需要把django自己的User表給刪掉备燃,我們敲上yes就行

image.png
現(xiàn)在再來創(chuàng)建超級用戶,
image.png
剛輸入完email又報(bào)錯(cuò)了凌唬!輸完email應(yīng)該是要輸入密碼的才對并齐,那這是什么原因呢?密碼其實(shí)是需要一個(gè)方法來實(shí)現(xiàn)的客税,比如密碼需要輸入兩次啊况褪,什么的。雖然UserProfile用戶表寫好了更耻,但是如何創(chuàng)建用戶我們還沒有寫测垛,所以現(xiàn)在得加上。


在我們前面復(fù)制MyUser類的上面還有一個(gè) MyUserManager類秧均,把它也復(fù)制到models中,和上面一樣食侮,也對date_of_birth與name對換一下

class UserProfileManager(BaseUserManager):
    def create_user(self, email, name, 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=self.normalize_email(email),
            name=name,
        )
        user.is_active = True
        user.set_password(password)
        user.save(using=self._db)
        return user

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

這個(gè)時(shí)候我們在MyUser里注釋的objects就得解開了!
現(xiàn)在需要繼續(xù)makemigrations了熬北,可有有時(shí)候會保一個(gè)django_admin_log的錯(cuò)誤疙描,只需要在migrate后面加上--fake诚隙。


不過不會顯示UserProfile表讶隐,只有在admin中加上下面代碼,才能夠?qū)Ρ磉M(jìn)行操作久又,這段代碼在djangoproject中也有

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 = models.UserProfile
        fields = ('email', 'name')

    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().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 = models.UserProfile
        fields = ('email', 'password', 'name', '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 UserProfileAdmin(BaseUserAdmin):
    # 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', 'name', 'is_admin')
    list_filter = ('is_admin',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('name',)}),
        ('Permissions', {'fields': ('is_admin',)}),
    )
    # 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', 'name', 'password1', 'password2')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()

# Now register the new UserAdmin...
admin.site.register(models.UserProfile, UserProfileAdmin)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巫延,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子地消,更是在濱河造成了極大的恐慌炉峰,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脉执,死亡現(xiàn)場離奇詭異疼阔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)半夷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門婆廊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巫橄,你說我怎么就攤上這事淘邻。” “怎么了湘换?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵宾舅,是天一觀的道長统阿。 經(jīng)常有香客問我,道長筹我,這世上最難降的妖魔是什么扶平? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮崎溃,結(jié)果婚禮上蜻直,老公的妹妹穿的比我還像新娘。我一直安慰自己袁串,他們只是感情好概而,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著囱修,像睡著了一般赎瑰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上破镰,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天餐曼,我揣著相機(jī)與錄音,去河邊找鬼鲜漩。 笑死源譬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的孕似。 我是一名探鬼主播踩娘,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼喉祭!你這毒婦竟也來了养渴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤泛烙,失蹤者是張志新(化名)和其女友劉穎理卑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔽氨,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡藐唠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鹉究。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宇立。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖坊饶,靈堂內(nèi)的尸體忽然破棺而出泄伪,到底是詐尸還是另有隱情,我是刑警寧澤匿级,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布蟋滴,位于F島的核電站染厅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏津函。R本人自食惡果不足惜肖粮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望尔苦。 院中可真熱鬧涩馆,春花似錦、人聲如沸允坚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稠项。三九已至涯雅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間展运,已是汗流浹背活逆。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拗胜,地道東北人蔗候。 一個(gè)月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像埂软,于是被迫代替她去往敵國和親锈遥。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容