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