day49-rest框架

weixin_33806914發表於2019-01-11

1配置

在django框架下安裝兩個三方庫
pip install djangorestframework
pip install django-filter
然後在當前應用的urls中配置路由
在路由檔案的urlpatterns之前新增程式碼;作用分別是宣告路由物件;註冊一個student資源,資源對應StuView類

router = SimpleRouter()
router.register('student', views.StuView)

在路由檔案的urlpatterns之後新增如下程式碼;作用是將路由新增到urlpatterns中

urlpatterns += router.urls

2物件序列化

在當前應用下的views檔案下定義一個類;該類能夠實現對資料庫的檢視、修改及刪除、新增功能;這些功能都是通過繼承父類來獲得的;各個繼承的類的作用如下。該方法主要針對資源(資源屬於一個類)進行操作

mixins.ListModelMixin,  檢視所有資源,GET
mixins.RetrieveModelMixin,  檢視指定id的資源 ,GET
mixins.DestroyModelMixin,  刪除指定的資源 ,DELETE
mixins.CreateModelMixin,  建立資源 ,POST
mixins.UpdateModelMixin  修改資源 ,PUT/PATCH

class StuView(viewsets.GenericViewSet,
          mixins.ListModelMixin, # 檢視所有資源,GET
          mixins.RetrieveModelMixin, # 檢視指定id的資源 ,GET
          mixins.DestroyModelMixin, # 刪除指定的資源 ,DELETE
          mixins.CreateModelMixin, # 建立資源 ,POST
          mixins.UpdateModelMixin): # 修改資源 ,PUT/PATCH
 指定資源返回的內容
queryset = Student.objects.all()
 #只檢視所有is_delete屬性為0的學生
# queryset = Student.objects.filter(is_delete=0)
 資源(queryset)序列化的結果
serializer_class = StuSerializer

 查詢所有資訊時,過濾掉被刪除(is_delete=0)的學生資訊
def get_queryset(self):
    queryset = self.queryset
    return queryset.filter(is_delete=0)

 刪除時不將資料從資料庫刪除,而是修改其is_delete為1
def perform_destroy(self, instance):
    instance.is_delete=1
    instance.save()

queryset = Student.objects.all()語句為獲取指定資源返回的內容
serializer_class = StuSerializer語句為將獲取的資源序列化(StuSerializer為定義的序列化類)
在過濾資訊時:

queryset = Student.objects.all()
serializer_class = StuSerializer
def get_queryset(self):
    queryset = self.queryset
    return queryset.filter(is_delete=0)

以上部分可以被以下部分代替

queryset = Student.objects.filter(is_delete=0)
serializer_class = StuSerializer

由於不能輕易從資料庫刪除資料,故通常將要刪除的物件的is_delete屬性修改為1,而檢視時,只看屬性是0的,從而達到遮蔽效果。所以需要先在models中新增以下程式碼:

is_delete = models.BooleanField(default=0)

然後在資料庫的查詢中新增以下程式碼

alter table student add is_delete bit default 0;

當需要對瀏覽器獲取的資料進行修改新增獲取狀態等資訊時;還需要在下面繼續新增程式碼

    def retrieve(self, request, *args, **kwargs):
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            return Response(serializer.data)
        except Exception as e:
            return Response({'code': 404, 'msg': '獲取失敗', 'data': ''})

上面部分除了返回值其他都是固定寫法

3序列化引數校驗及返回具體值

上面的物件序列化都是在呼叫序列化的方法,而本節的序列化引數校驗則是指定如何序列化及返回哪些值及對部分值進行修飾。
在當前應用下新建一個serializers.py檔案

3.1定義序列化類

from rest_framework import serializers
from app.models import Student
class StuSerializer(serializers.ModelSerializer):
    對傳入的s_name進行校驗
    s_name = serializers.CharField(max_length=10, min_length=2,
                      error_messages={'required': '姓名必填',
                       'max_length': '最大不能超過10字元',
                        'min_length': '最小不能小於2字元'})
    class Meta:
    指定序列化的模型
        model = Student
        指定序列化後返回哪些內容
        fields = ['s_name', 's_gender', 's_age', 'id']
      重構to_representation方法,使true和false顯示為男女
    def to_representation(self, instance):
        data = super(StuSerializer, self).to_representation(instance)
        data['s_gender'] = '男' if data['s_gender'] else '女'
        return data

