rest_framework_mongoengine实现后端的增删改查

rest_framework_mongoengine实现后端增删改查

一、增删改查

1. 继承ModelViewSet实现增删改查
  • 父urls.py
path("api/testapp/", include("apps.testapp.urls")), # 测试
  • 子urls.py
# -*- coding: utf-8 -*-
from django.urls import path
from rest_framework_mongoengine.routers import SimpleRouter

from apps.testapp.views import TestView, ProductViewSet

urlpatterns = [
    # 测试接口
    ...
]

model_mango_url = SimpleRouter()
model_mango_url.register(r'product', ProductViewSet)
urlpatterns += model_mango_url.urls
print("urlpatterns============", urlpatterns)
  • models.py
from django.db import models

# Create your models here.
from mongoengine import Document, fields


class Product(Document):
    name = fields.StringField(required=True)
    description = fields.StringField()
    price = fields.StringField()
  • serializer.py
from rest_framework import serializers
from rest_framework_mongoengine.serializers import DocumentSerializer

from apps.testapp.models import Product


class ProductSerializer(DocumentSerializer):
    # 序列化的是后更改了name字段 required=False
    name = serializers.CharField(required=False)

    class Meta:
        model = Product
        fields = '__all__'

  • views.py
from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.views import APIView
from rest_framework_mongoengine.viewsets import ModelViewSet

from apps.testapp.models import Product
from apps.testapp.serializers import ProductSerializer


class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
1.1 创建(create)
1.新增单个
POST {{ipaddr}}api/testapp/product/

{
    "name":"iphone14",
    "description":"十分骄傲了就是佛爱事件的发生",
    "price":"12"
}
2.批量插入
  • urls.py
urlpatterns = [
    # 批量插入
    path(r'product/create', ProductViewSet.as_view({'post': 'create_many'})),
]
  • views.py
class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
  
	# 如果重写的是create方法,那么之前的创建单个资源,也会走这个方法,所以为了区分,保留之前的单个字典插入,这里命名craete_many
    def create_many(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data, many=True)

        if serializer.is_valid():
            products = [Product(**item) for item in serializer.validated_data]
            Product.objects.insert(products)
            return Response(serializer.validated_data, status=201)
        return Response(serializer.errors, status=400)
  
  • 测试
POST   {{ipaddr}}api/testapp/product/create

[
    {
        "name": "iphone16",
        "description": "十分骄傲了就是佛爱事件的发生",
        "price": "12"
    },
    {
        "name": "iphone17",
        "description": "十分骄傲了就是佛爱事件的发生",
        "price": "12"
    },
    {
        "name": "iphone18",
        "description": "十分骄傲了就是佛爱事件的发生",
        "price": "12"
    }
]
1.2 读取(read)
1.获取所有列表 list
GET {{ipaddr}}api/testapp/product/

说明:底层使用的list方法

2.获取单个详情 retrieve
GET {{ipaddr}}api/testapp/product/660cbeb432362db8ac968ee9/

说明:底层使用的是retrieve

3.分页查询
GET {{ipaddr}}api/testapp/product?page=2&limit=2
  • settings.py
REST_FRAMEWORK = {
    ...
    "DEFAULT_PAGINATION_CLASS": "dvadmin.utils.pagination.CustomPagination",  # 自定义分页
    ...
}
  • pagination.py
# -*- coding: utf-8 -*-

from collections import OrderedDict

from django.core import paginator
from django.core.paginator import Paginator as DjangoPaginator, InvalidPage
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response


class CustomPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = "limit"
    max_page_size = 999
    django_paginator_class = DjangoPaginator

    def paginate_queryset(self, queryset, request, view=None):
        """
        Paginate a queryset if required, either returning a
        page object, or `None` if pagination is not configured for this view.
        """
        empty = True

        page_size = self.get_page_size(request)
        if not page_size:
            return None

        paginator = self.django_paginator_class(queryset, page_size)
        page_number = request.query_params.get(self.page_query_param, 1)
        if page_number in self.last_page_strings:
            page_number = paginator.num_pages

        try:
            self.page = paginator.page(page_number)
        except InvalidPage as exc:
            # msg = self.invalid_page_message.format(
            #     page_number=page_number, message=str(exc)
            # )
            # raise NotFound(msg)
            empty = False

        if paginator.num_pages > 1 and self.template is not None:
            # The browsable API should display pagination controls.
            self.display_page_controls = True

        self.request = request

        if not empty:
            self.page = []

        return list(self.page)

    def get_paginated_response(self, data):
        code = 2000
        msg = 'success'
        page = int(self.get_page_number(self.request, paginator)) or 1
        total = self.page.paginator.count if self.page else 0
        limit = int(self.get_page_size(self.request)) or 10
        is_next = self.page.has_next() if self.page else False
        is_previous = self.page.has_previous() if self.page else False

        if not data:
            code = 2000
            msg = "暂无数据"
            data = []

        return Response(OrderedDict([
            ('code', code),
            ('msg', msg),
            ('page', page),
            ('limit', limit),
            ('total', total),
            ('is_next', is_next),
            ('is_previous', is_previous),
            ('data', data)
        ]))
