diff --git a/backend/settings.py b/backend/settings.py index 4ba518e271b2fa642dba31001adba74ca2d3b6e2..307c8b184f12fcdc06757e038838051affd1f640 100644 --- a/backend/settings.py +++ b/backend/settings.py @@ -64,6 +64,7 @@ INSTALLED_APPS = [ 'tag', 'notice', 'scratch', + 'campus', # --- DRF --- 'rest_framework', 'rest_framework.authtoken', diff --git a/backend/urls.py b/backend/urls.py index f183a1960e41d74fb9091afa24605c619b3efd15..f60b839b0b567f482c2fb86ae359670c3762aecb 100644 --- a/backend/urls.py +++ b/backend/urls.py @@ -80,6 +80,7 @@ urlpatterns = [ path('tag/', include('tag.urls')), path('notice/', include('notice.urls')), path('scratch/', include('scratch.urls')), + path('campus/', include('campus.url')) ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/campus/__init__.py b/campus/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/campus/admin.py b/campus/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..9598b87fe1a8d1f681d7baa5dd270f7071e53f29 --- /dev/null +++ b/campus/admin.py @@ -0,0 +1,14 @@ +# Register your models here. +from django.contrib import admin + +from .models import CampusOrganizations, CampusOrganizationsManager + + +@admin.register(CampusOrganizations) +class CampusOrganizationsAdmin(admin.ModelAdmin): + list_display = ['name', 'accept'] + + +@admin.register(CampusOrganizationsManager) +class CampusOrganizationsManagerAdmin(admin.ModelAdmin): + list_display = ['organization', 'accept'] diff --git a/campus/apps.py b/campus/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..2bbf3c47add2c29544dc3fecdc7bcfe747fe7347 --- /dev/null +++ b/campus/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CampusConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'campus' diff --git a/campus/migrations/__init__.py b/campus/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/campus/models.py b/campus/models.py new file mode 100644 index 0000000000000000000000000000000000000000..8131d51d06ac6ece9ed2a50c06b16ebe093e549c --- /dev/null +++ b/campus/models.py @@ -0,0 +1,101 @@ +from django.db import models + +import users.models + + +# Create your models here. +class CampusOrganizations(models.Model): + name = models.CharField( + max_length=32, + null=False, + blank=False + ) + avatar = models.URLField('头像', default=( + 'https://img.qiusuo-mc.cn/media/avatar/825ed0c3b35e053013344ee5ade03458.png' + )) + intro = models.CharField( + max_length=1024, + default="这个社团很懒,还没有写上自我介绍" + ) + accept = models.BooleanField( + verbose_name="是否通过认证", + default=False + ) + + def __str__(self): + return str(self.id) + self.name + + +class CampusOrganizationsManager(models.Model): + organization = models.ForeignKey( + blank=False, + null=False, + to=CampusOrganizations, + related_name="manager_set", + on_delete=models.CASCADE, + verbose_name="所关联的社团" + ) + owner = models.ForeignKey( + blank=False, + null=False, + to=users.models.UserInfo, + related_name="job_set", + on_delete=models.CASCADE, + verbose_name="拥有者" + ) + position = models.CharField( + max_length=32, + null=False, + blank=False, + verbose_name="职位" + ) + intro = models.CharField( + max_length=1024, + default="这个人很懒,还没有写上自我介绍" + ) + accept = models.BooleanField( + verbose_name="是否通过认证", + default=False + ) + + def __str__(self): + return self.owner.username + '申请' + self.organization.name + + +class CampusOrganizationActivity(models.Model): + organization = models.ForeignKey( + blank=False, + null=False, + to=CampusOrganizations, + related_name="activity_set", + on_delete=models.CASCADE, + verbose_name="所关联的社团" + ) + + title = models.CharField( + max_length=128, + null=False, + blank=False, + ) + + post = models.URLField('宣传海报') + content = models.TextField( + max_length=1048576, + blank=True, + verbose_name=u'内容' + ) + + +class CampusOrganizationActivityTimeline(models.Model): + activity = models.ForeignKey( + blank=False, + null=False, + on_delete=models.CASCADE, + to=CampusOrganizationActivity, + related_name='timeline_set' + ) + time = models.DateTimeField + todo = models.CharField( + max_length=10, + default='' + ) diff --git a/campus/permissions.py b/campus/permissions.py new file mode 100644 index 0000000000000000000000000000000000000000..653dde9d30fec5977f348690c1bb4bf15ccfc373 --- /dev/null +++ b/campus/permissions.py @@ -0,0 +1,31 @@ +from django.contrib.auth.models import User +from rest_framework.permissions import BasePermission + +from backend.decoraters import pass_safe_method + + +class CampusOrganizationManagingPermission(BasePermission): + @staticmethod + def is_manager(request, view, obj): + for i in obj.manager_set.filter(accept=True).iterator(): + if i.owner.id == request.user.id: + return True + return False + + def has_update_permission(self, request, view, obj): + return self.is_manager(request, view, obj) + + def has_destroy_permission(self, request, view, obj): + return self.is_manager(request, view, obj) + + @pass_safe_method + def has_object_permission(self, request, view, obj): + # bypass. + if request.user and ( + request.user.is_staff or request.user.is_superuser): + return True + if view.action == 'update' or view.action == 'partial_update': + return self.has_update_permission(request, view, obj) + elif view.action == 'destroy': + return self.has_destroy_permission(request, view, obj) + return False diff --git a/campus/serializers.py b/campus/serializers.py new file mode 100644 index 0000000000000000000000000000000000000000..1d4c955b345a5d6bb5beb19c36d5c81481fc7a83 --- /dev/null +++ b/campus/serializers.py @@ -0,0 +1,34 @@ +from rest_framework import serializers + +from campus.models import * + + +class CampusOrganizationsManagerSerializer(serializers.ModelSerializer): + accept = serializers.BooleanField(read_only=True) + class Meta: + model = CampusOrganizationsManager + fields = '__all__' + + +class CampusOrganizationsSerializer(serializers.ModelSerializer): + manager_set = CampusOrganizationsManagerSerializer(many=True, read_only=True) + accept = serializers.BooleanField(read_only=True) + + class Meta: + model = CampusOrganizations + fields = '__all__' + depth = 2 + + +class CampusOrganizationActivityTimelineSerializer(serializers.ModelSerializer): + class Meta: + model = CampusOrganizationActivityTimeline + fields = '__all__' + + +class CampusOrganizationActivitySerializer(serializers.ModelSerializer): + timeline_set = CampusOrganizationActivityTimelineSerializer(many=True, read_only=True) + + class Meta: + model = CampusOrganizationActivity + fields = '__all__' diff --git a/campus/tests.py b/campus/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/campus/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/campus/url.py b/campus/url.py new file mode 100644 index 0000000000000000000000000000000000000000..0dd94c48689912fbb5ea6e568c0ce131ca905b32 --- /dev/null +++ b/campus/url.py @@ -0,0 +1,20 @@ +from django.urls import path, include +from rest_framework import routers + +from campus import views + +campus_api_router = routers.DefaultRouter() + +campus_api_router.register('campus_organizations', + views.CampusOrganizationViewSet, + basename='campus') +campus_api_router.register('campus_organizations_manager', + views.CampusOrganizationsManagerViewSet, + basename='campus') +campus_api_router.register('campus_organization_activity', + views.CampusOrganizationActivityViewSet, + basename='campus', + ) +urlpatterns = [ + path('', include((campus_api_router.urls, 'campus'), namespace='campus')) +] diff --git a/campus/views.py b/campus/views.py new file mode 100644 index 0000000000000000000000000000000000000000..8171bfe0851191544447db45e833b86ebe1b12f0 --- /dev/null +++ b/campus/views.py @@ -0,0 +1,61 @@ +from django.shortcuts import render +from drf_yasg import openapi +from drf_yasg.utils import swagger_auto_schema +from rest_framework import status +from rest_framework.decorators import action +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response +from rest_framework.viewsets import ModelViewSet + +from .permissions import CampusOrganizationManagingPermission +from .serializers import * + + +# Create your views here. +class CampusOrganizationViewSet(ModelViewSet): + queryset = CampusOrganizations.objects.all().filter(accept=True) + serializer_class = CampusOrganizationsSerializer + + permission_classes = [CampusOrganizationManagingPermission] + + +class CampusOrganizationsManagerViewSet(ModelViewSet): + queryset = CampusOrganizationsManager.objects.all().filter(accept=True) + serializer_class = CampusOrganizationsManagerSerializer + permission_classes = [IsAuthenticated] + + +class CampusOrganizationActivityViewSet(ModelViewSet): + queryset = CampusOrganizationActivity.objects.all() + serializer_class = CampusOrganizationActivitySerializer + permission_classes = [CampusOrganizationManagingPermission] + + @swagger_auto_schema(method='post', request_body=openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + 'timelines': openapi.Schema( + type=openapi.TYPE_ARRAY, + items=openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + 'activity': openapi.Schema(type=openapi.TYPE_NUMBER, description='活动id'), + 'time': openapi.Schema(type=openapi.FORMAT_DATETIME, description="ISO时间"), + 'todo': openapi.Schema(type=openapi.TYPE_STRING, description='干什么事情') + } + )) + } + )) + @action(methods=['POST'], detail=True, + permission_classes=[CampusOrganizationManagingPermission]) + def add_timeline(self, request, pk): + # print(request.data) + data = CampusOrganizationActivitySerializer(data=request.data.timelines, many=True) + data.is_valid() + print(data.validated_data) + data.save() + return Response(data={ + "success": True, + "code": 200, + "msg": "成功添加", + }, status=status.HTTP_200_OK) + # print(data)