django 二 后端
自定义字段和序列化 api/serializers/course
from api import models from rest_framework import serializers class CourseSerializer(serializers.ModelSerializer): level = serializers.CharField(source='get_level_display') class Meta: model = models.Course fields = ['id','title','course_img','level'] # class CourseDetailSerializer(serializers.ModelSerializer): # class Meta: # model = models.CourseDetail # fields = "__all__" # depth = 1 # 0-10 class CourseDetailSerializer(serializers.ModelSerializer): # one2one/fk/choice title = serializers.CharField(source='course.title') img = serializers.CharField(source='course.course_img') level = serializers.CharField(source='course.get_level_display') # m2m recommends = serializers.SerializerMethodField() chapter = serializers.SerializerMethodField() class Meta: model = models.CourseDetail fields = ['course','title','img','level','slogon','why','recommends','chapter'] def get_recommends(self,obj): # 获取推荐的所有课程 queryset = obj.recommend_courses.all() return [{'id':row.id,'title':row.title} for row in queryset] def get_chapter(self, obj): queryset = obj.course.chapter_set.all() return [{'id':row.id,'name':row.name} for row in queryset]
一级路由
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/(?P<version>\w+)/', include('api.urls')), ]
二级路由带参数 api/urls 路由
from django.conf.urls import url,include from api.views import course urlpatterns = [ # 方式一 # url(r'^course/$', course.CourseView.as_view()), # url(r'^course/(?P<pk>\d+)/$', course.CourseView.as_view()), # 方式二 url(r'^course/$', course.CourseView.as_view({'get':'list'})), url(r'^course/(?P<pk>\d+)$', course.CourseView.as_view({'get':'retrieve'})),
url(r'^auth/$',account.AuthView.as_view()),
url(r'^micro/$',course.MicroView.as_view()),
]
如何将带有参数的路由的视图写在一个类中 视图
from rest_framework.views import APIView from rest_framework.response import Response from api import models from api.serializers.course import * # 方式一: # class CourseView(APIView): # # def get(self,request,*args,**kwargs): # # ret = {'code':1000,'data':None} # # try: # pk = kwargs.get('pk') # if pk: # obj = models.Course.objects.filter(id=pk).first() # ser = CourseSerializer(instance=obj,many=False) # else: # queryset = models.Course.objects.all() # ser = CourseSerializer(instance=queryset,many=True) # ret['data'] = ser.data # except Exception as e: # ret['code'] = 1001 # ret['error'] = '获取课程失败' # # return Response(ret) # 方式二 # View # APIView # GenericAPIView from rest_framework.viewsets import GenericViewSet,ViewSetMixin class CourseView(ViewSetMixin,APIView): def list(self,request,*args,**kwargs): """ 课程列表接口 :param request: :param args: :param kwargs: :return: """ ret = {'code':1000,'data':None} try: queryset = models.Course.objects.all() ser = CourseSerializer(instance=queryset,many=True) ret['data'] = ser.data except Exception as e: ret['code'] = 1001 ret['error'] = '获取课程失败' return Response(ret) def retrieve(self,request,*args,**kwargs): """ 课程详细接口 :param request: :param args: :param kwargs: :return: """ ret = {'code': 1000, 'data': None} try: # 课程ID=2 pk = kwargs.get('pk') # 课程详细对象 obj = models.CourseDetail.objects.filter(course_id=pk).first() ser = CourseDetailSerializer(instance=obj,many=False) ret['data'] = ser.data except Exception as e: ret['code'] = 1001 ret['error'] = '获取课程失败' return Response(ret)
class MicroView(APIView):
authentication_classes = [LuffyAuth,]
def get(self,request, *args, **kwargs):
ret = {'code': 1000, 'title': '微职位'}
return Response(ret)
表设计
from django.db import models class Course(models.Model): """ 课程表 """ title = models.CharField(verbose_name='课程名称',max_length=32) course_img = models.CharField(verbose_name='课程图片',max_length=64) level_choices = ( (1,'初级'), (2,'中级'), (3,'高级'), ) level = models.IntegerField(verbose_name='课程难易程度',choices=level_choices,default=1) def __str__(self): return self.title class CourseDetail(models.Model): """ 课程详细 """ course = models.OneToOneField(to='Course') slogon = models.CharField(verbose_name='口号',max_length=255) why = models.CharField(verbose_name='为什么要学?',max_length=255) recommend_courses = models.ManyToManyField(verbose_name='推荐课程',to='Course',related_name='rc') def __str__(self): return "课程详细:"+self.course.title class Chapter(models.Model): """ 章节 """ num = models.IntegerField(verbose_name='章节') name = models.CharField(verbose_name='章节名称',max_length=32) course = models.ForeignKey(verbose_name='所属课程',to='Course') def __str__(self): return self.name
class UserInfo(models.Model):
user = models.CharField(max_length=32)
pwd = models.CharField(max_length=64)
class UserToken(models.Model):
user = models.OneToOneField(to='UserInfo')
token = models.CharField(max_length=64)
# api/auth/auth 认证组件 from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from api import models class LuffyAuth(BaseAuthentication): def authenticate(self, request): # 固定方法 token = request.query_params.get('token') obj = models.UserToken.objects.filter(token=token).first() if not obj: raise AuthenticationFailed({'code':1001,'error':'认证失败'}) return (obj.user.user,obj)
api/view/account 数据库更新token
from rest_framework.views import APIView from rest_framework.response import Response from api import models import uuid class AuthView(APIView): def post(self, request, *args, **kwargs): ret = {'code': 1000} user = request.data.get('user') pwd = request.data.get('pwd') user = models.UserInfo.objects.filter(user=user,pwd=pwd).first() if not user: ret['code'] = 1001 ret['error'] = '用户名或密码错误' else: uid = str(uuid.uuid4()) models.UserToken.objects.update_or_create(user=user,defaults={'token':uid}) ret['token'] = uid return Response(ret)
api/cors 中间件,解决跨域问题
class MiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, 'process_response'): response = self.process_response(request, response) return response class CORSMiddleware(MiddlewareMixin): def process_response(self,request,response): # 添加响应头 # 允许你的域名来获取我的数据 response['Access-Control-Allow-Origin'] = "*" # 允许你携带Content-Type请求头 # response['Access-Control-Allow-Headers'] = "Content-Type" # 允许你发送DELETE,PUT # response['Access-Control-Allow-Methods'] = "DELETE,PUT" return response
setting中版本的配置 版本
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer',], 'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning', 'ALLOWED_VERSIONS':['v1','v2'], # 允许的版本 'VERSION_PARAM':'version', # 参数 'DEFAULT_VERSION':'v1', # 默认版本 }