From 3ac5761bc8d3045ec3b477606b2030eb16bf5510 Mon Sep 17 00:00:00 2001 From: kongfp Date: Mon, 14 Aug 2023 13:28:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7=E3=80=81?= =?UTF-8?q?=E9=83=A8=E9=97=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- XZNSH_API/urls.py | 1 + app/urls.py | 2 - app/views.py | 62 ---------- user/models.py | 19 +++- user/serializers.py | 84 ++++++++++++++ user/urls.py | 17 +++ user/views.py | 268 +++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 385 insertions(+), 68 deletions(-) create mode 100644 user/serializers.py create mode 100644 user/urls.py diff --git a/XZNSH_API/urls.py b/XZNSH_API/urls.py index 13592fd..c1e70af 100644 --- a/XZNSH_API/urls.py +++ b/XZNSH_API/urls.py @@ -25,6 +25,7 @@ urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('app.urls')), path('event/', include('event.urls')), + path('api/organization/', include('user.urls')), ] diff --git a/app/urls.py b/app/urls.py index b05f915..1bb9739 100644 --- a/app/urls.py +++ b/app/urls.py @@ -23,8 +23,6 @@ router.register('', views.XZNSHModelViewSet) urlpatterns = [ path('', include(router.urls)), - path('add_user', views.RegisterLoginViewSet.as_view({"post": "register"})), - path('login', views.LoginView.as_view({"post": "login"})), path('events', views.XZNSHModelViewSet.as_view({"get": "get_events"})), path('scenes', views.XZNSHModelViewSet.as_view({"get": "get_scenes"})), path('violation_reasons', views.XZNSHModelViewSet.as_view({"get": "get_violation_reason"})) diff --git a/app/views.py b/app/views.py index b429763..11f9646 100644 --- a/app/views.py +++ b/app/views.py @@ -22,7 +22,6 @@ class XZNSHModelViewSet(viewsets.ModelViewSet): serializer_class = SerialMyModel # 分页类 pagination_class = MyPageNumberPagination - # 条件筛选 filterset_class = SerialFilter @@ -54,64 +53,3 @@ class XZNSHModelViewSet(viewsets.ModelViewSet): } return response - -class RegisterLoginViewSet(viewsets.ModelViewSet): - def register(self, request, *args, **kwargs): - """注册 POST""" - # 判断用户是否为管理员 - # user = request.user - # if not user.is_superuser: - # return Response({'msg': '您不是管理员,无权限添加成员'}) - data = request.data - username = data.get('username') - password = data.get('password') - try: - if UserProfile.objects.filter(username=username).first(): - return Response({'msg': '该用户名已存在,请换一个'}) - UserProfile.objects.create_user(username=username, password=password) - return Response({'msg': '注册成功'}) - except Exception as e: - logger.info(e) - response = { - "msg": f'注册失败, 原因:{e}' - } - return Response(response) - - -class LoginView(viewsets.ModelViewSet): - def login(self, request, *args, **kwargs): - """登录 POST""" - data = request.data - username = data.get('username') - password = data.get('password') - login_user = authenticate(username=username, password=password) - if login_user and login_user.is_active: - # 生成token - token = generate_token(login_user) - response = { - 'success': True, - 'msg': '登录成功', - 'data': { - 'username': login_user.username, - 'roles': ['admin'] if login_user.is_superuser else ['common'], - 'accessToken': token, - 'expires': decode_token_exp_time(token) - } - } - return Response(response) - else: - response = { - 'success': False, - 'msg': '登录失败', - 'data': { - 'username': None, - 'roles': [], - 'accessToken': None, - 'expires': None - } - } - return Response(response) - - def logout(self, request, *args, **kwargs): - """登出 GET""" - pass diff --git a/user/models.py b/user/models.py index 934d813..9602e68 100644 --- a/user/models.py +++ b/user/models.py @@ -4,17 +4,30 @@ from django.db import models # Create your models here. +class Department(models.Model): + name = models.CharField(max_length=128, verbose_name='部门名称') + parent_id = models.IntegerField(verbose_name='上级部门id', null=True, blank=True) + is_active = models.BooleanField(default=True, verbose_name="是否启用") + status = models.IntegerField(verbose_name='状态', default=1) + insert_time = models.DateTimeField(auto_now_add=True, verbose_name='插入时间') + update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间') + + class Meta: + db_table = 'department' + + class UserProfile(AbstractUser): GENDER = ((0, '女'), (1, '男')) organization = models.CharField(max_length=256, verbose_name='组织', null=True, blank=True) gender = models.IntegerField(choices=GENDER, default=1, verbose_name='性别') phone_number = models.CharField(max_length=12, verbose_name='手机号', null=True, blank=True) head_sculpture = models.CharField(max_length=512, verbose_name='头像', blank=True, null=True) - status = models.IntegerField(verbose_name='状态', default=0) - recorder_number = models.CharField(max_length=256, verbose_name='执法记录仪编号', null=True, blank=True) + status = models.IntegerField(verbose_name='状态', default=1) + department = models.ForeignKey(Department, on_delete=models.DO_NOTHING, null=True) + insert_time = models.DateTimeField(auto_now_add=True, verbose_name='插入时间') + update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'xznsh_user' - diff --git a/user/serializers.py b/user/serializers.py new file mode 100644 index 0000000..4c65f28 --- /dev/null +++ b/user/serializers.py @@ -0,0 +1,84 @@ +import datetime + +from rest_framework import serializers +from django_filters.rest_framework import FilterSet, DjangoFilterBackend +import django_filters +from user.models import UserProfile, Department +import logging +from django.contrib.auth.hashers import make_password + +logger = logging.getLogger('mylogger') + + +class UserSerializer(serializers.ModelSerializer): + department_name = serializers.SerializerMethodField() + + def to_internal_value(self, data): + password = data.get("password") + if password: + data["password"] = make_password(password) + + ret = super().to_internal_value(data) + return ret + + def to_representation(self, instance: UserProfile): + ret = super().to_representation(instance) + ret["gender_display"] = instance.get_gender_display() + ret["department_id"] = instance.department_id + return ret + + def get_department_name(self, obj: UserProfile): + department_name = "" + if obj.department: + department_name = obj.department.name + + return department_name + + class Meta: + model = UserProfile + fields = "__all__" + + extra_kwargs = { + "password": {"write_only": True}, + } + + +class UserFilter(FilterSet): + """ + 过滤器,支持模糊查询 + """ + # department_id = django_filters.NumberFilter(field_name='department') + username = django_filters.CharFilter(field_name='username', lookup_expr='icontains') + phone_number = django_filters.CharFilter(field_name='phone_number', lookup_expr='icontains') + is_superuser = django_filters.BooleanFilter(field_name='is_superuser') + is_active = django_filters.BooleanFilter(field_name='is_active') + + class Meta: + # 指定模型 + models = UserProfile + # 指定需要模糊查询的字段 + fields = ("username", "phone_number", "is_superuser", "is_active") + + +class DepartmentSerializer(serializers.ModelSerializer): + + class Meta: + model = Department + fields = "__all__" + depth = 1 + + +class DepartmentFilter(FilterSet): + """ + 过滤器,支持模糊查询 + """ + name = django_filters.CharFilter(field_name='name', lookup_expr='icontains') + parent_id = django_filters.NumberFilter(field_name='parent_id') + department_id = django_filters.NumberFilter(field_name='id') + is_active = django_filters.BooleanFilter(field_name='is_active') + + class Meta: + # 指定模型 + models = Department + # 指定需要模糊查询的字段 + fields = ("name", "parent_id", "department_id", "is_active") diff --git a/user/urls.py b/user/urls.py new file mode 100644 index 0000000..9c5997e --- /dev/null +++ b/user/urls.py @@ -0,0 +1,17 @@ +from django.urls import path, include, re_path +from rest_framework.routers import DefaultRouter +from user import views + +router = DefaultRouter() +router.register('departments', views.DepartmentViewSet) + +urlpatterns = [ + path('trees/', views.DepartmentViewSet.as_view({"get": "get_trees"})), + path('login/', views.LoginView.as_view({"post": "login"})), + path('users/', views.UserViewSet.as_view({"post": "create", "get": "list"})), + path('users//', views.UserViewSet.as_view({'get': 'retrieve', + 'put': 'update', + 'delete': 'destroy'})), +] + +urlpatterns += router.urls diff --git a/user/views.py b/user/views.py index 91ea44a..6c3d168 100644 --- a/user/views.py +++ b/user/views.py @@ -1,3 +1,269 @@ -from django.shortcuts import render +import logging +from rest_framework import viewsets +from rest_framework.response import Response +from rest_framework import status +from app.pagination import MyPageNumberPagination +from user.models import UserProfile, Department +from django.contrib.auth import authenticate, login, logout +from app.utils import generate_token, decode_token_exp_time +from user.serializers import UserSerializer, UserFilter, DepartmentSerializer, DepartmentFilter +from rest_framework.exceptions import NotFound # Create your views here. +logger = logging.getLogger('mylogger') + + +class UserViewSet(viewsets.GenericViewSet): + # 查询类 + queryset = UserProfile.objects.filter(status=1).all().order_by("-id") # 按照uid倒序 + # 序列化类 + serializer_class = UserSerializer + # # 分页类 + pagination_class = MyPageNumberPagination + # + # 条件筛选 + filterset_class = UserFilter + + def create(self, request, *args, **kwargs): + department = request.data.pop("department_id", None) + request.data["department"] = department + + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response({ + "success": True, + "msg": "新增用户成功", + "data": serializer.data + }, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + department_id = dict(request.query_params).get("department_id", None) + if department_id and department_id != [""]: + department_id_list = self.get_children_department(department_id) + department_id_list.extend(department_id) + + queryset = self.filter_queryset(self.get_queryset().filter(department_id__in=department_id_list).all()) + else: + queryset = self.filter_queryset(self.get_queryset()) + + try: + page = self.paginate_queryset(queryset) + except NotFound as exc: + page = None + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(queryset, many=True) + return Response(serializer.data) + + def retrieve(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance) + return Response(serializer.data) + + def update(self, request, *args, **kwargs): + department = request.data.pop("department_id", None) + request.data["department"] = department + partial = kwargs.pop('partial', True) + instance = self.get_object() + serializer = self.get_serializer(instance, data=request.data, partial=partial) + serializer.is_valid(raise_exception=True) + serializer.save() + + if getattr(instance, '_prefetched_objects_cache', None): + # If 'prefetch_related' has been applied to a queryset, we need to + # forcibly invalidate the prefetch cache on the instance. + instance._prefetched_objects_cache = {} + + return Response({ + "success": True, + "msg": "新增修改成功", + "data": serializer.data + }) + + def destroy(self, request, *args, **kwargs): + instance = self.get_object() # type: UserProfile + instance.status = 0 + instance.save() + return Response({"success": True, "msg": "用户删除成功"}) + + def get_children_department(self, parents): + + res = [] + for parent in parents: + + children_list = Department.objects.filter(parent_id=parent).values_list('id', flat=True).distinct() + if children_list: + res.extend(children_list) + children_ids = self.get_children_department(children_list) + res.extend(children_ids) + + return res + + +class LoginView(viewsets.ModelViewSet): + + def login(self, request, *args, **kwargs): + """登录 POST""" + data = request.data + username = data.get('username') + password = data.get('password') + login_user = authenticate(username=username, password=password) + if login_user and login_user.is_active and login_user.status: + # 生成token + token = generate_token(login_user) + response = { + 'success': True, + 'msg': '登录成功', + 'data': { + 'username': login_user.username, + 'roles': ['admin'] if login_user.is_superuser else ['common'], + 'accessToken': token, + 'expires': decode_token_exp_time(token) + } + } + return Response(response) + else: + response = { + 'success': False, + 'msg': '登录失败', + 'data': { + 'username': None, + 'roles': [], + 'accessToken': None, + 'expires': None + } + } + return Response(response) + + def logout(self, request, *args, **kwargs): + """登出 GET""" + pass + + +class RegisterLoginViewSet(viewsets.ModelViewSet): + def register(self, request, *args, **kwargs): + """注册 POST""" + # 判断用户是否为管理员 + # user = request.user + # if not user.is_superuser: + # return Response({'msg': '您不是管理员,无权限添加成员'}) + data = request.data + username = data.get('username') + password = data.get('password') + try: + if UserProfile.objects.filter(username=username).first(): + return Response({'msg': '该用户名已存在,请换一个'}) + UserProfile.objects.create_user(username=username, password=password) + return Response({'msg': '注册成功'}) + except Exception as e: + logger.info(e) + response = { + "msg": f'注册失败, 原因:{e}' + } + return Response(response) + + +class DepartmentViewSet(viewsets.ModelViewSet): + # 查询类 + queryset = Department.objects.filter(status=1).all() + # 序列化类 + serializer_class = DepartmentSerializer + # # 分页类 + pagination_class = MyPageNumberPagination + # 条件筛选 + filterset_class = DepartmentFilter + + def create(self, request, *args, **kwargs): + name = request.data.pop("department_name", None) + if not name: + return Response({"msg": "部门名称必须存在", "success": False}) + + parent_id = request.data.pop("department_id", None) or None + flag = self.is_exist(name, parent_id) + + if flag: + return Response({"msg": "该部门已存在", "success": False}) + + request.data["name"] = name + request.data["parent_id"] = parent_id + + response = super().create(request, *args, **kwargs) + data = response.data + res = { + "success": True, + "msg": "部门创建成功", + "data": data + } + response.data = res + return response + + def update(self, request, *args, **kwargs): + name = request.data.get("name", None) + department = request.data.get("department_id", None) + + instance = self.get_object() + if name and department != instance.parent_id: + flag = self.is_exist(name, department) + if flag: + return Response({"msg": "该部门已存在", "success": False}) + + # request.data["name"] = name + kwargs["partial"] = True + response = super().update(request, *args, **kwargs) + + data = response.data + res = { + "success": True, + "msg": "部门更新成功", + "data": data + } + response.data = res + + return response + + def destroy(self, request, *args, **kwargs): + instance = self.get_object() # type: Department + instance.status = 0 + instance.save() + return Response({"success": True, "msg": "部门删除成功"}) + + def is_exist(self, name, parent_id): + is_exist = self.get_queryset().filter(status=1, name=name, parent_id=parent_id).exists() + return is_exist + + def get_trees(self, request, *args, **kwargs): + flag = request.query_params.get("users", False) + roots = self.get_queryset().filter(parent_id=None) + res = self.get_children(roots, flag) + + response = { + 'success': True, + 'msg': '查询成功', + 'data': res + } + + return Response(response) + + def get_children(self, parents, users_flag=False): + + res = [] + for parent in parents: + parent_data = self.serializer_class(parent).data + if users_flag: + users = UserProfile.objects.filter(status=1).filter(department=parent.id).all() + users_data = UserSerializer(users, many=True).data + parent_data["users"] = users_data + + children = self.get_queryset().filter(parent_id=parent.id) + children_data = [] + if children: + children_data = self.get_children(children, users_flag) + parent_data["children"] = children_data + + res.append(parent_data) + + return res +