เฟรมเวิร์ก Django REST: serializer ที่ไม่ใช่โมเดล


158

ฉันเริ่มต้นในกรอบงาน Django REST และต้องการคำแนะนำของคุณ ฉันกำลังพัฒนาบริการเว็บ บริการจะต้องจัดเตรียมส่วนต่อประสาน REST กับบริการอื่น ๆ ส่วนต่อประสาน REST ที่ฉันต้องนำไปใช้นั้นไม่ได้ทำงานกับแบบจำลองของฉันโดยตรง (ฉันหมายถึงการดำเนินการรับ, วาง, โพสต์, ลบ) แต่จะให้บริการอื่น ๆ ด้วยผลการคำนวณบางส่วน ตามคำขอของฉันบริการของฉันทำการคำนวณและส่งคืนผลลัพธ์กลับมา (ไม่เก็บผลลัพธ์ไว้ในฐานข้อมูลของตัวเอง)

ด้านล่างนี้เป็นความเข้าใจของฉันเกี่ยวกับวิธีการนำอินเตอร์เฟส REST ไปใช้งาน ถูกต้องฉันถ้าฉันผิด

  1. สร้างคลาสที่ทำให้การคำนวณ ตั้งชื่อมันว่า 'CalcClass' CalcClass ใช้โมเดลในการทำงาน
    • พารามิเตอร์ที่จำเป็นสำหรับการคำนวณจะถูกส่งไปยังตัวสร้าง
    • ใช้การดำเนินการคำนวณ มันจะส่งคืนผลลัพธ์เป็น 'ResultClass'
  2. สร้าง ResultClass
    • มาจากวัตถุ
    • มันมีเพียงคุณสมบัติที่มีผลลัพธ์การคำนวณ
    • ส่วนหนึ่งของผลการคำนวณจะแสดงเป็น tuple ของ tuples ดังที่ฉันเข้าใจแล้วจะเป็นการดีกว่าถ้าจะทำให้ซีเรียลไลซ์เซชั่นต่อไปใช้คลาสแยกต่างหากสำหรับผลลัพธ์เหล่านั้นและเพิ่มรายการของออบเจ็กต์ดังกล่าวไปยัง
  3. สร้าง Serializer สำหรับ ResultClass
    • สืบทอดมาจาก serializers.Serializer
    • ผลลัพธ์จากการคำนวณเป็นแบบอ่านอย่างเดียวดังนั้นให้ใช้คลาสส่วนใหญ่เป็นฟิลด์สำหรับฟิลด์แทนที่จะเป็นคลาสพิเศษเช่น IntegerField
    • ฉันไม่ควรใช้วิธี save () ทั้งใน ResultClass หรือ Serializer เพราะฉันจะไม่เก็บผลลัพธ์ (ฉันแค่ต้องการส่งคืนตามที่ร้องขอ)
    • Impl serializer สำหรับผลลัพธ์ที่ซ้อนกัน (จำ tuple ของ tuples ที่กล่าวถึงข้างต้น)
  4. สร้างมุมมองเพื่อส่งคืนผลลัพธ์การคำนวณ
    • สืบทอดมาจาก APIView
    • ต้องการเพียงแค่รับ ()
    • ใน get () สร้าง CalcClass ด้วย params ที่ดึงมาจากการร้องขอ, เรียก calc (), รับ ResultClass, สร้าง Serializer และส่ง ResultClass ไปที่มัน, ส่งคืน Response (serializer.data)
  5. URL ที่
    • ไม่มีราก api ในกรณีของฉัน ฉันควรมี URL เพื่อรับผลการคำนวณต่างๆ (คำนวณด้วยพารามิเตอร์ต่าง)
    • เพิ่มการเรียก format_suffix_patterns สำหรับการเรียกดู API

ฉันพลาดอะไรไปหรือเปล่า? วิธีการที่ถูกต้องโดยทั่วไป?


วิธีการนี้ถูกต้องและจริง ๆ แล้วฉันดูหรูหรากว่าคำตอบที่ยอมรับ (ข้อมูลผลลัพธ์ถูกห่อหุ้มในประเภทผลลัพธ์ที่นำมาใช้ซ้ำได้) แต่ในตอนท้ายของวันนี้ส่วนใหญ่เป็นคำถามของการตั้งค่าส่วนตัวและทั้งสองวิธีการทำงาน
zepp.lee

คำตอบ:


157

Django-rest-framework ทำงานได้ดีแม้ไม่ได้ผูกกับแบบจำลอง วิธีการของคุณดูโอเค แต่ฉันเชื่อว่าคุณสามารถตัดบางขั้นตอนเพื่อให้ทุกอย่างทำงานได้

ตัวอย่างเช่นเฟรมเวิร์กที่เหลือมาพร้อมกับ renderers ในตัวไม่กี่ตัว นอกกรอบก็สามารถส่งคืน JSON และ XML ให้กับผู้ใช้ API คุณสามารถเปิดใช้งาน YAML ได้โดยเพียงแค่ติดตั้งโมดูลหลามที่ต้องการ Django-rest-framework จะส่งออกวัตถุพื้นฐานใด ๆ เช่น dict, list และ tuple โดยไม่ต้องทำงานใด ๆ เพิ่มเติมในส่วนของคุณ

