Django1.0和2.0中的rest_framework的超链接字段的处理

大家看到这个标题是不是有点懵逼,其实我就是想要一个这样的效果

比如我get一条书籍的数据,在一对多的字段中我们显示一个url,看起来是不是很绚!

下面我们就来实现这么一个东西

首先我们一对多字段中的一表是 出版社表,因为我们这里要显示某个出版社的url,所以我们首先必须要为出版社的设计一个url

"""
from django.conf.urls import url
from django.contrib import admin
from django.conf.urls import include
from app1 import views
urlpatterns = [
    url(r‘^test/‘, views.test),
    url(r‘^test_cbv/‘, views.test_cbv.as_view(),name="test1"),
    url(r‘^test_rest/‘, views.Rest_view.as_view(),name="test2"),
    url(r‘^book_cbv/‘, views.Book_cbv.as_view(),name="test3"),
    url(r‘^publish_detail_cbv/(?P<id>\d+)‘, views.Pub_detail_cbv.as_view(),name="publish_url_name"),
    url(r‘^book_detail_cbv/(?P<id>\d+)‘, views.Book_detail_cbv.as_view(),name="test4"),
]

  

就是这样的一条

然后我们为出版社设计modelserializer类,所有的字段都使用默认的形式

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

  

然后我们写cbv中的c,也就是视图类

class Pub_detail_cbv(APIView):
    def get(self,request,id):
        obj = models.Publish.objects.filter(id=id).first()

        # bs = pubmodelserializer(obj,many=False,context={‘request‘: request})
        bs = pubmodelserializer(obj, many=False)
        return Response(bs.data)

    def put(self,request,id):
        obj = models.Publish.objects.filter(id=id)
        bs = pubmodelserializer(obj,data=request.data)
        if bs.is_valid():
            bs.save()

            return Response(bs.data)
        else:
            return Response(bs.errors)

这样,基本框架就完成了,我们开始来实现超链接

首先要为每条url设计别名

因为我们要对书籍表中的某个字段做超链接处理,所以需要到书籍表的modelserializer类中为超链接字段做特殊的处理

超链接字段使用使用HyperLinkedIdentityField这个类

这个必须要有3个参数,后面会具体的分析

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

    book_publish = serializers.HyperlinkedIdentityField(
        view_name="publish_url_name",
        lookup_field="book_publish_id",
        lookup_url_kwarg="id"

    )

  

就是我截图框红的这里,下面我们来具体解释下

view_name就是这个字段我们想显示的url的别名

lookup_field字段是一个我们自定义的值,因为我们这里的类是对model对象做序列化处理,所以每个model对象都一个序列化的实例,而这个字段就是这个实例的出版社的id

lookup_url_kwarg字段就是我们的url参数,比如我们这里写的是id,那么lookup_filed这个参数对应的值就会赋值给url中命名变量为id这个变量

这里我们在看下url,因为我们的url中这里要显示的id,所以我们在lookup_fileld就要获取对应的出版社的id,所以这里大家是否清楚了,lookup_fileld要获取什么值,完全取决于我们在url中变量想要什么值;这里为什么还要指定url中的变量的名称呢?因为url中的变量可不止一个,所以必须要指定变量的名称;这里不能使用位置参数,必须使用命名参数

下面我们通过postman发送一个get请求测试一下

发现会报错

这个报错要这样解决

在视图类中序列化一个modelserializer对象的时候要这么写,其实这也是一个固定的写法,在所以实例化model对象或者queryset中均这样写就好了

class Book_detail_cbv(APIView):
    def get(self,request,id):
        obj = models.Book.objects.filter(id=id).first()

        bs = bookmodelserializer(obj,many=False,context={‘request‘: request})
        # bs = bookmodelserializer(obj, many=False,)
        return Response(bs.data)

  

然后我们在测试一下

上面是django1.0版本的处理

  

===============================================================================================================

在djaong2.0中,稍微有一点不同,就是django2.0中对于二级路由的命令别名和django1.0有些改动,这里稍微做一下回忆

首先在工程的url文件中需要按照下面的格式来写

然后在对应app的url中要这么写

最后在超链接类中view_name要这样指定url的别名

其他均和在django1.0中保持一致

附上在django2.0中的所有的代码

序列化处理的代码

from rest_framework import serializers
from app1 import models
from rest_framework.views import APIView
from rest_framework.response import Response
from django.urls import reverse
class bookmodelserializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"
    #
    # book_publish = serializers.CharField(source="book_publish.publish_name")
    book_publish = serializers.HyperlinkedIdentityField(
        view_name= "app1:pub_detail",
        lookup_field="book_publish_id",
        lookup_url_kwarg="pid"
    )

    def create(self, validated_data):
        print("validated_data",validated_data,"==============================")

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

  

视图类的代码

from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.shortcuts import redirect
from django import views

# Create your views here.

class Test(views.View):
    def get(self,request):
        print(request,type(request))
        return HttpResponse("ok")

    def post(self):
        pass

from rest_framework import serializers
from app1 import models
from rest_framework.views import APIView
from rest_framework.response import Response

from app1.serializer import *

class Book_modelserializer_cbv(APIView):
    def get(self,request):

        queryset_list = models.Book.objects.all()
        ret = bookmodelserializers(queryset_list,many=True)
        print(dir(ret),type(ret))
        return Response(ret.data)

    def post(self,request):

        ret = bookmodelserializers(data=request.data)
        print("request.data",request.data,"==============================")
        if ret.is_valid():
            ret.save()
            return Response(ret.data)
        else:
            return Response(ret.errors)

class Book_Detail_modelserializer_cbv(APIView):
    def get(self,request,bid):
        obj = models.Book.objects.filter(id=bid).first()

        ret = bookmodelserializers(obj,many=False,context={‘request‘: request})
        return Response(ret.data)

    def put(self,request,bid):
        obj = models.Book.objects.get(id=bid)
        bs = bookmodelserializers(obj,data=request.data)
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return Response(bs.errors)

    def delete(self,request,bid):
        models.Book.objects.get(id=bid).delete()
        return HttpResponse("删除成功")

from django.urls import reverse

class Pub_Detail_modelserializer_cbv(APIView):
    def get(self,request,pid):
        obj = models.Publish.objects.filter(id=pid).first()

        ret = pubmodelserializers(obj,many=False,context={‘request‘: request})
        s = reverse("app1:pub_detail",kwargs={"pid":int(pid)})

        return Response(ret.data)

    def put(self,request,pid):
        obj = models.Publish.objects.get(id=pid)
        bs = pubmodelserializers(obj,data=request.data,)
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return Response(bs.errors)

    def delete(self,request,pid):
        models.Publish.objects.get(id=pid).delete()
        return HttpResponse("删除成功")

  

原文地址:https://www.cnblogs.com/bainianminguo/p/10459458.html

时间: 2024-08-28 20:50:32

Django1.0和2.0中的rest_framework的超链接字段的处理的相关文章

java中Integer i1= 0; Integer i2= 0; 为什么可以用 == 符号呢

java中Integer i1= 0; Integer i2= 0;  有i1 == i2,且有i1 = 1;那么i2为什么不会变成1呢? 我这个时候的想法是:这是因为java中整型常量是基于int的,而java中有自动包装机制,也就是说看起来i1,i2是Integer类型,但是其底层还是基于int类型的(不能理解的话在java中还有一个地方那就是Arrays.asList(T...args) 他返回一个基于数组的List,如果在List中改变其大小,那么将会引发异常[UnsupportedOp

C++中减去‘0’的作用( -&#39;0&#39; )

我们在日常研(chao)究(xi)大佬们的代码时,可能会遇到减去字符'0'的情况,比如下图,这种语法问题吧说简单它不那么简单,毕竟不好理解:但说难吧也不难,其实就是让代码更简洁更有逼格的途径而已. 说了那么多屁话那么这个减去零到底是干啥的呢? 它的作用就是减去0的ASCII值:48.可以方便的用来转换大小写或者数字和和字符.比如我们可以写这么一个函数: #include <cstdio> #include <iostream> using namespace std; int ch

OpenGL2.0及以上版本中gl,glut,glew,glfw,mesa等部件的关系

OpenGL2.0及以上版本中gl,glut,glew,glfw,mesa等部件的关系 一.OpenGL OpenGL函数库相关的API有核心库(gl),实用库(glu),辅助库(aux).实用工具库(glut),窗口库(glx.agl.wgl)和扩展函数库等. gl是核心,glu是对gl的部分封装.glx.agl.wgl 是针对不同窗口系统的函数.glut是为跨平台的OpenGL程序的工具包,比aux功能强大(aux很大程度上已经被glut库取代.).扩展函数库是硬件厂商为实现硬件更新利用Op

C++:vector中的v.at(0)和v[0]的区别

设v是一个vector的对象, 如果v是非空的,则v.at(0)和v[0]是没有区别的,都是取数组中第一个值: 如果v是空的,则v.at(0)会抛出异常(exception std::out_of_range),指出数组下标越界,而v[0]的行为是未知的,因为operator[]操作符是不做下标越界检查的,这是为了保证程序执行效率.

android4.0浏览器在eclipse中编译的步骤

工程源码: 注意: 如果下载已经修过的源码,只要进行3.4.8步骤就应该可以了. eclipse版本:adt-bundle-windows (Android Developer Tools Build: v21.0.0-519525) 1.从android4.0系统的代码中拷贝一份浏览器的代码,到本地文件夹,并重命名为BrowserEclipse: < android4.0源码>/package/apps/Browser  -->  <本地目录>/BrowserEclipse

(转)SDL2.0在mfc窗口中显示yuv的一种方法

DWORD ThreadFun() {    //用mfc窗口句柄创建一个sdl window    SDL_Window * pWindow = SDL_CreateWindowFrom( (void *)( GetDlgItem(IDC_STATIC1)->GetSafeHwnd() ) ); SDL_Rect sdlRT;    sdlRT.h = 288;    sdlRT.w = 352;    sdlRT.x = 0;    sdlRT.y = 0; SDL_Rect dstRT; 

Android开发如何在4.0及以上系统中自定义TitleBar

本文将通过一个实例讲解怎么实现在4.0及以上系统版本中实现自定义TitleBar,这只是我自己找到的一种方法; xml布局文件 activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="m

vc6.0运用mysql数据库中的编码所导致的乱码问题(接收和输出的编码必须要一致)

[编译中遇见的问题]       ①在用vc 6.0去调用MySQL中的数据时,出现中文乱码       ②不明白mysql中的码制 [开始解决问题]      ①打开mysql控制台        ②开始展示自己        ③打开vc 6.0(配置mysql环境在这里我就不哆嗦了) 走起.....在vc 6.0中复制下列代码,进行连接mysql和调用代码如下: #include <Windows.h>#include <stdio.h>#include <stdlib.

do...while(0)在宏定义中的巧妙用法

大家都知道,do-while(condition)可以表示循环,但你有没有遇到在一些宏定义中可以不用循环的地方,也用到了 do-while.比如: #define DELETE_POINTER(p) do { if(NULL != p) delete p; p = NULL; }while(0) 这时,do-while(0)的功能就不仅仅是循环了,这是do..while(0)的一种巧妙用法.它有以下几种功能: 1.在后面要加分号,使调用如同函数:调用如下: int* p = new int(5)