4.根据name模糊查询 list

重写list方法,最好不要重写retrieve方法,二者区别如下:

获取所有列表 底层使用list方法:api/product/
获取单个资源 底层使用retrieve:api/product/123456789/ # 数字是id

因此,如果重写retrieve方法,那么传递参数的时候如果再拼接api/product/name/ 底层识别路径参数的时候不容易区分是name还是id;

  • views.py
class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    def list(self, request, *args, **kwargs):
        """
        重写list方法,根据name字段模糊查询,获取所有列表也是走这个方法
        """
        # request.query_params.get('name') 这种方式接受参数 url格式为:/product/?name=apple;
        # kwargs.get("name")  # 这种方式接受参数 url格式:/product/<str:name>/
        name = request.query_params.get('name')
        if name:
            product = Product.objects.filter(name__icontains=name)
            serializer = self.get_serializer(product, many=True)
            return Response(serializer.data)
        else:
            print("list方法 获取所有列表============")
            return super().list(request, *args, **kwargs)

  • 测试
# 根据name模糊查询
GET  {{ipaddr}}api/testapp/product/?name=iphone18
# 查询所有
GET  {{ipaddr}}api/testapp/product/
5.多条件查询 list

重写list方法

  • views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.views import APIView
from rest_framework_mongoengine.viewsets import ModelViewSet

from apps.testapp.models import Product
from apps.testapp.serializers import ProductSerializer

class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    def list(self, request, *args, **kwargs):
        """
        重写list方法,根据name字段模糊查询,获取所有列表也是走这个方法
        """
        # request.query_params.get('name') 这种方式接受参数 url格式为:/product/?name=apple;
        # kwargs.get("name")  # 这种方式接受参数 url格式:/product/<str:name>/
        params = request.query_params
        name = params.get('name')
        price = params.get('price')
        # 根据查询参数过滤 queryset
        queryset = Product.objects.all()
        if name:
            queryset = queryset.filter(name__icontains=name)
        if price:
            queryset = queryset.filter(price=price)
        # 序列化查询结果,并返回响应
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

  • 测试
GET   {{ipaddr}}api/testapp/product/?name=iphone18&price=136
6.返回部分字段
  • views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.views import APIView
from rest_framework_mongoengine.viewsets import ModelViewSet

from apps.testapp.models import Product
from apps.testapp.serializers import ProductSerializer


class TestView(APIView):


class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    def list(self, request, *args, **kwargs):
        """
        重写list方法,根据name字段模糊查询,获取所有列表也是走这个方法
        """
        # request.query_params.get('name') 这种方式接受参数 url格式为:/product/?name=apple;
        # kwargs.get("name")  # 这种方式接受参数 url格式:/product/<str:name>/
        params = request.query_params
        name = params.get('name')
        price = params.get('price')
        queryset = Product.objects.all()
        if name:
            queryset = queryset.filter(name__icontains=name)
        if price:
            queryset = queryset.filter(price=price)

        # 定义一个包含部分字段的新序列化器
        class PartialProductSerializer(ProductSerializer):
            class Meta(ProductSerializer.Meta):
                fields = ('name', 'price')

        # 序列化查询结果,并返回响应
        serializer = PartialProductSerializer(queryset, many=True)
        return Response(serializer.data)
  • 测试
GET  {{ipaddr}}api/testapp/product/?name=iphone18&price=136


[
    {
        "name": "iphone18",
        "price": "136"
    }
]
7.排序查询
  • views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.views import APIView
from rest_framework_mongoengine.viewsets import ModelViewSet

from apps.testapp.models import Product
from apps.testapp.serializers import ProductSerializer


class TestView(APIView):


class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    def list(self, request, *args, **kwargs):
        """
        重写list方法,根据name字段模糊查询,获取所有列表也是走这个方法
        """
        # request.query_params.get('name') 这种方式接受参数 url格式为:/product/?name=apple;
        # kwargs.get("name")  # 这种方式接受参数 url格式:/product/<str:name>/
        params = request.query_params
        name = params.get('name')
        price = params.get('price')
        queryset = Product.objects.all()
        if name:
            queryset = queryset.filter(name__icontains=name)
        if price:
            queryset = queryset.filter(price=price)

        # 定义一个包含部分字段的新序列化器
        class PartialProductSerializer(ProductSerializer):
            class Meta(ProductSerializer.Meta):
                fields = ('name', 'price')
  
		# queryset = queryset.order_by('price')  # 按照price字段升序排序
        queryset = queryset.order_by('-price')  # 按照price字段降序排序
  
        # 序列化查询结果,并返回响应
        serializer = PartialProductSerializer(queryset, many=True)
        return Response(serializer.data)
  • 测试
GET   {{ipaddr}}api/testapp/product/?name=iphone18

