1.官网

https://www.django-rest-framework.org/tutorial/quickstart/#quickstart

2.目录结构

models.py
from django.db import models

# Create your models here.
from django.db import models

# Create your models here.

class User(models.Model):
    name=models.CharField(max_length=32)
    pwd=models.CharField(max_length=32)
    type_choices=((1,"普通用户"),(2,"VIP"),(3,"SVIP"))
    user_type=models.IntegerField(choices=type_choices,default=1)


class Token(models.Model):
    user=models.OneToOneField("User")
    token = models.CharField(max_length=128)

    def __str__(self):
        return self.token


class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")
    def __str__(self):
        return self.title

class Publish(models.Model):
    name=models.CharField(max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    def __str__(self):
        return self.name
serilizer.py
# by luffycity.com

from rest_framework import serializers

from app01.models import *
# 为queryset,model对象做序列化
class PublishSerializers(serializers.Serializer):
    name = serializers.CharField()
    email = serializers.CharField()


class PublishModelSerializers(serializers.ModelSerializer):
    class Meta:
        model=Publish
        fields="__all__"




# class BookSerializers(serializers.Serializer):
#     title = serializers.CharField(max_length=32)
#     price = serializers.IntegerField()
#     pub_date = serializers.DateField()
#     publish=serializers.CharField(source="publish.name")
#     #authors=serializers.CharField(source="authors.all")
#     authors = serializers.SerializerMethodField()
#     def get_authors(self,obj):
#         temp=[]
#         for obj in obj.authors.all():
#             temp.append(obj.name)
#         return temp

'''
序列化BookSerializers(book_list,many=True)过程:
     temp=[]
     for obj in book_list:
         temp.append({
            "title":obj.title,
            "price":obj.price,
            "pub_date":obj.pub_date,
            "publish":str(obj.publish), # obj.publish.name
            #"authors":obj.authors.all,
            "authors": get_authors(obj)
         })

'''


class BookModelSerializers(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"

    #publish=serializers.CharField(source="publish.pk")
    publish=serializers.HyperlinkedIdentityField(
            view_name="detailpublish",
            lookup_field="publish_id",
            lookup_url_kwarg="pk",

    )


    # authors=serializers.CharField(source="authors.all")
    # authors = serializers.SerializerMethodField()
    # def get_authors(self,obj):
    #     temp=[]
    #     for obj in obj.authors.all():
    #         temp.append(obj.name)
    #     return temp

    def create(self, validated_data):
        print("validated_data",validated_data)
        book=Book.objects.create(title=validated_data["title"],price=validated_data["price"],pub_date=validated_data["pub_date"],publish_id=validated_data["publish"]["pk"])
        book.authors.add(*validated_data["authors"])

        return book


class AuthorModelSerializers(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = "__all__"
utils.py
from rest_framework import exceptions

from rest_framework.authentication import BaseAuthentication


from .models import *
class TokenAuth(BaseAuthentication):
    def authenticate(self,request):

        token = request.GET.get("token")
        token_obj = Token.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed("验证失败!")
        else:
            return token_obj.user.name,token_obj.token



class SVIPPermission(object):
    message="只有超级用户才能访问"
    def has_permission(self,request,view):
        username=request.user
        user_type=User.objects.filter(name=username).first().user_type

        if user_type==3:

            return True # 通过权限认证
        else:
            return False
views.py
from django.shortcuts import render,HttpResponse

# Create your views here.

from django.views import View
from rest_framework.response import Response
from .models import *

from app01.serilizer import *


from rest_framework.views import APIView
# Publish表
class PublishView(APIView):
    def get(self,request):

        # restframework
        # 取数据
        # print("request.data", request.data)
        # print("request.data type", type(request.data))
        # print(request._request.GET)
        # print(request.GET)
        # 序列化
        # 方式1:
        # publish_list=list(Publish.objects.all().values("name","email"))

        # 方式2:
        # from django.forms.models import model_to_dict
        # publish_list=Publish.objects.all()
        # temp=[]
        # for obj in publish_list:
        #     temp.append(model_to_dict(obj))

        # 方式3:
        # from django.core import serializers
        # ret=serializers.serialize("json",publish_list)

        # 序列组件
        publish_list = Publish.objects.all()
        ps = PublishModelSerializers(publish_list, many=True)
        return Response(ps.data)

    def post(self,request):
        # 取数据
        # 原生request支持的操作
        # print("POST",request.POST)
        # print("body",request.body)
        # # print(request)
        # print(type(request))
        # from django.core.handlers.wsgi import WSGIRequest
        #  新的request支持的操作
        # print("request.data",request.data)
        # print("request.data type",type(request.data))


        #
        # post请求的数据
        ps = PublishModelSerializers(data=request.data)
        if ps.is_valid():
            print(ps.validated_data)
            ps.save()  # create方法
            return Response(ps.data)
        else:
            return Response(ps.errors)
class PublishDetailView(APIView):
    def get(self, request, pk):

        publish = Publish.objects.filter(pk=pk).first()
        ps = PublishModelSerializers(publish)
        return Response(ps.data)

    def put(self, request, pk):
        publish = Publish.objects.filter(pk=pk).first()
        ps = PublishModelSerializers(publish, data=request.data)
        if ps.is_valid():
            ps.save()
            return Response(ps.data)
        else:
            return Response(ps.errors)

    def delete(self, request, pk):
        Publish.objects.filter(pk=pk).delete()

        return Response()




from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser
# Book表

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
class MyPageNumberPagination(PageNumberPagination):
    page_size = 1
    page_query_param = 'page'
    page_size_query_param="size"
    max_page_size=2




class MyLimitOffsetPagination(LimitOffsetPagination):
    default_limit=1

class BookView(APIView):
    # authentication_classes = [TokenAuth,] # [TokenAuth(),]
    # permission_classes = []
    # throttle_classes = []
    parser_classes = [JSONParser,FormParser]

    def get(self,request):
        print("request.user",request.user)
        print("request.auth",request.auth)
        print("_request.body",request._request.body)
        print("_request.GET",request._request.GET)
        book_list=Book.objects.all()

        # 分页

        pnp=MyLimitOffsetPagination()
        books_page=pnp.paginate_queryset(book_list,request,self)

        bs=BookModelSerializers(books_page,many=True,context={'request': request})
        return Response(bs.data)
    
    def post(self,request):
        # post请求的数据

        print("request.data",request.data)


        bs=BookModelSerializers(data=request.data)
        if bs.is_valid():
            print(bs.validated_data)
            bs.save()# create方法
            return Response(bs.data)
        else:
            return Response(bs.errors)



class BookDetailView(APIView):

    def get(self,request,id):

        book=Book.objects.filter(pk=id).first()

        bs=BookModelSerializers(book,context={'request': request})

        return Response(bs.data)

    def put(self,request,id):
        book=Book.objects.filter(pk=id).first()
        bs=BookModelSerializers(book,data=request.data)
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return Response(bs.errors)

    def delete(self,request,id):
        Book.objects.filter(pk=id).delete()

        return Response()

# ##############################################################Author

# from rest_framework import mixins
# from rest_framework import generics
#
# class AuthorView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView):
#     queryset=Author.objects.all()
#     serializer_class =AuthorModelSerializers
#
#     def get(self,request, *args, **kwargs):
#         return self.list(request, *args, **kwargs)
#     def post(self,request, *args, **kwargs):
#         return self.create(request, *args, **kwargs)
#
#
# class AuthorDetailView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView):
#     queryset = Author.objects.all()
#     serializer_class = AuthorModelSerializers
#
#     def get(self,request,*args, **kwargs):
#         return self.retrieve(request,*args, **kwargs)
#
#     def delete(self,request,*args, **kwargs):
#         return self.destroy(request,*args, **kwargs)
#
#     def put(self,request,*args, **kwargs):
#         return self.retrieve(request,*args, **kwargs)

##############################################################################

#
# from rest_framework import mixins
# from rest_framework import generics
#
#
# class AuthorView(generics.ListCreateAPIView):
#     queryset=Author.objects.all()
#     serializer_class =AuthorModelSerializers
#
# class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView):
#     queryset = Author.objects.all()
#     serializer_class = AuthorModelSerializers

##############################################################################

from rest_framework import viewsets

from app01.utils import TokenAuth



from app01.utils import SVIPPermission



class VisitRateThrottle(object):
    def allow_request(self,request,view):
        # 要求访问站点的频率不能超过每分钟20次
        if 1:
            print(request.META.get("REMOTE_ADDR"))

            return True
        else:
            return False


from rest_framework.response import  Response


class AuthorModelView(viewsets.ModelViewSet):

    #authentication_classes = [TokenAuth,]
    #permission_classes=[SVIPPermission,]
    #throttle_classes = [VisitRateThrottle]    # 限制某个IP每分钟访问次数不能超过20次
    queryset = Author.objects.all()
    serializer_class = AuthorModelSerializers
    pagination_class = MyPageNumberPagination
    renderer_classes = []


def get_random_str(user):
    import hashlib,time
    ctime=str(time.time())

    md5=hashlib.md5(bytes(user,encoding="utf8"))
    md5.update(bytes(ctime,encoding="utf8"))

    return md5.hexdigest()


from .models import User

class LoginView(APIView):
    authentication_classes = []
    def post(self,request):

        name=request.data.get("name")
        pwd=request.data.get("pwd")
        user=User.objects.filter(name=name,pwd=pwd).first()
        res = {"state_code": 1000, "msg": None}
        if user:

            random_str=get_random_str(user.name)
            token=Token.objects.update_or_create(user=user,defaults={"token":random_str})
            res["token"]=random_str
        else:
            res["state_code"]=1001 #错误状态码
            res["msg"] = "用户名或者密码错误"

        import json
        return Response(json.dumps(res,ensure_ascii=False))

 

settings.py
"""
Django settings for restdemo project.

Generated by 'django-admin startproject' using Django 1.11.1.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'zh7zb+r@$sgy(e=2p%dh7229g2z*diug%7ifpg$53a8=_gvi=d'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    "rest_framework",
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    #'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'restdemo.urls'



TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(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',
            ],
        },
    },
]

WSGI_APPLICATION = 'restdemo.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'

REST_FRAMEWORK = {

    # "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.TokenAuth",],
    # "DEFAULT_PERMISSION_CLASSES": ["app01.utils.SVIPPermission",],
    # "PAGE_SIZE":1
}
urls.py
"""restdemo URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url,include
from django.contrib import admin

from rest_framework import routers
from app01 import views



routers=routers.DefaultRouter()
routers.register("authors",views.AuthorModelView)


urlpatterns = [

    url(r'^admin/', admin.site.urls),
    url(r'^publishes/$', views.PublishView.as_view(),name="publish"), #  View:view(request)=====APIView:dispatch()
    url(r'^publishes/(?P<pk>\d+)/$', views.PublishDetailView.as_view(),name="detailpublish"), #  View:view(request)=====APIView:dispatch()

    url(r'^books/$', views.BookView.as_view(),name="books"),
    url(r'^books/(\d+)/$', views.BookDetailView.as_view(),name="detailbook"),
    #url(r'^books/(\d+)/$', View:view),     # view(request)

    # url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"),
    # url(r'^authors/(?P<pk>\d+)/$', views.AuthorModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="detailauthor"),
    #
    url(r'', include(routers.urls)),
    url(r'^login/$', views.LoginView.as_view(),name="login"),

]