Django REST framework: serializer non-model

158

Saya pemula dalam kerangka Django REST dan butuh saran Anda. Saya sedang mengembangkan layanan web. Layanan harus menyediakan antarmuka REST ke layanan lain. Antarmuka REST, yang perlu saya terapkan, tidak bekerja dengan model saya secara langsung (maksud saya operasi get, put, post, delete). Sebagai gantinya, ia menyediakan layanan lain dengan beberapa hasil perhitungan. Berdasarkan permintaan, layanan saya membuat perhitungan dan mengembalikan hasilnya (tidak menyimpan hasilnya dalam database sendiri).

Di bawah ini adalah pemahaman saya tentang bagaimana antarmuka REST dapat diimplementasikan. Koreksi saya, jika saya salah.

  1. Buat kelas yang membuat perhitungan. Beri nama 'CalcClass'. CalcClass menggunakan model dalam pekerjaannya.
    • Params yang diperlukan untuk perhitungan diteruskan ke konstruktor.
    • Laksanakan operasi kalk. Ini mengembalikan hasil sebagai 'ResultClass'.
  2. Buat ResultClass.
    • Berasal dari objek.
    • Hanya saja memiliki atribut yang berisi hasil kalk.
    • Salah satu bagian dari hasil perhitungan direpresentasikan sebagai tupel tupel. Seperti yang saya pahami, akan lebih baik untuk serialisasi lebih lanjut untuk mengimplementasikan kelas yang terpisah untuk hasil tersebut dan menambahkan daftar objek tersebut ke ResultClass.
  3. Buat Serializer untuk ResultClass.
    • Berasal dari serializers. Serializer.
    • Hasil kalk hanya baca, jadi gunakan sebagian besar kelas bidang untuk bidang, bukan kelas khusus, seperti IntegerField.
    • Saya seharusnya tidak mengimplementasikan metode save () baik pada ResultClass, maupun Serializer, karena saya tidak akan menyimpan hasilnya (saya hanya ingin mengembalikannya berdasarkan permintaan).
    • Serializer impl untuk hasil bersarang (ingat tupel tupel yang disebutkan di atas).
  4. Buat Lihat untuk mengembalikan hasil perhitungan.
    • Berasal dari APIView.
    • Perlu hanya mendapatkan ().
    • Di get () buat CalcClass dengan params yang diambil dari permintaan, panggil kalnya (), dapatkan ResultClass, buat Serializer, dan berikan ResultClass ke sana, kembalikan Respons (serializer.data).
  5. URL
    • Tidak ada akar api dalam kasus saya. Saya seharusnya hanya memiliki URL untuk mendapatkan berbagai hasil kalk (kalk dengan par berbeda).
    • Tambahkan memanggil format_suffix_patterns untuk menjelajah api.

Apakah saya melewatkan sesuatu? Apakah pendekatannya benar secara umum?

Zakhar
sumber
Pendekatan ini benar dan bagi saya benar-benar terlihat lebih elegan daripada jawaban yang diterima (data hasil dienkapsulasi dalam jenis hasil yang dapat digunakan kembali). Tetapi pada akhir hari ini sebagian besar adalah pertanyaan tentang preferensi pribadi dan kedua pendekatan melakukan pekerjaan.
zepp.lee

Jawaban:

157

Django-rest-framework bekerja dengan baik bahkan tanpa mengikatnya pada model. Pendekatan Anda kedengarannya oke, tapi saya yakin Anda bisa memangkas beberapa langkah agar semuanya berjalan baik.

Misalnya, kerangka istirahat dilengkapi dengan beberapa penyaji bawaan. Di luar kotak, JSON dan XML dapat dikembalikan ke konsumen API. Anda juga dapat mengaktifkan YAML dengan hanya menginstal modul python yang diperlukan. Django-rest-framework akan menampilkan objek dasar seperti dict, list, dan tuple tanpa kerja ekstra dari Anda.

Jadi pada dasarnya Anda hanya perlu membuat fungsi atau kelas yang mengambil argumen, melakukan semua perhitungan yang diperlukan dan mengembalikan hasilnya dalam tuple ke tampilan api REST. Jika JSON dan / atau XML sesuai dengan kebutuhan Anda, django-rest-framework akan menangani serialisasi untuk Anda.

Anda dapat melewati langkah 2 dan 3 dalam hal ini, dan cukup gunakan satu kelas untuk perhitungan dan satu untuk presentasi kepada konsumen API.

Berikut beberapa cuplikan yang dapat membantu Anda:

Harap dicatat bahwa saya belum menguji ini. Itu hanya dimaksudkan sebagai contoh, tetapi harus bekerja :)

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

Tampilan 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

Urls.py Anda:

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'),
)

Kode ini akan menampilkan daftar daftar ketika Anda mengakses http://example.com/api/v1.0/resource/?format=json . Jika menggunakan akhiran, Anda bisa menggantinya ?format=jsondengan .json. Anda juga dapat menentukan pengodean yang ingin Anda kembali dengan menambahkan "Content-type"atau "Accept"ke header.

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

Semoga ini bisa membantu Anda.

Gabriel Samfira
sumber
2
Hai Gabriel! Terima kasih atas jawaban Anda! Saya sudah mengimplementasikan apa yang saya butuhkan sesuai dengan rencana saya. Bekerja dengan baik! Saya menggunakan serializer untuk output json yang lebih baik.
Zakhar
3
Saya telah mencoba mengikuti saran ini tetapi saya mendapatkan: "Tidak dapat menerapkan DjangoModelPermissions pada tampilan yang tidak memiliki .modelatau .querysetproperti.". Saya telah mencoba contoh yang diberikan. Mungkinkah itu sesuatu dengan versi terbaru django-rest-framework?
Orlando
Contoh ini telah ditulis beberapa waktu lalu. Sejak itu saya tidak punya kesempatan untuk bekerja dengan Django lagi. tetapi Anda mungkin menemukan sesuatu yang berguna di sini: django-rest-framework.org/api-guide/routers
Gabriel Samfira
1
Contoh ini persis apa yang saya butuhkan untuk kebutuhan saya adalah layanan yang melakukan beberapa operasi tanpa serializer non model!
Khalil TABBAL
@Orlando: Lihat di sini cara menerapkan logika izin khusus untuk tampilan non-model dengan djang-restframework 3: stackoverflow.com/a/34040070/640916
djangonaut
-1

Di urls.py, fungsi login_required membutuhkan

from django.contrib.auth.decorators import login_required
ymorvan
sumber
jika itu hanya komentar alih-alih jawaban, pertimbangkan untuk menggunakan add a commentsesi ini
lucascavalcante