Django從Models 10分鐘建立一套R(shí)estfulApi

目錄

效果預(yù)覽

簡(jiǎn)介

Django是一套完善而強(qiáng)大的web開發(fā)框架, 結(jié)合Django Restframework我們可以非??斓拇罱ㄒ惶缀笈_(tái)的api, 該api主要特點(diǎn):

  • 標(biāo)準(zhǔn)的Restful接口, 支持增刪改查
    每個(gè)模型分列表和詳情兩種接口, 列表GET獲取列表/POST新建,詳情接口GET獲取詳情/PUT修改/DELETE刪除
  • 所有接口自帶權(quán)限認(rèn)證
    使用Basic Auth, 詳細(xì)權(quán)限可以通過Admin配置

而我們只需要設(shè)計(jì)好我們的Models(數(shù)據(jù)模型)

實(shí)現(xiàn)步驟

1. 環(huán)境搭建

使用Python3+Django2.1+Django Restframework

pip3 install django
pip3 install djangorestframework

2. 創(chuàng)建項(xiàng)目及應(yīng)用

創(chuàng)建一個(gè)名為django_shop的項(xiàng)目,進(jìn)入項(xiàng)目目錄,創(chuàng)建一個(gè)名為shop的應(yīng)用

django-admin startproject django_shop
cd django_shop
python3 -m manage.py startapp shop

3. 在項(xiàng)目設(shè)置中注冊(cè)我們的應(yīng)用及rest_framework

修改項(xiàng)目目錄下django_shop/settings.py文件
INSTALLED_APP列表中增加兩行, 注冊(cè)應(yīng)用及rest_framework框架

INSTALLED_APPS = [
    ...
    'shop.apps.ShopConfig',
    'rest_framework'
]

文件末尾增加如下REST_FRAMWORK配置, 以使Api權(quán)限生效

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
    ]
}

4. 設(shè)計(jì)和編寫Models(數(shù)據(jù)模型)

Models設(shè)計(jì)實(shí)際上就是數(shù)據(jù)庫(kù)表設(shè)計(jì), 一個(gè)Model對(duì)應(yīng)一張數(shù)據(jù)庫(kù)表, 數(shù)據(jù)模型(數(shù)據(jù)庫(kù)表)的設(shè)計(jì)是一個(gè)項(xiàng)目的核心, 我們需要考慮:

  • 需要哪些模型(表)?
  • 每個(gè)表包含什么字段?
  • 表與表之間的相互關(guān)系(一對(duì)多/一對(duì)一/多對(duì)多)

我們這里設(shè)計(jì)4個(gè)模型(表):

  • Category: 商品分類模型, 包含字段name(分類名稱), slug(分類鏈接)
  • Product: 商品模型, 包含字段category(所屬分類), name(商品名稱), slug(商品鏈接), description(商品描述), price(商品價(jià)格), available(是否上架), created(創(chuàng)建時(shí)間), modified(修改時(shí)間)
  • Order: 訂單模型, 包含字段username(客戶姓名), mobile(客戶電話), address(客戶地址), city(客戶城市), pay_status(是否支付), created(創(chuàng)建時(shí)間), modified(修改時(shí)間)
  • OrderItem: 訂單條目(訂單中每種商品一個(gè)條目), 包含字段order(所屬訂單), product(訂購(gòu)的商品), quantity(訂購(gòu)數(shù)量)

修改項(xiàng)目目錄下的models.py, 創(chuàng)建我們需要的模型

from django.db import models


class Category(models.Model):
    name = models.CharField("分類名稱", max_length=200, db_index=True)
    slug = models.SlugField("分類鏈接", max_length=200, db_index=True, unique=True)


