摘要:博客網(wǎng)站的用戶信息并不復(fù)雜,因此擴(kuò)展就足夠了??梢栽谶@個(gè)基礎(chǔ)上,擴(kuò)展為一個(gè)美觀詳細(xì)的用戶信息頁面。當(dāng)然最好再給個(gè)人信息添加一個(gè)入口。沒有對用戶的登錄狀態(tài)進(jìn)行檢查??偨Y(jié)本章使用一對一鏈接的方式,擴(kuò)展并更新了用戶信息。
可能你已經(jīng)發(fā)現(xiàn)了,Django自帶的User模型非常實(shí)用,以至于我們沒有寫用戶管理相關(guān)的任何模型。
但是自帶的User畢竟可用的字段較少。比方說非常重要的電話號碼、頭像等都沒有。解決的方法有很多,你可以不使用User,自己從零寫用戶模型;也可以對User模型進(jìn)行擴(kuò)展。
博客網(wǎng)站的用戶信息并不復(fù)雜,因此擴(kuò)展User就足夠了。
擴(kuò)展User模型擴(kuò)展User模型又有不同的方法。在大多數(shù)情況下,使用模型一對一鏈接的方法是比較適合的。
編寫userprofile/models.py如下:
userprofile/models.py from django.db import models from django.contrib.auth.models import User # 引入內(nèi)置信號 from django.db.models.signals import post_save # 引入信號接收器的裝飾器 from django.dispatch import receiver # 用戶擴(kuò)展信息 class Profile(models.Model): # 與 User 模型構(gòu)成一對一的關(guān)系 user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile") # 電話號碼字段 phone = models.CharField(max_length=20, blank=True) # 頭像 avatar = models.ImageField(upload_to="avatar/%Y%m%d/", blank=True) # 個(gè)人簡介 bio = models.TextField(max_length=500, blank=True) def __str__(self): return "user {}".format(self.user.username) # 信號接收函數(shù),每當(dāng)新建 User 實(shí)例時(shí)自動(dòng)調(diào)用 @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: Profile.objects.create(user=instance) # 信號接收函數(shù),每當(dāng)更新 User 實(shí)例時(shí)自動(dòng)調(diào)用 @receiver(post_save, sender=User) def save_user_profile(sender, instance, **kwargs): instance.profile.save()
每個(gè)Profile模型對應(yīng)唯一的一個(gè)User模型,形成了對User的外接擴(kuò)展,因此你可以在Profile添加任何想要的字段。這種方法的好處是不需要對User進(jìn)行任何改動(dòng),從而擁有完全自定義的數(shù)據(jù)表。模型本身沒有什么新的知識,比較神奇的是用到的信號機(jī)制。
Django包含一個(gè)“信號調(diào)度程序”,它可以在框架中的某些位置發(fā)生操作時(shí),通知其他應(yīng)用程序。簡而言之,信號允許某些發(fā)送者通知一組接收器已經(jīng)發(fā)生了某個(gè)動(dòng)作。當(dāng)許多代碼可能對同一事件感興趣時(shí),信號就特別有用。
這里引入的post_save就是一個(gè)內(nèi)置信號,它可以在模型調(diào)用save()方法后發(fā)出信號。
有了信號之后還需要定義接收器,告訴Django應(yīng)該把信號發(fā)給誰。裝飾器receiver就起到接收器的作用。每當(dāng)User有更新時(shí),就發(fā)送一個(gè)信號啟動(dòng)post_save相關(guān)的函數(shù)。
通過信號的傳遞,實(shí)現(xiàn)了每當(dāng)User創(chuàng)建/更新時(shí),Profile也會(huì)自動(dòng)的創(chuàng)建/更新。
當(dāng)然你也可以不使用信號來自動(dòng)創(chuàng)建Profile表,而是采用手動(dòng)方式實(shí)現(xiàn)。重建數(shù)據(jù)庫為什么刪除User表不需要信號?答案是兩者的關(guān)系采用了models.CASCADE級聯(lián)刪除,已經(jīng)帶有關(guān)聯(lián)刪除的功能了。
avatar字段用來存放頭像,暫且不管它,下一章講解。
前面講過,每次改動(dòng)模型后都需要進(jìn)行數(shù)據(jù)的遷移。由于avatar字段為圖像字段,需要安裝第三方庫Pillow來支持:
(env) E:django_projectmy_blog> pip install Pillow
安裝成功后,通過makemigrations、migrate遷移數(shù)據(jù):
(env) E:django_projectmy_blog>python manage.py makemigrations Migrations for "userprofile": userprofilemigrations