diff --git a/article/migrations/0002_article_author.py b/article/migrations/0002_article_author.py new file mode 100644 index 0000000..3df5f6b --- /dev/null +++ b/article/migrations/0002_article_author.py @@ -0,0 +1,21 @@ +# Generated by Django 3.1.3 on 2022-09-22 21:50 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('article', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='article', + name='author', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='articles', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/article/models.py b/article/models.py index c2e0efa..2181105 100644 --- a/article/models.py +++ b/article/models.py @@ -1,9 +1,17 @@ from django.db import models from django.utils import timezone +from django.contrib.auth.models import User # 博客文章 model class Article(models.Model): + # 作者 + author = models.ForeignKey( + User, + null=True, + on_delete=models.CASCADE, + related_name='articles' + ) # 标题 title = models.CharField(max_length=100) # 正文 diff --git a/article/permissions.py b/article/permissions.py new file mode 100644 index 0000000..c64cf88 --- /dev/null +++ b/article/permissions.py @@ -0,0 +1,16 @@ +from rest_framework import permissions + + +class IsAdminUserOrReadOnly(permissions.BasePermission): + """ + 仅管理员用户可以进行修改 + 其他用户仅可进行查看 + """ + # 每次请求到来时被唤醒执行 + def has_permission(self, request, view): + # 对其他仅允许GET, HEAD, OPTIONS请求 + if request.method in permissions.SAFE_METHODS: + return True + # 仅管理员可进行其他操作 + return request.user.is_superuser + diff --git a/article/serializers.py b/article/serializers.py index 0fe0a23..79831fb 100644 --- a/article/serializers.py +++ b/article/serializers.py @@ -1,19 +1,29 @@ from rest_framework import serializers from article.models import Article +from user_info.serializers import UserDescSerializer + # 返回文章列表或创建一篇文章 class ArticleListSerializer(serializers.ModelSerializer): + author = UserDescSerializer(read_only=True) + # 使用article的url.py中的view --> detail + url = serializers.HyperlinkedIdentityField(view_name="article:detail") + class Meta: model = Article fields = [ - 'id', + 'url', 'title', 'created', 'body', + 'author', ] + # read_only_fields = ['author'] + + # 返回文章详情 + -# 返回文章详情 class ArticleDetailSerializer(serializers.ModelSerializer): class Meta: model = Article - fields = '__all__' + fields = '__all__' \ No newline at end of file diff --git a/article/views.py b/article/views.py index 710faf0..4e16769 100644 --- a/article/views.py +++ b/article/views.py @@ -7,6 +7,7 @@ from django.http import Http404 from rest_framework import mixins from rest_framework import generics from rest_framework import status +from article.permissions import IsAdminUserOrReadOnly @api_view(['GET', 'POST']) @@ -27,9 +28,15 @@ def article_list(request): # 和article_list()功能相同 class ArticleList(generics.ListCreateAPIView): + # 添加用户权限 + permission_classes = [IsAdminUserOrReadOnly] queryset = Article.objects.all() serializer_class = ArticleListSerializer + def perform_create(self, serializer): + # 在序列化数据真正保存之前调用 + serializer.save(author=self.request.user) + # 第一种版本 @@ -89,5 +96,6 @@ class ArticleList(generics.ListCreateAPIView): # ArticleDetail类还可以简化为下面的代码 class ArticleDetail(generics.RetrieveUpdateDestroyAPIView): + permission_classes = [IsAdminUserOrReadOnly] queryset = Article.objects.all() serializer_class = ArticleDetailSerializer diff --git a/db.sqlite3 b/db.sqlite3 index 93fb8ec..cbb0937 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/drf_vue_blog/settings.py b/drf_vue_blog/settings.py index 66d4a7b..2cf0d36 100644 --- a/drf_vue_blog/settings.py +++ b/drf_vue_blog/settings.py @@ -27,6 +27,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'rest_framework', 'article', + 'user_info', ] MIDDLEWARE = [ @@ -109,3 +110,9 @@ USE_TZ = False # https://docs.djangoproject.com/en/3.1/howto/static-files/ STATIC_URL = '/static/' + +# 使用django_rest_framework中的分页功能 +REST_FRAMEWORK = { + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'PAGE_SIZE': 3, # 每页3条记录 +} \ No newline at end of file diff --git a/user_info/__init__.py b/user_info/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/user_info/admin.py b/user_info/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/user_info/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/user_info/apps.py b/user_info/apps.py new file mode 100644 index 0000000..1bf3bab --- /dev/null +++ b/user_info/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class UserInfoConfig(AppConfig): + name = 'user_info' diff --git a/user_info/migrations/__init__.py b/user_info/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/user_info/models.py b/user_info/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/user_info/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/user_info/serializers.py b/user_info/serializers.py new file mode 100644 index 0000000..3783888 --- /dev/null +++ b/user_info/serializers.py @@ -0,0 +1,15 @@ +from django.contrib.auth.models import User +from rest_framework import serializers + + +class UserDescSerializer(serializers.ModelSerializer): + """文章列表中引用的嵌套序列化器""" + + class Meta: + model = User + fields = [ + 'id', + 'username', + # 'last_login', + # 'date_joined' + ] diff --git a/user_info/tests.py b/user_info/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/user_info/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/user_info/views.py b/user_info/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/user_info/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here.