class Product(models.Model):
    category = models.ForeignKey(Category, related_name='category', on_delete=models.CASCADE, verbose_name="所屬分類")
    name = models.CharField("商品名稱", max_length=200, db_index=True)
    slug = models.SlugField("商品鏈接", max_length=200, db_index=True)
    description = models.TextField("商品描述", blank=True)
    price = models.DecimalField("商品價(jià)格", max_digits=10, decimal_places=2)
    available = models.BooleanField("是否上架", default=True)
    created = models.DateTimeField("創(chuàng)建時(shí)間", auto_now_add=True)
    updated = models.DateTimeField("更新時(shí)間", auto_now=True)


class Order(models.Model):
    username = models.CharField("客戶姓名", max_length=50)
    mobile = models.CharField("客戶電話", max_length=25)
    address = models.CharField("客戶地址", max_length=250)
    city = models.CharField("客戶城市", max_length=100)
    pay_status = models.BooleanField("是否支付", default=False)
    created = models.DateTimeField("創(chuàng)建時(shí)間", auto_now_add=True)
    updated = models.DateTimeField("更新時(shí)間", auto_now=True)


class OrderItem(models.Model):
    order = models.ForeignKey(Order, related_name='order_items', on_delete=models.CASCADE, verbose_name="所屬訂單")
    product = models.ForeignKey(Product, related_name='product_items', on_delete=models.CASCADE, verbose_name="訂購(gòu)產(chǎn)品")
    quantity = models.PositiveIntegerField("訂購(gòu)數(shù)量", default=1)

5. 生成數(shù)據(jù)庫(kù)表并創(chuàng)建超級(jí)用戶

在項(xiàng)目目錄下打開命令行窗口, 使用以下命令創(chuàng)建models.py對(duì)應(yīng)的表

python3 manage.py makemigrations
python3 manage.py migrate

使用以下命令創(chuàng)建超級(jí)用戶

python3 manage.py createsuperuser

輸入用戶名/郵箱/密碼(兩遍)創(chuàng)建超級(jí)用戶

6. 編寫Restful Api

6.1 為每個(gè)數(shù)據(jù)模型建立對(duì)應(yīng)的序列化器

每一個(gè)Model實(shí)際上都是一個(gè)Python類的對(duì)象, 對(duì)象一般只能存活于內(nèi)存中,想要進(jìn)行保存和傳輸(作為響應(yīng)返回), 我們一般需要將對(duì)象轉(zhuǎn)化為字符串, 這稱之為序列化
由于每個(gè)Model對(duì)象的結(jié)構(gòu)不同, 我們要為每個(gè)對(duì)象建立對(duì)應(yīng)的序列化器(用于將該Model對(duì)象轉(zhuǎn)為字符串)

在shop應(yīng)用目錄下新建文件夾api, 在api下新建serializers.py,用于存放所有Model的序列化器, 內(nèi)容如下:

from rest_framework import serializers
from ..models import Category, Product, Order, OrderItem

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category   # 要序列化的模型
        fields = '__all__'   # 要序列化的字段

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = '__all__'

class OrderItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__'

默認(rèn)情況下, 每個(gè)Model都可以采用同樣的套路, 復(fù)制粘貼修改即可

6.2 為每個(gè)模型建立對(duì)應(yīng)的Restful Api

在標(biāo)準(zhǔn)的Restful Api模式中, 每個(gè)Model建立兩個(gè)接口:

  • List接口: GET返回列表/POST新建
  • Detail接口: GET返回詳情/PUT修改/DELETE刪除
    在shop/api/目錄下新建views.py, 內(nèi)容如下:
from rest_framework import generics
from .serializers import CategorySerializer, ProductSerializer, OrderSerializer, OrderItemSerializer
from ..models import Category, Product, Order, OrderItem

class CategoryList(generics.ListCreateAPIView):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

