Django 个人博客教程-03:用户模型和博客链接

上一篇文章中,我们自定义了 slug 模型字段和将分类和标签写到同一个模型类中。这篇文章主要继续编写用户模型和博客链接模型。

Step1、扩展用户模型

Django 自带用户模型 User 类,这里我们直接用 OneToOneField 的外键联接自带的 User 类。

在 docspace/models.py 中添加下面代码:

from django.db import models
from django.conf import settings
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.contrib.auth import get_user_model

User = get_user_model()


class Profile(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.RESTRICT
    )
    mobile = models.CharField(
        max_length=16,
        blank=True, null=True,
        verbose_name=_("Mobile phone number")
    )
    website = models.URLField(
        blank=True, null=True,
        verbose_name=_("Website"),
    )
    role = models.SlugField(
        default='editor',
        verbose_name=_("User role"),
    )
    resume = models.TextField(
        blank=True, null=True,
        verbose_name=_("Personal profile"),
    )

    def __str__(self):
        """
        用户有 nickname 则优先返回它,否则返回用户 username
        """

        return self.nickname or self.user.username
    
    class Meta:
        verbose_name = _('Profile')
        verbose_name_plural = _('Profiles')


@receiver(post_save, sender=User)
def create_or_save_user_profile(sender, instance, created, **kwargs):
    """
    通过信号,当用户创建的同时创建用户 Profile 实例
    同时当用户实例保存的时候也保存用户 Profile 实例数据
    usage:
        u = User.objects.get(pk=1)
        u.profile.role = 'admin'
        u.save()
    """

    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()

  1. 上面代码扩展了 Django 的用户,额外给用户添加了一些字段
  2. 通过模型的 post_save 信号自动为用户创建 Profile 实例数据

Step2、链接模型

作为一个博客程序来说,URL链接统一管理是很有必要的,比如自定义链接,友情链接,链接的打开方式,链接的类别等等。

链接模型比较独立,下面是参考 wordpress 中的链接数据库结构写的 Link 模型

继续在 docspace/models.py 中添加代码:

class Link(models.Model):
    mark = models.SlugField(
        allow_unicode=True, default='link',
        verbose_name=_("Link mark"),
    )
    name = models.CharField(
        max_length=255, verbose_name=_("Link name"),
    )
    url = models.URLField(
        max_length=255, verbose_name=_("Link url"),
    )
    image = models.CharField(
        max_length=255, verbose_name=_("Link image"),
        null=True, blank=True,
    )
    target = models.CharField(
        max_length=25, default='_blank',
        verbose_name=_("Link target"),
    )
    description = models.CharField(
        max_length=255, null=True, blank=True,
        verbose_name=_("Link description"),
    )
    visible = models.CharField(
        max_length=20, null=True, blank=True,
    )
    owner = models.ForeignKey(
        User, on_delete=models.SET_NULL,
        null=True, blank=True, related_name='links',
    )
    rating = models.IntegerField(
        default=0, verbose_name=_("Link rating"),
    )
    updated = models.DateTimeField(
        blank=True, null=True, default=datetime.now,
        verbose_name=_("Link updated"),
    )
    rel = models.CharField(
        max_length=255, default='friend',
        verbose_name=_("Link Relationship (XFN)"),
    )
    notes = models.TextField(
        null=True, blank=True, verbose_name=_("Link notes"),
    )
    rss = models.CharField(
        max_length=255, null=True, blank=True,
        verbose_name=_("RSS address"),
    )

    class Meta:
        verbose_name = _("Link")
        verbose_name_plural = _("Links")

    def __str__(self):
        return "{} {}".format(self.name, self.url)

    @property
    def is_visible(self):
        return self.visible == 'Y'

在 PC 时代,页面的外部链接和 SEO 有很大关联,虽然现在属于移动互联网时代了,很多应用都有自己的专门引流渠道。但作为个人独立博客来说,SEO 依旧还是主要的引流方式,因此这个单独起来管理还是很有必要的。


Step3、创建用户与检查用户 Profile 实例的生成

Django 在命令行创建一个超级用户并检查该用户的 Profile 实例数据是否正常生成。同样,我们先迁移本次创建的 Profile 和 Link 两个模型类,结果如下:

(env) PS C:\Users\shoutian\docspace> python .\manage.py makemigrations
Migrations for 'docspace':
docspace\migrations\0002_link_profile.py
- Create model Profile
- Create model Link
(env) PS C:\Users\shoutian\docspace> python .\manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, docspace, sessions
Running migrations:
Applying docspace.0002_link_profile... OK
(env) PS C:\Users\shoutian\docspace> echo 'admin'|python .\manage.py createsuperuser --username admin
Superuser creation skipped due to not running in a TTY. You can run `manage.py createsuperuser` in your project to create one manually.
(env) PS C:\Users\shoutian\docspace> python .\manage.py createsuperuser --username admin
Email address:
Password:
Password (again):
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
(env) PS C:\Users\shoutian\docspace> python .\manage.py shell
Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.contrib.auth import get_user_model
>>> from docspace.models import Profile
>>> u = get_user_model().objects.get(username='admin')
>>> u.profile
<Profile: admin>
>>> u.profile.role
'editor'
>>> u.profile.__dict__
{'_state': <django.db.models.base.ModelState object at 0x000002585972BC40>, 'id': 1, 'user_id': 1, 'nickname': None, 'mobile': None, 'website': None, 'role': 'editor', 'resume': None}
>>> u.profile.role = 'admin'
>>> u.save()
>>> u.profile.__dict__
{'_state': <django.db.models.base.ModelState object at 0x000002585972BC40>, 'id': 1, 'user_id': 1, 'nickname': None, 'mobile': None, 'website': None, 'role': 'admin', 'resume': None}
>>>

上面测试结果都和我们的预期是一样的。链接这一块这边暂时不谈,等我们到管理友情链接的时候再说。

到此,博客用户模型和博客链接模型已经写完,下一篇文章将进入模型设计的重点内容---文章模型和评论模型《Django 个人博客教程-04:文章模型和评论模型》


阅读说明:

...\> 这个开头表示Windows powershell下执行的指令

...]$ 这个开头表示Linux bash下执行的指令


系列文章:

  1. Django 个人博客教程-00:开篇
  2. Django 个人博客教程-01:开发环境与项目初始化
  3. 《Django 个人博客教程-02:自定义字段与模型抽象类》
  4. 《Django 个人博客教程-03:用户模型和博客链接》当前文章
  5. 《Django 个人博客教程-04:文章模型和评论模型》下一篇

如果觉得文章对你有用,请分享给其他人或点击在看



相关阅读RelatedRead

Django 个人博客教程-02:自定义字段与模型抽象类

Django利用xlrd将excel表格数据导入到model数据库中

django-idcops 部署线上生成环境

Django个人博客教程-1:开发环境之编译安装python3.7

Django个人博客教程-1:开发环境

Django个人博客教程:开篇

本博启用灰色调 2020年4月4日举行全国性哀悼活动

暂无评论添加评论