ดังนั้นโดยทั่วไปคุณต้องสร้างฟังก์ชันหรือคลาสที่ใช้ในการโต้แย้งทำการคำนวณที่จำเป็นทั้งหมดและส่งคืนผลลัพธ์ในรูปแบบ tuple ไปยังมุมมอง REST api หาก JSON และ / หรือ XML ตรงกับความต้องการของคุณ django-rest-framework จะดูแลการทำให้เป็นอนุกรมสำหรับคุณ

คุณสามารถข้ามขั้นตอนที่ 2 และ 3 ในกรณีนี้และใช้คลาสเดียวสำหรับการคำนวณและอีกหนึ่งคลาสสำหรับการนำเสนอไปยังผู้บริโภค API

นี่เป็นตัวอย่างข้อมูลบางส่วนที่อาจช่วยคุณได้:

โปรดทราบว่าฉันยังไม่ได้ทดสอบ มันมีไว้เพื่อเป็นตัวอย่างเท่านั้น แต่ควรใช้งานได้ :)

CalcClass:

class CalcClass(object):

    def __init__(self, *args, **kw):
        # Initialize any variables you need from the input you get
        pass

    def do_work(self):
        # Do some calculations here
        # returns a tuple ((1,2,3, ), (4,5,6,))
        result = ((1,2,3, ), (4,5,6,)) # final result
        return result

มุมมอง REST:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from MyProject.MyApp import CalcClass


class MyRESTView(APIView):

    def get(self, request, *args, **kw):
        # Process any get params that you may need
        # If you don't need to process get params,
        # you can skip this part
        get_arg1 = request.GET.get('arg1', None)
        get_arg2 = request.GET.get('arg2', None)

        # Any URL parameters get passed in **kw
        myClass = CalcClass(get_arg1, get_arg2, *args, **kw)
        result = myClass.do_work()
        response = Response(result, status=status.HTTP_200_OK)
        return response

URL ของคุณ:

from MyProject.MyApp.views import MyRESTView
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    # this URL passes resource_id in **kw to MyRESTView
    url(r'^api/v1.0/resource/(?P<resource_id>\d+)[/]?$', login_required(MyRESTView.as_view()), name='my_rest_view'),
    url(r'^api/v1.0/resource[/]?$', login_required(MyRESTView.as_view()), name='my_rest_view'),
)

รหัสนี้ควรรายการการส่งออกของรายการเมื่อคุณเข้าถึงhttp://example.com/api/v1.0/resource/?format=json ถ้าใช้คำต่อท้ายคุณสามารถใช้แทนด้วย?format=json .jsonนอกจากนี้คุณยังสามารถระบุการเข้ารหัสที่คุณต้องการรับกลับโดยเพิ่ม"Content-type"หรือ"Accept"ส่วนหัว

[
  [
    1, 
    2, 
    3
  ], 
  [
    4, 
    5, 
    6
  ]
]

หวังว่านี่จะช่วยคุณได้


2
สวัสดีกาเบรียล! ขอบคุณสำหรับคำตอบ! ฉันนำสิ่งที่ฉันต้องการไปใช้แล้วตามแผนที่วางไว้ ทำงานได้ดี! ฉันใช้ serializer เพื่อการส่งออก json ที่ดีขึ้น
Zakhar

3
ฉันได้ลองทำตามคำแนะนำนี้แล้ว แต่ได้รับ: "ไม่สามารถใช้ DjangoModelPermissions ในมุมมองที่ไม่มีคุณสมบัติ.modelหรือ.queryset" ฉันลองตัวอย่างที่ให้มาแล้ว มันอาจเป็นอะไรกับ django-rest-framework รุ่นล่าสุดหรือไม่
ออร์แลนโด

ตัวอย่างนี้ถูกเขียนขึ้นเมื่อไม่นานมานี้ ฉันไม่มีโอกาสได้ทำงานกับ Django อีกเลย แต่คุณอาจพบบางสิ่งที่มีประโยชน์ที่นี่: django-rest-framework.org/api-guide/routers
Gabriel Samfira

1
ตัวอย่างนี้คือสิ่งที่ฉันต้องการสำหรับความต้องการของฉันคือบริการที่กำลังดำเนินการบางอย่างโดยไม่มี serializer ที่ไม่ใช่รุ่น!
Khalil TABBAL

@Orlando: ดูที่นี่วิธีการใช้ตรรกะสิทธิ์เฉพาะสำหรับมุมมองที่ไม่ใช่รูปแบบที่มี djang-restframework 3: stackoverflow.com/a/34040070/640916
djangonaut

-1

ใน urls.py ฟังก์ชัน login_required ต้องการ

from django.contrib.auth.decorators import login_required

ถ้านั่นเป็นเพียงความคิดเห็นแทนคำตอบให้ลองใช้add a commentเซสชั่น
lucascavalcante
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.