class ProductList(generics.ListCreateAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

class ProductDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

class OrderList(generics.ListCreateAPIView):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

class OrderDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

class OrderItemList(generics.ListCreateAPIView):
    queryset = OrderItem.objects.all()
    serializer_class = OrderItemSerializer

class OrderItemDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = OrderItem.objects.all()
    serializer_class = OrderItemSerializer

套路同樣一致, 復(fù)制粘貼修改即可

  • generics.ListCreateAPIView: 指該接口支持列表和新建
  • generics.RetrieveUpdateDestroyAPIView: 指該接口支持詳情/更新/刪除

generics還支持各種單獨(dú)的方法, 詳見generics源碼(Pycharm中按住Ctrl點(diǎn)擊generics)

6.3 為接口掛載接口地址

在shop/api/下新建urls.py, 用于存放本應(yīng)用api的接口地址, 每個(gè)Model格式一樣, 內(nèi)容如下:

from django.urls import path
from . import views

app_name = 'shop'   # 指定命名空間

urlpatterns = [
    path('categories/', views.CategoryList.as_view(), name='category_list'),
    path('categories/<pk>/', views.CategoryDetail.as_view(), name='category_detail'),
    path('products/', views.ProductList.as_view(), name='product_list'),
    path('products/<pk>/', views.ProductDetail.as_view(), name='product_detail'),
    path('orders/', views.OrderList.as_view(), name='order_list'),
    path('orders/<pk>/', views.OrderDetail.as_view(), name='order_detail'),
    path('order_items/', views.OrderItemList.as_view(), name='order_item_list'),
    path('order_items/<pk>/', views.OrderItemDetail.as_view(), name='order_item_detail'),
]

將應(yīng)用api的接口地址掛在到項(xiàng)目的總路由下
修改項(xiàng)目路徑django_shop目錄下的urls.py, 內(nèi)容如下:

from django.contrib import admin
from django.urls import path, include  # 在原有的基礎(chǔ)上增加導(dǎo)入include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/shop/', include('shop.api.urls', namespace='shop')),  # 增加該行
]

7. 運(yùn)行項(xiàng)目及調(diào)試接口

在項(xiàng)目路徑下打開命令窗口, 運(yùn)行 python3 manage.py runserver啟動(dòng)開發(fā)服務(wù)器
打開網(wǎng)頁(yè)訪問: http://127.0.0.1:8000/api/shop/categories/
即可看到分類列表接口(其他列表接口同理修改url即可, 如.../api/shop/projects/)
當(dāng)前尚無(wú)數(shù)據(jù)(非登錄狀態(tài)無(wú)權(quán)限修改數(shù)據(jù))
訪問: http://127.0.0.1:8000/admin/ 使用超級(jí)管理員登錄,并重新回到接口頁(yè)面, 可使用POST創(chuàng)建新數(shù)據(jù), 如下圖:

使用Post創(chuàng)建新數(shù)據(jù)

創(chuàng)建后重新刷新頁(yè)面(分類列表接口)即可看到創(chuàng)建的數(shù)據(jù)

分類詳情接口, 訪問: http://127.0.0.1:8000/api/shop/categories/1/

注意, 列表和詳情統(tǒng)一使用復(fù)數(shù)categories, 1為該分類的id

分類詳情接口操作, 其他模型列表/詳情操作同理

使用Postman測(cè)試Api

  1. 使用Postman測(cè)試所有接口都需要提供Basic Auth授權(quán), 操作方法如下
使用BasicAuth授權(quán), 用戶名和密碼是超級(jí)用戶的用戶名和密碼
  1. 使用POST新建數(shù)據(jù)(支持表單和JSON格式), 其他接口及操作方法同理
使用POST新建數(shù)據(jù)

注: 本次搭建的是通用的增刪改查接口, 一般還需要根據(jù)項(xiàng)目實(shí)際需要進(jìn)行添加和修改

下一節(jié)帶著大家從Models 10分鐘快速定制一套Admin后臺(tái)系統(tǒng)

PS: 雖然標(biāo)題是10分鐘搭建一套R(shí)estful Api接口, 但是實(shí)際寫這篇文章從下午7點(diǎn)下班一致在辦公室寫到凌晨1:20(現(xiàn)在), 碼字不易, 歡迎多多點(diǎn)贊/評(píng)論和贊賞, 如有什么其他想學(xué)的教程也可留言給我

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容