https://api.example.com
# 如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下
https://example.com/api/
https://api.example.com/v1/
-
路径(Endpoint):路径又称“终点”,表示API的具体网址,每一个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,一般数据库表中都是同种记录的“集合(collection)”,所以API中的名词也应该使用复数
https://api.example.com/api/v1/employees
GET(SELECT):从服务器取出资源(一项或多项)
POST(CREATE):在服务器新建一个资源
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)
DELETE(DELETE):从服务器删除资源
?limit=10:指定返回记录的数量
?offset=10:指定返回记录开始的位置
?page=2&per_page=100:指定第几页,以及每页的记录数
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
?animal_type_id=1:指定筛选条件
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功
202 Accepted - [*]:表示请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有响应
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)
403 Forbidden - [*]:表示用户得到授权(与401错误相对),但是访问被禁止的
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作
406 Not Acceptable - [GET]:用户请求的格式不可得
410 Gone - [GET]:用户请求的资源被永久删除,且不会再得到
422 Unprocesable entity - [POST/PUT/PATCH]:当创建一个对象时,发生验证错误
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户无法判断发出的请求是否成功
{
"error": "Invalid API key"
}
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档
pip install django
django-admin startproject <项目名>
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ["*"]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
LANGUAGE_CODE = 'zh-hans' # 'en-us'
TIME_ZONE = 'Asia/Shanghai' # 'UTC'
USE_I18N = True
USE_TZ = False # True:使用UTC时间,False:使用UTC时间
STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'static' # 用于指定生产环境中静态文件的最终收集路径
STATICFILES_DIRS = [ # 用于开发阶段 ,指定额外的静态文件搜索路径 (除各应用的 static/ 目录外)
BASE_DIR / 'staticfiles'
]
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
# 开发环境:将 STATIC_URL 映射到 STATIC_ROOT 或 STATICFILES_DIRS
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
# admin Admin123@
python manage.py runserver [[0.0.0.0:]8000]
pip install djangorestframework
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework.authtoken', # DRF自带的Token认证
]
# DRF 相关的全局配置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 使用 DRF 的分页
'PAGE_SIZE': 50, # 每页条数
'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S', # 接口返回的时间格式
'DEFAULT_RENDER_CLASSES': [ # 当DRF返回Response对象时使用哪个 render 类,这里可以不用写,默认就是这个配置
'rest_framework.render.JSONRenderer',
'rest_framework.render.BrowsableAPIRenderer',
],
'DEFAULT_PARSER_CLASSES': [ # 解析request.data
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
'DEFAULT_PERMISSION_CLASSES': [ # 权限相关
'rest_framework.permissions.IsAuthenticated' # 要求用户登录
],
'DEFAULT_AUTHENTICATION_CLASSES': [ # 认证相关
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
]
}
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('api-auth/', include('rest_framework.urls')), # DRF的登录和退出
path('admin/', admin.site.urls),
]
# 开发环境:将 STATIC_URL 映射到 STATIC_ROOT 或 STATICFILES_DIRS
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
from django.core import serializers
json_data = serializers.serialize('json', queryset_data)
from django.db import models
from django.conf import settings
# Create your models here.
class CourseModel(models.Model):
name = models.CharField(max_length=255, unique=True, help_text="课程名称", verbose_name="课程名称")
introduction = models.TextField(help_text="课程介绍", verbose_name="课程介绍")
price = models.DecimalField(max_digits=6, decimal_places=2, help_text="课程价格", verbose_name="课程价格")
teacher = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, help_text="课程讲师",
verbose_name="课程讲师")
create_time = models.DateTimeField(auto_now_add=True, help_text="创建时间", verbose_name="创建时间")
update_time = models.DateTimeField(auto_now=True, help_text="更新时间", verbose_name="更新时间")
class Meta:
verbose_name = "课程信息"
verbose_name_plural = verbose_name
ordering = ('price',)
def __str__(self):
return self.name
from rest_framework import serializers
from .models import CourseModel
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
class CourseSerializer(serializers.ModelSerializer):
teacher = serializers.ReadOnlyField(source='teacher.username')
class Meta:
model = CourseModel
# exclude = ('id',)
fields = ('id', 'name', 'introduction', 'teacher', 'price', 'create_time', 'update_time')
# fields = "__all__"
import json
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from .models import CourseModel
"""
函数视图 Function Based View
"""
# csrf_exempt 的作用是在POST请求时取消CSRF的限制
@csrf_exempt
def query_course(request):
course_dict = {
'name': '课程名称',
'introduction': '课程介绍',
'price': '12.50'
}
if request.method == 'GET':
# return HttpResponse(json.dumps(course_dict), content_type="application/json")
# 等价于
return JsonResponse(course_dict)
if request.method == 'POST':
course = json.loads(request.body.decode('utf-8'))
return JsonResponse(course, safe=False)
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import CourseModel
from .serializers import CourseSerializer
"""
DRF 函数视图 Function Based View
"""
@api_view(['GET', 'POST'])
def course_list(request):
if request.method == 'GET':
course_list = CourseSerializer(instance=CourseModel.objects.all(), many=True)
return Response(data=course_list.data, status=status.HTTP_200_OK)
elif request.method == 'POST':
r = CourseSerializer(data=request.data, partial=True) # partial=True 表示可以部分更新
if r.is_valid():
r.save(teacher=request.user) # 在保存时,可以单独对某个字段传值
return Response(data=r.data, status=status.HTTP_201_CREATED)
return Response(r.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def course_detail(request, pk):
"""
获取、更新、删除一个课程
:param request:
:param pk:
:return:
"""
try:
course = CourseModel.objects.get(pk=pk)
except Exception as e:
return Response(data={'msg:'"没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
else:
if request.method == 'GET':
course_list = CourseSerializer(instance=course)
return Response(data=course_list.data, status=status.HTTP_200_OK)
elif request.method == 'PUT':
r = CourseSerializer(instance=course, data=request.data, partial=True) # partial=True 表示可以部分更新
if r.is_valid():
r.save() # 在更新时,已经有用户了
return Response(data=r.data, status=status.HTTP_200_OK)
return Response(r.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
course.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
# path('api-auth/', include('rest_framework.urls')), # DRF的登录和退出
path('admin/', admin.site.urls),
path('course/', include('course.urls'))
]
# 开发环境:将 STATIC_URL 映射到 STATIC_ROOT 或 STATICFILES_DIRS
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
from django.urls import path
from .views import query_course, course_detail
urlpatterns = [
path('fbv/list/', query_course, name="fbv-list"),
path('fbv/detail/<int:pk>', course_detail, name="fbv-detail")
]
import json
from django.http import HttpResponse, JsonResponse
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from .models import CourseModel
"""
类视图 Classed Based View
"""
# 既可以用方法装饰器在类上声明使用 csrf_exempt
@method_decorator(csrf_exempt, name='dispatch')
class CourseView(View):
course_dict = {
'name': '课程名称',
'introduction': '课程介绍',
'price': '12.50'
}
def get(self):
return JsonResponse(self.course_dict)
# 也可以直接在方法上使用
# @csrf_exempt
def post(self, request):
course = json.loads(request.body.decode('utf-8'))
return JsonResponse(course, safe=False)
from rest_framework import status
# from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import CourseModel
from .serializers import CourseSerializer
"""
DRF 类视图 Classed Based View
"""
class CourseList(APIView):
def get(self, request):
"""
查询课程信息
:param request:
:return:
"""
print("here...")
queryset = CourseModel.objects.all()
r = CourseSerializer(instance=queryset, many=True)
return Response(data=r.data, status=status.HTTP_200_OK)
def post(self, request):
"""
添加课程信息
:param request:
:return:
"""
r = CourseSerializer(data=request.data)
if r.is_valid():
r.save(teacher=self.request.user)
return Response(data=r.data, status=status.HTTP_201_CREATED)
return Response(r.errors, status=status.HTTP_400_BAD_REQUEST)
class CourseDetail(APIView):
@staticmethod
def get_course_instance(pk):
"""
根据id查询课程
:param pk:课程ID
:return:
"""
try:
return CourseModel.objects.get(pk=pk)
except Exception as e:
return
def get(self, request, pk):
"""
获取课程信息
:param request:
:param pk:
:return:
"""
course = self.get_course_instance(pk=pk)
if not course:
return Response(data={'msg:'"没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
r = CourseSerializer(instance=course)
return Response(data=r.data, status=status.HTTP_200_OK)
def put(self, request, pk):
"""
更新课程信息
:param request:
:param pk:
:return:
"""
course = self.get_course_instance(pk=pk)
if not course:
return Response(data={'msg:'"没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
r = CourseSerializer(instance=course, data=request.data)
if r.is_valid():
r.save()
return Response(data=r.data, status=status.HTTP_201_CREATED)
return Response(r.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
"""
删除课程
:param request:
:param pk:
:return:
"""
r = self.get_course_instance(pk=pk)
if not r:
return Response(data={'msg:'"没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
r.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
from django.urls import path
from .views import course_list, course_detail, CourseList, CourseDetail
urlpatterns = [
path('fbv/list/', course_list, name="fbv-list"),
path('fbv/detail/<int:pk>', course_detail, name="fbv-detail"),
path('cbv/list/', CourseList.as_view(), name="cbv-list"),
path('cbv/detail/<int:pk>', CourseDetail.as_view(), name="cbv-detail"),
]
# from rest_framework import status
# from rest_framework.decorators import api_view
# from rest_framework.response import Response
# from rest_framework.views import APIView
from rest_framework import generics
from .models import CourseModel
from .serializers import CourseSerializer
"""
DRF 通用类视图 Generic Classed Based View
"""
class GCourseList(generics.ListCreateAPIView):
queryset = CourseModel.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer):
"""
重写该方法以实现新增时使用当前登录用户
:param serializer:
:return:
"""
serializer.save(teacher=self.request.user)
class GCourseDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = CourseModel.objects.all()
serializer_class = CourseSerializer
from django.urls import path
from .views import course_list, course_detail, CourseList, CourseDetail, GCourseList, GCourseDetail
urlpatterns = [
path('fbv/list/', course_list, name="fbv-list"),
path('fbv/detail/<int:pk>', course_detail, name="fbv-detail"),
path('cbv/list/', CourseList.as_view(), name="cbv-list"),
path('cbv/detail/<int:pk>', CourseDetail.as_view(), name="cbv-detail"),
path('gcbv/list/', GCourseList.as_view(), name="gcbv-list"),
path('gcbv/detail/<int:pk>', GCourseDetail.as_view(), name="gcbv-detail"),
]
# from rest_framework import status
# from rest_framework.decorators import api_view
# from rest_framework.response import Response
# from rest_framework.views import APIView
# from rest_framework import generics
from rest_framework import viewsets
from .models import CourseModel
from .serializers import CourseSerializer
"""
DRF DRF的视图集 viewsets
"""
class CourseViewSet(viewsets.ModelViewSet):
queryset = CourseModel.objects.all()
serializer_class = CourseSerializer
def perform_create(self, serializer):
"""
重写该方法以实现新增时使用当前登录用户
:param serializer:
:return:
"""
serializer.save(teacher=self.request.user)
from django.urls import path, include
from .views import course_list, course_detail, CourseList, CourseDetail, GCourseList, GCourseDetail, CourseViewSet
# 视图集方式二 start
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(prefix="viewsets2", viewset=CourseViewSet)
# 视图集方式二 end
urlpatterns = [
# 函数视图
path('fbv/list/', course_list, name="fbv-list"),
path('fbv/detail/<int:pk>', course_detail, name="fbv-detail"),
# 类视图
path('cbv/list/', CourseList.as_view(), name="cbv-list"),
path('cbv/detail/<int:pk>', CourseDetail.as_view(), name="cbv-detail"),
# 通用类视图
path('gcbv/list/', GCourseList.as_view(), name="gcbv-list"),
path('gcbv/detail/<int:pk>', GCourseDetail.as_view(), name="gcbv-detail"),
# 视图集
# 视图集方式一
path('viewsets/', CourseViewSet.as_view({
"get": "list",
"post": "create"
}), name="viewsets-list"),
path('viewsets/<int:pk>',
CourseViewSet.as_view({
"get": "retrieve",
"put": "update",
"patch": "partial_update",
"delete": "destroy"
}), name="viewsets-detail"),
# 视图集方式二: v1/viewsets2/
path("", include(router.urls)),
# 视图集方式二: v1/viewsets2/
path("v1/", include(router.urls)),
]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken', # DRF自带的Token认证
'course.apps.CourseConfig'
]
# DRF 相关的全局配置
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': [ # 认证相关
# 'rest_framework.authentication.BasicAuthentication',
# 'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication', # token认证时需要加上
]
}
1、通过Django manage.py生成Token
python manage.py drf_create_token <用户名>
2、通过Django的信号机制生成Token
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.conf import settings
from rest_framework.authtoken.models import Token
# sender 可以使用 User,也可以使用 settings.AUTH_USER_MODEL
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def generate_token(sender, instance=None, created=False, **kwargs):
"""
创建用户时自动生成Token
:param sender:
:param instance:
:param created:
:param kwargs:
:return:
"""
if created:
Token.objects.create(user=instance)
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
# 获取Token的视图
from rest_framework.authtoken import views
urlpatterns = [
path('api-token-auth/', views.obtain_auth_token), # 获取Token的接口
# path('api-auth/', include('rest_framework.urls')), # DRF的登录和退出
path('admin/', admin.site.urls),
path('course/', include('course.urls'))
]
# 函数视图
from rest_framework.decorators import api_view, authentication_classes
from rest_framework.authentication import BasicAuthentication,SessionAuthentication,TokenAuthentication
@api_view(['GET', 'POST'])
@authentication_classes((BasicAuthentication, TokenAuthentication)) # 元组里可以填一个或多个,优先级高于全局设置
def course_list(request):
if request.method == 'GET':
course_list = CourseSerializer(instance=CourseModel.objects.all(), many=True)
return Response(data=course_list.data, status=status.HTTP_200_OK)
elif request.method == 'POST':
r = CourseSerializer(data=request.data, partial=True) # partial=True 表示可以部分更新
if r.is_valid():
r.save(teacher=request.user) # 在保存时,可以单独对某个字段传值
return Response(data=r.data, status=status.HTTP_201_CREATED)
return Response(r.errors, status=status.HTTP_400_BAD_REQUEST)
# 类视图
class CourseList(APIView):
# 配置使用的认证方式
authentication_classes = (TokenAuthentication,)
def get(self, request):
"""
查询课程信息
:param request:
:return:
"""
print("here...")
queryset = CourseModel.objects.all()
r = CourseSerializer(instance=queryset, many=True)
return Response(data=r.data, status=status.HTTP_200_OK)
def post(self, request):
"""
添加课程信息
:param request:
:return:
"""
r = CourseSerializer(data=request.data)
if r.is_valid():
r.save(teacher=self.request.user)
return Response(data=r.data, status=status.HTTP_201_CREATED)
return Response(r.errors, status=status.HTTP_400_BAD_REQUEST)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken', # DRF自带的Token认证
'course.apps.CourseConfig'
]
# DRF 相关的全局配置
REST_FRAMEWORK = {
...
'DEFAULT_PERMISSION_CLASSES': [ # 权限相关
'rest_framework.permissions.IsAuthenticated', # 只有登录的用户才能执行操作
'rest_framework.permissions.IsAuthenticatedOrReadOnly', # 登录的用户可以增删改查,不登录的用户可以查询
'rest_framework.permissions.IsAdminUser', # 如果auth_user表中用户的 is_staff为True,有权限访问
'rest_framework.permissions.AllowAny', # 默认权限方式,所有用户都可以访问
],
'DEFAULT_AUTHENTICATION_CLASSES': [ # 认证相关
# 'rest_framework.authentication.BasicAuthentication',
# 'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication', # token认证时需要加上
]
}
# 函数视图
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.authentication import BasicAuthentication,SessionAuthentication,TokenAuthentication
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly, IsAdminUser, AllowAny
@api_view(['GET', 'POST'])
@authentication_classes((BasicAuthentication, TokenAuthentication)) # 元组里可以填一个或多个,优先级高于全局设置
@permission_classes((IsAuthenticated,))
def course_list(request):
if request.method == 'GET':
course_list = CourseSerializer(instance=CourseModel.objects.all(), many=True)
return Response(data=course_list.data, status=status.HTTP_200_OK)
elif request.method == 'POST':
r = CourseSerializer(data=request.data, partial=True) # partial=True 表示可以部分更新
if r.is_valid():
r.save(teacher=request.user) # 在保存时,可以单独对某个字段传值
return Response(data=r.data, status=status.HTTP_201_CREATED)
return Response(r.errors, status=status.HTTP_400_BAD_REQUEST)
# 类视图
class CourseList(APIView):
# 配置使用的认证方式
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,)
def get(self, request):
"""
查询课程信息
:param request:
:return:
"""
print("here...")
queryset = CourseModel.objects.all()
r = CourseSerializer(instance=queryset, many=True)
return Response(data=r.data, status=status.HTTP_200_OK)
def post(self, request):
"""
添加课程信息
:param request:
:return:
"""
r = CourseSerializer(data=request.data)
if r.is_valid():
r.save(teacher=self.request.user)
return Response(data=r.data, status=status.HTTP_201_CREATED)
return Response(r.errors, status=status.HTTP_400_BAD_REQUEST)
from rest_framework import permissions
class IsOwnerReadOnly(permissions.BasePermission):
"""
自定义权限:只允许对象的所有者能够编辑
"""
def has_object_permission(self, request, view, obj):
print("permission...", request.user, obj.teacher, request.method)
"""
所有的request请求都有读权限,因此允许GET/HEAD/OPTIONS方法
:param request:
:param view:
:param obj:
:return:
"""
if request.method in permissions.SAFE_METHODS:
return True
# 对象的所有者才有写权限
return request.user == obj.teacher
from .permissions import IsOwnerReadOnly
class CourseDetail(APIView):
# 使用自定义权限
permission_classes = (IsOwnerReadOnly,)
@staticmethod
def get_course_instance(pk):
"""
根据id查询课程
:param pk:课程ID
:return:
"""
try:
return CourseModel.objects.get(pk=pk)
except Exception as e:
return
def get(self, request, pk):
"""
获取课程信息
:param request:
:param pk:
:return:
"""
course = self.get_course_instance(pk=pk)
if not course:
return Response(data={'msg:'"没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
r = CourseSerializer(instance=course)
return Response(data=r.data, status=status.HTTP_200_OK)
def put(self, request, pk):
"""
更新课程信息
:param request:
:param pk:
:return:
"""
course = self.get_course_instance(pk=pk)
if not course:
return Response(data={'msg:'"没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
r = CourseSerializer(instance=course, data=request.data)
if r.is_valid():
r.save()
return Response(data=r.data, status=status.HTTP_201_CREATED)
return Response(r.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
"""
删除课程
:param request:
:param pk:
:return:
"""
r = self.get_course_instance(pk=pk)
if not r:
return Response(data={'msg:'"没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
r.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
# DRF 相关的全局配置
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', # 自动生成接口文档
...
}
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
from rest_framework.authtoken import views
# 生成API接口文档
from rest_framework.documentation import include_docs_urls
urlpatterns = [
path('api-token-auth/', views.obtain_auth_token), # 获取Token的接口
# path('api-auth/', include('rest_framework.urls')), # DRF的登录和退出
path('admin/', admin.site.urls),
path('course/', include('course.urls')),
path('docs/', include_docs_urls('course.urls')),
]
# 开发环境:将 STATIC_URL 映射到 STATIC_ROOT 或 STATICFILES_DIRS
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
# DRF 相关的全局配置
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema', # 自动生成接口文档
...
}
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
from rest_framework.authtoken import views
# 文档相关
from rest_framework import schemas
schema_view = schemas.get_schema_view(title='APISchema', description="描述信息")
urlpatterns = [
path('api-token-auth/', views.obtain_auth_token), # 获取Token的接口
# path('api-auth/', include('rest_framework.urls')), # DRF的登录和退出
path('admin/', admin.site.urls),
path('course/', include('course.urls')),
path('docs/', schema_view),
]
# 开发环境:将 STATIC_URL 映射到 STATIC_ROOT 或 STATICFILES_DIRS
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)