diff --git a/backend/decoraters.py b/backend/decoraters.py index ab6efca3e7b6c58e5c7da867390eb0ebbe7307dd..8efe48f7d75d6429594fd9a655645ff1be0df2a7 100644 --- a/backend/decoraters.py +++ b/backend/decoraters.py @@ -1,6 +1,6 @@ from functools import wraps -SAFE_ACTIONS = ('list',) +SAFE_ACTIONS = ('list', 'retrieve') SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS') diff --git a/backend/exceptions.py b/backend/exceptions.py index 253d3c33d99f09f8bf20f8734a64e58af88cffe3..48c5d24216329e65a127ea01b7c12ceb41c062b6 100644 --- a/backend/exceptions.py +++ b/backend/exceptions.py @@ -1,7 +1,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.db import DataError from rest_framework import status -from rest_framework.exceptions import ValidationError, PermissionDenied +from rest_framework.exceptions import ValidationError, PermissionDenied, NotAuthenticated from rest_framework.response import Response from rest_framework.views import exception_handler @@ -34,6 +34,12 @@ def custom_exception_handler(exc, handler): 'error_msg': exc.detail }, status=status.HTTP_403_FORBIDDEN) + elif isinstance(exc, NotAuthenticated): + response = Response(data={ + 'code': 401, + 'error_msg': exc.detail + }, status=status.HTTP_401_UNAUTHORIZED) + elif isinstance(exc, Exception): response = Response(data={ 'code': 500, diff --git a/backend/permissions.py b/backend/permissions.py index a394dc32e8a2edc43e4fe876ad0fc3b1d1fd3104..722b7750023e7f30f5e8810f9fa0a6987fa3fbe0 100644 --- a/backend/permissions.py +++ b/backend/permissions.py @@ -76,6 +76,7 @@ class IsManualAuthenticatedOrReadOnly(BasePermission): request.user and user_info.is_manual_authenticated) + @pass_safe_method def has_object_permission(self, request, view, obj): user = request.user if user.is_staff: diff --git a/users/models.py b/users/models.py index 7ffec2756d1c67ac622b00f0ca2b40aede23aa01..8b730065a8c7dbb9503ef56acfea4432f060942f 100644 --- a/users/models.py +++ b/users/models.py @@ -95,14 +95,6 @@ class UserInfo(User): db_constraint=False ) - fans = models.ManyToManyField( - verbose_name='粉丝', - to='UserInfo', - db_constraint=False, - blank=True, - related_query_name='follows' - ) - # permissions: is_manual_authenticated = models.BooleanField( '人工认证', default=False, help_text=( diff --git a/users/serializers.py b/users/serializers.py index 06f8c6bd7795f819a2b774f4c28480ccec0691f6..4cfc1e52964834ef2b71032ddc0450cda2f2a225 100644 --- a/users/serializers.py +++ b/users/serializers.py @@ -163,31 +163,3 @@ class ResetPasswordSerializer(serializers.Serializer): instance.set_password(validated_data['password']) instance.save() return instance - - -class FanFollowDetailSerializer(serializers.ModelSerializer): - school = serializers.SerializerMethodField() - subject = serializers.SerializerMethodField() - - class Meta: - model = UserInfo - fields = [ - 'id', 'first_name', 'last_name', - 'school', 'position', - 'subject', 'avatar' - ] - - def get_school(self, obj): - school = obj.school - return school.school_name if school else None - - def get_subject(self, obj): - subject = obj.subject - return subject.cate_name if subject else None - - -class UserFansSerializer(serializers.ModelSerializer): - - class Meta: - model = UserInfo - fields = ['id', 'username'] diff --git a/users/tests.py b/users/tests.py index eb0436e90255215eda8e90db0af35957e60ae16c..b740aa742eb6799ea0cea1d5f852561bcbd61580 100644 --- a/users/tests.py +++ b/users/tests.py @@ -1,92 +1,3 @@ -# 写的什么东西?我不写 test 还发现不了,django 的 test 是你这样写的? -# import re # 正则 -# from collections import OrderedDict # 创建有序字典 -# -# from django.conf import settings # 导入setting配置文件(获取项目根路径urls.py) -# from django.urls import URLPattern, URLResolver # Django自定义的类,可以判断当前URL是否为根路径(URLPattern)或继续向下分发(URLResolver ) -# from django.utils.module_loading import import_string # 字符串导入模块 -# -# -# def check_url_exclude(url): -# """ -# 排除一些特定的URL -# :param url: 待检验的URL -# :return: -# """ -# for regex in settings.AUTO_DISCOVER_EXCLUDE: # 将要定向排除的URL(可包含正则) 按照列表的形式写入配置文件 settings.AUTO_DISCOVER_EXCLUDE 下 -# if re.match(regex, url): -# return True -# -# -# """ -# 示例: -# AUTO_DISCOVER_EXCLUDE = [ -# '/admin/.*', -# '/login/', -# '/logout/', -# '/index/', -# ] -# """ -# -# -# def recursion_urls(pre_namespace, pre_url, urlpatterns, url_ordered_dict): -# """ -# 递归的去获取URL -# :param pre_namespace: namespace前缀,用于拼接name -# :param pre_url: url前缀,用于拼接url -# :param urlpatterns: 路由关系列表 -# :param url_ordered_dict: 用于保存递归中获取的所有路由 -# :return: -# """ -# for item in urlpatterns: -# if isinstance(item, URLPattern): # 已经是根网址,获取name及url写入url_ordered_dict -# if not item.name: # 没有别名(name)的路由地址直接跳过 -# continue -# # 拼接路由别名(包含分发下来的namespace;如 "rbac:menu_list") -# if pre_namespace: -# name = "%s:%s" % (pre_namespace, item.name) -# else: -# name = item.name -# # 拼接路由地址URl(包含分发下来的上层路由;如 "/rbac/menu/list") -# url = pre_url + item.pattern.regex.pattern # 此时拼接的路由包含起止符号,如:/^rbac/^menu/list/$ -# url = url.replace("^", "").replace("$", "") # 删除起止符:/rbac/menu/list/ -# # 排除一些特定的路由URL -# if check_url_exclude(url): # 调用check_url_exclude函数定向排除部分URL -# continue -# url_ordered_dict[name] = {"name": name, "url": url} -# -# elif isinstance(item, URLResolver): # 路由分发,递归操作 -# if pre_namespace: # 上次循环(上一层)分发是否包含namespace -# if item.namespace: # 本次循环(当前层)是否包含namespace -# namespace = "%s:%s" % (pre_namespace, item.namespace,) # 上层、当前层都包含直接拼接两层的namespace -# else: -# namespace = pre_namespace # 当前层分发不包含namespace,直接用上一层的 -# else: -# if item.namespace: -# namespace = item.namespace # 上一层分发不包含namespace,直接使用当前层的 -# else: -# namespace = None # 上一层、当前层都没有,直接定义层none -# recursion_urls(namespace, pre_url + item.pattern.regex.pattern, item.url_patterns, -# url_ordered_dict) # 递归继续执行 -# -# -# def get_all_url_dict(): -# """ -# 获取项目所有路由 -# :return: -# """ -# url_ordered_dict = OrderedDict() # 包含本项目所有权限URl的有序字典 -# md = import_string(settings.ROOT_URLCONF) # 配置文件内的 ROOT_URLCONF 为本项目根路由urls.py 的路径(字符串),使用 import_string 用字符串加载模块 -# recursion_urls(None, "/", md.urlpatterns, -# url_ordered_dict) # 调用 recursion_urls 函数获取所有路由字典,根路径下没有namespace 定义为 None;没有url前缀 定义为 / -# return url_ordered_dict -# -# -# if __name__ == '__main__': -# -# dict = get_all_url_dict() - - from django.test import TestCase from users.models import UserNode diff --git a/users/views/user_api.py b/users/views/user_api.py index ce98bbca3cdbd41b0e60c9b073f67336c124f753..76ef9ddaaad5bc151db163f04b70b7fbe090c568 100644 --- a/users/views/user_api.py +++ b/users/views/user_api.py @@ -14,7 +14,7 @@ from users.models import UserInfo, UserTitle, UserNode from users.serializers import ( UserTitleSerializer, UserProfileSerializer, - ResetPasswordSerializer, FanFollowDetailSerializer + ResetPasswordSerializer ) from users.utils import get_user_by_email_or_phone @@ -77,8 +77,7 @@ class UserInfoViewSet(ModelViewSet): upload_avatar(request) @action(methods=['GET'], detail=True, - permission_classes=[permissions.AllowAny], - serializer_class=[FanFollowDetailSerializer]) + permission_classes=[permissions.AllowAny]) def fans(self, request, pk): """ 用户的粉丝列表 @@ -106,8 +105,7 @@ class UserInfoViewSet(ModelViewSet): ) @action(methods=['GET'], detail=True, - permission_classes=[permissions.AllowAny], - serializer_class=[FanFollowDetailSerializer]) + permission_classes=[permissions.AllowAny]) def follows(self, request, pk): """ 用户的关注列表