data = super(StuSerializer, self).to_representation(instance):繼承父類的to_representation方法並傳入類名,to_representation作用是對傳入的物件instance作相關處理並序列化生成字典,如果沒有處理過程則直接生成字典data。

4給前端返回指定格式資料

在把資料返回給前端前先對其進行處理,新增狀態碼及獲取是否成功的資訊
這個功能主要通過重寫retrieve方法實現。
在應用下的views.py檔案中的序列化類中重寫retrieve方法
在重寫方法之前,需要先在settings中配置rest_framework的相關資訊

REST_FRAMEWORK = {
# 使用自定義的render方法
'DEFAULT_RENDERER_CLASSES':(
    'utils.jsonrenderer.MyJSONRenderer',
)
}

重寫方法如下

    def retrieve(self, request, *args, **kwargs):
    try:
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)
    except Exception as e:
        return Response({'code': 404, 'msg': '獲取失敗', 'data': ''})

上面程式碼只能對獲取失敗的資訊進行操作,所以需要在中介軟體資料夾下新建一個jsonrenderer.py檔案

from rest_framework.renderers import JSONRenderer
class MyJSONRenderer(JSONRenderer):
    def render(self, data, accepted_media_type=None, renderer_context=None):
        try:
            當傳入的請求失敗時,對其進行解析
            code = data['code']
            msg = data['msg']
            result = data['data']
        except:
           當傳入請求成功時,由於沒有對其進行組裝,故只有data資料,
            沒有msg和code,會報錯,所以給其賦值
            code = 200
            msg = '請求成功'
            result = data
        my_data = {
            'code': code,
            'msg': msg,
            'data': result
        }
         呼叫父類的render方法接收my_render資料,使其返回為data
        return super().render(my_data)

5介面(API)文件

介面文件必須說明以下內容
請求(請求方式,請求路由)
請求引數(各欄位的名稱及型別及其意義,以及是否必填)
響應()
響應引數
如下

 請求
GET /user/student/
 請求引數
s_name str 姓名 (必填)
s_age int 年齡 (非必填)
s_gender str 性別 (非必填)
math float 數學成績 (非必填)
wuli float 物理成績 (非必填)
響應    
    {
    'code': 200,
    'msg':'請求成功',
    'data':[
        {'s_name': '小明'},
        {'s_age': 20},
        {'s_gender': '男'}
    ]
}

 響應引數
s_name str 學生姓名
s_gender str 性別
s_age int 年齡

6介面

在views中定義一個檢視函式

def stu_list(request):
if request.method == 'GET':
    return render(request, 'stu_list.html')

新建Html文件

<body>
        <script>
    $.ajax({
        url: '/user/student/',
        type: 'GET',
        {#data: '',#}
        dataType: 'json',
        success: function (result) {
            {#ajax非同步請求#}
            for(var i=0; i<result.data.length; i++){
                var s = '<p>姓名: '+ result.data[i].s_name +' 性別:' +
                    ' '+ result.data[i].s_gender + '年齡: '+
                    result.data[i].s_age + '<a onclick="del_stu(' +
                    result.data[i].id + ')">刪除</a><a href="" ' +
                    'onclik="edit_stu(' + result.data[i].id +
                    ')">編輯</a></p>'
                {#在div標籤後追加上面的內容,若將append寫成html或者text則只加最後的一次#}
                $('.stus').append(s)
            }
            console.log(result.data)

        },
        error: function (result) {
            alert('失敗')
        }

    });
function del_stu(id){
        $.ajax({
            url: '/user/student/' + id + '/',
            type: 'DELETE',
            dataType: 'json',
            success: function (result) {
                console.log(result)
                {#刪除後,重新跳向stu_list頁面以重新整理#}
                location.href = '/user/stu_list/'
            },
            error: function(result){
                alert('刪除失敗')
            }
        })
    };

    function edit_stu(id){
        $.ajax({
            url:  '/user/student/' + id + '/',
            type: 'PATCH',
            data:{'s_name': '石頭人'},
            dataType:  'json',
            success: function (data){
                console.log(data)
            },
            error: function(data){
                alert('修改失敗')
            }
        })
    };
    function add_stu() {
        $.ajax({
            url: '/user/student/',
            type: 'POST',
            data:{'s_name': '墨菲特'},
            dataType: 'json',
            success: function (data) {
                console.log(data)
            },
            error:function(data){
                alert('失敗')
            }
        })
    }

</script>
<div class="stus">
    <a onclick="add_stu();">新增</a>
</div>
</body>

該文件能夠實現ajax的非同步請求

相關文章