$ cd myapi
$ python -m venv env
$ source env/bin/activate
# on Windows: envScriptsactivate
$ pip install django djangorestframework
$ django-admin startproject myproject
$ cd myproject
$ python manage.py startapp myapp
接下來,更新您的 settings.py 以包含 rest_framework 和您剛剛創建的應用程序:
NSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
# Add this
'myapp',
# Your app
]
讓我們為書籍創建一個簡單的模型。在 myapp/models.py 中:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
published_date = models.DateField()
isbn = models.CharField(max_length=13)
def __str__(self):
return self.title
定義模型后,進行遷移和遷移:
$ python manage.py makemigrations
$ python manage.py migrate
DRF 中的Python 數據類型,這些數據類型可以輕松呈現為 JSON 或其他內容類型。在 myapp/serializers.py 中為 Book 模型創建一個序列化器:
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['id', 'title', 'author', 'published_date', 'isbn']
現在,我們將創建視圖來處理 CRUD 操作。DRF 提供了幾個通用視圖和視圖集,可以輕松實現這些操作。在 myapp/views.py 中:
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
# Create and Read (List) Operations
class BookListCreateView(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
# Retrieve, Update, and Delete Operations
class BookDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
最后,讓我們連接 URL。在 myapp/urls.py 中:
from django.urls import path
from .views import BookListCreateView, BookDetailView
urlpatterns = [
path('books/', BookListCreateView.as_view(), name='book-list'),
path('books//', BookDetailView.as_view(), name='book-detail'),
]
在 myproject/urls.py 中,包含應用程序的 URL:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('myapp.urls')),# Include app URLs
]
要測試您的 API,您可以使用 curl、Postman 或 DRF 提供的 Django-admin API 接口等工具。讓我們看一些示例請求。
創建新書籍(POST 請求)
POST /api/books/
Content-Type: application/json
{
"title": "Django for APIs",
"author": "William S. Vincent",
"published_date": "2020-01-01",
"isbn": "9781735467207"
}
響應:
{
"id": 1,
"title": "Django for APIs",
"author": "William S. Vincent",
"published_date": "2020-01-01",
"isbn": "9781735467207"
}
獲取所有書籍(GET 請求)
GET /api/books/
響應:
[
{
"id": 1,
"title": "Django for APIs",
"author": "William S. Vincent",
"published_date": "2020-01-01",
"isbn": "9781735467207"
}
]
更新書籍(PUT 請求)
PUT /api/books/1/
Content-Type: application/json
{
"title": "Django for APIs Updated",
"author": "William S. Vincent",
"published_date": "2020-01-01",
"isbn": "9781735467207"
}
響應:
{
"id": 1,
"title": "Django for APIs Updated",
"author": "William S. Vincent",
"published_date": "2020-01-01",
"isbn": "9781735467207"
}
刪除書籍(DELETE 請求)
DELETE /api/books/1/
響應:204 無內容
以下是使用 Django 和 Django REST Framework (DRF) 構建 RESTful API 時可以采用的一些其他演示和方法,每個演示和方法都重點介紹了實現 CRUD 操作的不同方法。
DRF 提供 ViewSet 和 Routers,可簡化 URL 路由和視圖。我們可以使用 ViewSet 在一個類中定義所有操作,而不必為每個 CRUD 操作手動定義視圖。
在此演示中,我們將使用 ViewSet 為 Book 模型創建相同的 CRUD 操作。
首先,更新 views.py 以使用 ViewSets:
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
我們可以使用 DRF 的 DefaultRouter,而不必手動編寫 URL,它將自動為所有 CRUD 操作(列出、檢索、創建、更新、刪除)創建路由。
在 myapp/urls.py 中,使用路由器:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BookViewSet
router = DefaultRouter()
router.register(r'books', BookViewSet)# Register the viewseturlpatterns = [
path('', include(router.urls)),# Include router-generated URLs
]
此方法將自動創建以下 URL:
1.3 測試 ViewSet CRUD 操作
您可以使用 Postman 或 curl 等工具測試這些 API:
創建新圖書 (POST):
POST /books/
Content-Type: application/json
{
"title": "REST API Design",
"author": "Michael Stowe",
"published_date": "2016-07-18",
"isbn": "9781491924509"
}
檢索所有圖書 (GET):
GET /books/
更新圖書 (PUT):
PUT /books/1/
Content-Type: application/json
{
"title": "REST API Design Updated",
"author": "Michael Stowe",
"published_date": "2016-07-18",
"isbn": "9781491924509"
}
刪除圖書 (DELETE):
DELETE /books/1/
有時,您可能希望自定義視圖或更好地控制特定 API 操作。在此演示中,我們將使用 DRF Mixins 手動處理 Book 模型的 CRUD 操作。
在 views.py 中,為每個操作使用特定的 mixins:
from rest_framework import generics, mixins
from .models import Book
from .serializers import BookSerializer
class BookListCreateView(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
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 BookDetailView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
在這里,我們手動定義要包含哪些 mixin。這使我們能夠更好地控制自定義各個操作的行為。
在 urls.py 中,您可以手動定義路由:
from django.urls import path
from .views import BookListCreateView, BookDetailView
urlpatterns = [
path('books/', BookListCreateView.as_view(), name='book-list-create'),
path('books//', BookDetailView.as_view(), name='book-detail'),
]
以與之前相同的方式測試操作。功能(POST、GET、PUT、DELETE)將保持不變,但使用 mixins 可讓您輕松擴展或自定義操作。
為了增強您的 API,您可以將過濾、搜索和分頁等功能與 DRF 的內置類集成。
首先,安裝 django-filter:
$ pip install django-filter
然后,將其添加到 settings.py:
INSTALLED_APPS = [
...
'django_filters',
# Add this line
]
在 views.py 中,實現過濾:
from rest_framework import viewsets, filters
from django_filters.rest_framework import DjangoFilterBackend
from .models import Book
from .serializers import BookSerializer
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ['author', 'published_date']
# Filter by these fields
search_fields = ['title', 'author']
# Search within these fields
要實現分頁,請在 settings.py 中配置它:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
# Return 10 items per page
}
這將在調用 GET /books/ 端點時自動對結果進行分頁。
按作者過濾 (GET):
GET /books/?author=Michael%20Stowe
按標題搜索 (GET):
GET /books/?search=Design
分頁響應 (GET):
GET /books/?page=2
您可以使用 DRF 提供的 @action 裝飾器將自定義操作添加到您的 ViewSet。
在 views.py 中,向 BookViewSet 添加自定義操作:
from rest_framework.decorators import action
from rest_framework.response import Response
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
@action(detail=False, methods=['get'])
def recent_books(self, request):
recent_books = Book.objects.order_by('-published_date')[:5]
serializer = self.get_serializer(recent_books, many=True)
return Response(serializer.data)
自定義操作將自動添加到路由器 URL。上述操作可通過以下方式訪問:
GET /books/recent_books/
獲取最近的書籍(GET):
GET /books/recent_books/
文章轉自微信公眾號@攻城獅奶爸雜貨鋪