django-Vue搭建博客:文章关联用户

权限是 web 应用的重要组成部分。没有权限控制,任何人的请求都会对数据资源进行操控,那就乱套了。

本章就来学习 drf 中如何进行权限管理。

教程来源杜塞-django-vue系列
博客链接 传送门

上一章我们已经将用户以外键的形式关联到文章中,但是由于 author字段允许为空,所以理论上我们上一节发表的文章是没有作者的文章:

>http http://127.0.0.1:8000/api/article/8/
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 124
Content-Type: application/json
Date: Mon, 14 Jun 2021 05:43:30 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "author": null,
    "body": "",
    "created": "2021-06-13T15:01:15.586622",
    "id": 8,
    "title": "may",
    "updated": "2021-06-13T15:01:15.586622"
}

我们可以对文章直接赋予作者(也可以伪造作者):

>http -a xianwei:admin123456 POST http://127.0.0.1:8000/api/article/ title=python body=python author=999
HTTP/1.1 400 Bad Request
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 58
Content-Type: application/json
Date: Mon, 14 Jun 2021 06:09:51 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "author": [
        "Invalid pk \"999\" - object does not exist."
    ]
}

解决这个问题,既然请求中带有作者信息,那我们就可以从request中提取用户信息,并额外存储到数据中。

修改视图:

# article/views.py

class ArticleList(generics.ListCreateAPIView):
    ···
    # 新增,存储用户作者
    def perform_create(self, serializer):
        serializer.save(author=self.request.user)
  • 新增的这个 perform_create()从父类 ListCreateAPIView继承而来,它在序列化数据真正保存之前调用,因此可以在这里添加额外的数据(即用户对象)。
  • serializerv参数是 ArticleListSerializer序列化器实例,并且已经携带着验证后的数据。它的 save()方法可以接收关键字参数作为额外的需要保存的数据。

在命令行重新测试:

>http -a xianwei:admin123456 POST http://127.0.0.1:8000/api/article/ title="user" body="with user"
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 132
Content-Type: application/json
Date: Mon, 14 Jun 2021 06:00:30 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "author": 3,
    "body": "with user",
    "created": "2021-06-14T14:00:30.477454",
    "id": 11,
    "title": "user",
    "updated": "2021-06-14T14:00:30.477454"
}

id=3,是因为我有三个用户。
但是我们仍可以手动传错误的 author

>http -a xianwei:admin123456 POST http://127.0.0.1:8000/api/article/ title=java body=java author=999
HTTP/1.1 400 Bad Request
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 58
Content-Type: application/json
Date: Mon, 14 Jun 2021 06:10:40 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "author": [
        "Invalid pk \"999\" - object does not exist."
    ]
}

好在序列化器中允许你指定只读字段,修改序列化器:

# article/serializers.py

class ArticleListSerializer(serializers.ModelSerializer):
    class Meta:
		···
`		# 新增
        read_only_fields = ['author']

我们再次发送POST创建文章请求时,序列化器就不理会我们请求中附带的 author数据了。

>http -a xianwei:admin123456 POST http://127.0.0.1:8000/api/article/ title=sss body=ddd author=999
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 62
Content-Type: application/json
Date: Mon, 14 Jun 2021 06:16:24 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "created": "2021-06-14T14:16:24.718403",
    "id": 12,
    "title": "sss"
}

显示用户信息

虽然作者外键关联到了文章中,但我们只能查看到作者id,而不能看到其姓名等其他信息,所以我们要把作者具体信息嵌入文章信息中。

新建 app ,用来绑定用户信息(记得注册到setting文件内):

(env) > python manage.py startapp user_info

在user_info内新建序列化器:

# user_info/serializers.py

from rest_framework import serializers
from django.contrib.auth.models import User
class UserDescSerializer(serializers.ModelSerializer):

    """与文章列表中引用的嵌套序列化器"""

    class Meta:
        model = User
        fields=[
            'id',
            'username',
            'last_login',
            'date_joined',
        ]

序列化器我们已经熟悉了,这个序列化器用在文章列表中,用来展示作者基本信息。

最后修改文章列表的序列化器,把他们嵌套起来:

# article/serializers.py
# 这里我们要把author字段添加进fields内
from user_info.serializers import UserDescSerializer

class ArticleListSerializer(serializers.ModelSerializer):
    # read_only 参数设置为只读
    author = UserDescSerializer(read_only=True)

    class Meta:
        model = Article
        fields = [
            'id',
            'title',
            'created',
            'author',
        ]

这就 OK 了,在命令行测试一下:

>http http://127.0.0.1:8000/api/article/
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 549
Content-Type: application/json
Date: Mon, 14 Jun 2021 06:34:25 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.9.4
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

[
    {
        "author": null,
        "created": "2021-06-13T15:01:15.586622",
        "id": 8,
        "title": "may"
    },
	···
]

任务完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值