django ninja api 简明教程

 

https://eadwincode.github.io/django-ninja-jwt/

https://pypi.org/project/django-ninja-jwt/

 

中文博客简明教程:https://blog.csdn.net/qq_43373298/article/details/121384656

官网教程(读一遍不费劲,很舒服): https://django-ninja.rest-framework.com/

动手实践了2类api

 

genera.url.py

from appninja.api import api
urlpatterns = [
    path('admin/xxzx/', admin.site.urls),
    path('api/', api.urls),

appninja.api.py

from ninja import NinjaAPI
from ninja import  Schema
api = NinjaAPI()
from appninja.api1 import router as router1
from appninja.api2 import router as router2
from appninja.api3 import router as router3
from appninja.api_tree import router as router_tree
api.add_router("/api1/", router1)
api.add_router("/api2/", router2)
api.add_router("/api3/", router3)
api.add_router("/apitree/", router_tree)

#http://127.0.0.1:8000/api/add?a=1&b=2
@api.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}

api_tree.py

from ninja import NinjaAPI
from ninja import  Schema
from ninja import Router
from django.shortcuts import render, get_object_or_404, redirect
from appninja.models import Testig
router = Router()
api = NinjaAPI()
class JgOut(Schema):
    id: int
    name: str
    pid: int
class JgIn(Schema):
    name: str
    pid: int
class Jginout(Schema):
    id: int =None
    name: str  =None
    pid: int  =None

@router.post("/ins_or_upd")
def create_employee(request, payload: Jginout):
    print(payload)
    if payload.id:
        testjg = get_object_or_404(Testig, id=payload.id)
        for attr, value in payload.dict().items():
            setattr(testjg, attr, value)
        testjg.save()
    else:
         payload.id=None
         testjg = Testig.objects.create(**payload.dict())

    return {'result': testjg.id }

@router.post("/post_del")
def post_del_Testig(request, plyload: Jginout):
    person = get_object_or_404(Testig, id=plyload.id)
    person.delete()
    return {"result": 'Success'}

#参数必须是pId ,注意大小写,pid不可以形成tree
@router.get('/treedict_good')
def treedict_good(request):
    dictdata=Testig.objects.annotate(pId=F('pid')).values('id','pId','name')
    return list(dictdata)

api_crud.py

from ninja import NinjaAPI
api = NinjaAPI()
from appninja.models import Employee,Department
from datetime import date
from ninja import Field, Schema
from ninja import UploadedFile, File
from django.shortcuts import render, get_object_or_404, redirect
class EmployeeIn(Schema):
    first_name: str
    last_name: str
    department_id: int = None
    birthdate: date = None

@api.post("/employees")
def create_employee(request, payload: EmployeeIn):
    employee = Employee.objects.create(**payload.dict())
    return {"id": employee.id}


@api.post("/employees")
def create_employee(request, payload: EmployeeIn, cv: UploadedFile = File(...)):
    payload_dict = payload.dict()
    employee = Employee(**payload_dict)
    employee.cv.save(cv.name, cv) # will save model instance as well
    return {"id": employee.id}

from django.core.files.storage import FileSystemStorage
from ninja import UploadedFile, File

STORAGE = FileSystemStorage()

@api.post("/upload")
def create_upload(request, cv: UploadedFile = File(...)):
    filename = STORAGE.save(cv.name, cv)
    # Handle things further

class EmployeeOut(Schema):
    id: int
    first_name: str
    last_name: str
    department_id: int = None #None is default,it can display the actual value
    birthdate: date = None
@api.get("/employees/{employee_id}", response=EmployeeOut)
def get_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    return employee
#如果不用employOut,则会 TypeError: Object of type Employee is not JSON serializable 错误
#EmployeeOut自动把object转变为json,并且validate

from typing import List
#List和list区别不大,主要用于类型注解
@api.get("/employees", response=List[EmployeeOut])
def list_employees(request):
    qs = Employee.objects.all()
    return qs

#put用于更新
@api.put("/employees/{employee_id}")
def update_employee(request, employee_id: int, payload: EmployeeIn):
    employee = get_object_or_404(Employee, id=employee_id)
    for attr, value in payload.dict().items():
        setattr(employee, attr, value)
    employee.save()
    return {"success": True}


@api.delete("/employees/{employee_id}")
def delete_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    employee.delete()
    return {"success": True}


class TaskSchema(Schema):
    id: int
    title: str
    # The first Field param is the default, use ... for required fields.
    completed: bool = Field(..., alias="is_completed")
    owner_first_name: str = Field(None, alias="owner.first_name")



#It is also possible to return regular django http responses:
from django.http import HttpResponse
from django.shortcuts import redirect

@api.get("/http")
def result_django(request):
    return HttpResponse('some data')   # !!!!

@api.get("/something")
def some_redirect(request):
    return redirect("/some-path")  # !!!!

效果1 api_tree

 效果2 api_crud

 

特点总结:

1、遇到问题,看 http://127.0.0.1:8000/api/docs ,查看api是否存在

 

 

2、遇到api错误 不要慌,基本就是以下原因

   (1)api的methon错误,如get api,html端用post请求

  (2)请求端的参数,与api参数不匹配,建议用schema

 (3)路径错误,api找不到

 (4)api逻辑端,queryset错误,如get_object_or_404返回404错误

3、建议使用router,不论多简单,可以划分文件 api1.py,  api2.py,可以划分请求路径,  用不用router的特殊区别 注意以下红字

#不用route
@api.
get("/add") def add(request, a: int, b: int): return {"result": a + b} #用route @router.get('/treedict_good') def treedict_good(request): dictdata=Testig.objects.annotate(pId=F('pid')).values('id','pId','name') return list(dictdata)

 

4、一切都可以用get+post搞定,不用路径参数,post提交必须用schema

   (1) crud例子:参考了官网crud的例子,提现了resuful : 用put \delete\get\post等各种method,还用了路径参数 delete/{id} 

     缺点:不统一,容易引发错误

(2)tree的例子:一切用get+post搞定,传递参数就用schema,(in、out、inout )

    优点:统一、代码容易复制,方便记忆

posted @ 2023-07-03 10:20  花生与酒  阅读(1364)  评论(0编辑  收藏  举报