[
    {
        "name": "iphone18",
        "price": "436"
    },
    {
        "name": "iphone18",
        "price": "166"
    },
    {
        "name": "iphone18",
        "price": "136"
    },
    {
        "name": "iphone18",
        "price": "12"
    }
]
1.3 更新(update)
1.修改单个
PUT {{ipaddr}}api/testapp/product/660cc1ce799f2e1df6778875/
{
    "price":"15999"
}
2.批量修改

举例:批量修改name="iphone14"的数据,price更新为1300

  • views.py
# Create your views here.
from rest_framework.response import Response
from rest_framework.decorators import api_view, action
from rest_framework.views import APIView
from rest_framework_mongoengine.viewsets import ModelViewSet

from apps.testapp.models import Product
from apps.testapp.serializers import ProductSerializer


class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
  
    """
    @action说明:
    methods:一个列表,包含允许的 HTTP 方法。例如,['get', 'post'] 表示这个动作既允许 GET 请求也允许 POST 请求。
    detail:一个布尔值,指示这个动作是否适用于单个实例。如果设置为 True,则动作的 URL 将包含一个实例的主键,例如 /products/1/batch_update/。
    如果设置为 False,则动作的 URL 不包含实例的主键,例如 /products/batch_update/。
    """
    @action(methods=['post'], detail=False)
    def batch_update(self, request):
        # 获取请求的数据
        data = request.data
        # 确保请求的数据中包含了需要更新的名称和价格
        if 'name' in data and 'price' in data:
            # 获取要更新的名称和价格
            name_to_update = data['name']
            new_price = data['price']
            # 执行批量更新操作
            updated_count = Product.objects.filter(name=name_to_update).update(price=new_price)
            # 返回更新结果
            return Response(
                {'message': f'Updated {updated_count} products.', 'name': name_to_update, 'new_price': new_price})
        else:
            # 如果请求的数据不完整,返回错误信息
            return Response({'error': 'Name and price fields are required.'}, status=400)


  • 测试
POST  {{ipaddr}}api/testapp/product/batch_update/

{
    "name":"iphone14",
    "price":"1300"
}
1.4 删除(Delete)
1.删除单个资源
DELETE  {{ipaddr}}api/testapp/product/660cbeb432362db8ac968ee9/
2.批量删除
  • views.py
from django.http import JsonResponse
from django.shortcuts import render

# Create your views here.
from rest_framework.response import Response
from rest_framework.decorators import api_view, action
from rest_framework.views import APIView
from rest_framework_mongoengine.viewsets import ModelViewSet

from apps.testapp.models import Product
from apps.testapp.serializers import ProductSerializer


class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    @action(methods=['post'], detail=False)
    def batch_delete(self, request):
        # 获取请求的数据
        data = request.data
        # 确保请求的数据中包含了需要删除的名称
        if 'name' in data:
            # 获取要删除的名称
            name_to_delete = data['name']
            # 执行批量删除操作
            deleted_count = Product.objects.filter(name=name_to_delete).delete()
            # 返回删除结果
            return Response({'message': f'Deleted {deleted_count} products.', 'name': name_to_delete})
        else:
            # 如果请求的数据不完整,返回错误信息
            return Response({'error': 'Name field is required.'}, status=400)

  • 测试
POST   {{ipaddr}}api/testapp/product/batch_delete/

{
    "name":"iphone19"
}

相关推荐

  1. rest_framework_mongoengine实现增删

    2024-04-13 22:20:03       28 阅读
  2. 除了增删一定要学会这些!

    2024-04-13 22:20:03       70 阅读
  3. 图表管理功能(前后实现增删

    2024-04-13 22:20:03       46 阅读
  4. SpringBoot实现增删

    2024-04-13 22:20:03       39 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-13 22:20:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-13 22:20:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-13 22:20:03       82 阅读
  4. Python语言-面向对象

    2024-04-13 22:20:03       91 阅读

热门阅读

  1. 说说你对栈、队列的理解?应用场景?

    2024-04-13 22:20:03       38 阅读
  2. WebKit结构简介

    2024-04-13 22:20:03       39 阅读
  3. 乌龟棋(c++实现)

    2024-04-13 22:20:03       39 阅读
  4. uniapp各种常用的提示框

    2024-04-13 22:20:03       33 阅读
  5. C++运算符重载

    2024-04-13 22:20:03       39 阅读
  6. 18. Linux API 编程预备知识

    2024-04-13 22:20:03       25 阅读
  7. 【应用】Spring-Bean注入-xml+注解

    2024-04-13 22:20:03       30 阅读
  8. skynet中newservice和uniqueservice的区别

    2024-04-13 22:20:03       34 阅读
  9. ChatGPT革新学术写作:论文撰写的新思路

    2024-04-13 22:20:03       41 阅读
  10. shell脚本启动jar包

    2024-04-13 22:20:03       34 阅读
  11. C语言隐藏执行其他程序

    2024-04-13 22:20:03       34 阅读
  12. openjudge_2.5基本算法之搜索_1756:八皇后

    2024-04-13 22:20:03       38 阅读