Django REST framework

参考:

---------------------------------------------------------------------------------------------------------------------------------

DRF | YUAN

10 序列化器的save操作_哔哩哔哩_bilibili

py 写抽象方法的技巧:方法抛异常,(子类实现就使用会报异常)或者用@abstractmethod 
coreapi 在新文档 【DRF配置管理】如何建立coreapi风格接口文档-CSDN博客

fbv  cbv GenericAPIView (通用视图) ViewSet ,装饰器

---------------------------------------------------------------------------------------------------------------------------------

一,View类

        django 自带的类,自带crud操作(rest风格) ,只能接受urlencoded 传参。

二,ApiView类 

     1,介绍

        drf 里的类,继承View 类,改写了as_view() 和 dispatch() 方法,可以接受json传参,(可以配置认证,鉴权)。

                a,xxxView  :get() 列表查询,post() 新增;

                b,xxxDetailView:get() 单记录查询,delete() 删除单条,put() 单条更新

                c,简单序列器:serialiazers.serialiazer :

                     要自己写属性,重写create、update() 方法才能save()。

                d,增强序列化器 serialiazers.ModelSerialiazer

                    作用: 序列化(instance)和反序列化(data),校验属性(序列化类的属性参数)

                    不用自已写属性,create,update()方法            

     2,路由和接口  

               a, path ("api/xxx",views.xxxView.as_view())

               b,  re_path("api/xxx/(\d+)",views.xxxDetailView.as_view())

               c,  取参:request.data

               d, 序列化:xxxSerialiazers (instance=)

               e, 校验:xxxSerialiazers.is_vaild()

               f,  业务逻辑:

               g,返回:respose() ,respose(serialiazer.data),respose(serialiazer.errers)

三,GenericAPIView  通用试图类

     1,介绍

        只需改变 querySet 和 serializer_class 属性 ,方法所有view,detailView 通用(方法与变量解耦了)。因为GenericAPIView  继承APIView ,增加了querySet ,serializer_class ,调度的4个相关方法。

    2,路由和接口:        

       a,路由:

                path ("api/xxx",views.xxxView.as_view())

                re_path("api/xxx/(?P<pk>\d+)",views.xxxDetailView.as_view())

        b,属性:

                querySet = xxx.Objects.all()

                serializer_class = xxxSerializers       

class  xxxSerialiazers(serialiazers.ModelSerialiazer):    
    class    Meta:
     model = xxx;
    fields = "__all__"

       c,接口类

class  xxxView(GenericAPIView):
  def get(self,request):
    pass

  def pust(self,request):
    pass

class  xxxDetailView(GenericAPIView):
    def delete(self,request):
        pass

    def put(self,request):
        pass

    def get(self,request):
        pass

四,ViewSet    

        1 .介绍,

        yyyyMixin 5个混合类   

       ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典{“http请求”:“视图方法”}的映射处理工作,如{‘get’:’list’},重写as_view(),可以传参数了。

        (view,APIView,Generic,混合类, 按请求方法get,put,post..自动路由)

        2,路由和接口

                a,路由

from django.urls import path, re_path

from vset.views import BookView

urlpatterns = [
    # path("set", views.BookView.as_view({"http请求":"视图方法"})),
    path("books/", BookView.as_view({
        "get": "get_all_book",
        "post": "add_book"
    })),
    re_path("^books/(?P<pk>\d+)$", BookView.as_view({
        "get": "get_one_book",
        "put": "edit_book",
        "delete": "delete",
    })),
]

               b,视图类

from rest_framework import serializers
from rest_framework import status
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet

from sers.models import Book


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"


class BookView(ViewSet):

    def get_all_book(self, request):

        books = Book.objects.all()
        bs = BookSerializer(instance=books, many=True)
        return Response(bs.data)

    def add_book(self, request):
        bs = BookSerializer(data=request.data)
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return Response(bs.errors)

    def get_one_book(self, request, pk):
        book = Book.objects.get(pk=pk)
        bs = BookSerializer(instance=book)
        return Response(bs.data)

    def edit_book(self, request, pk):
        instance = Book.objects.get(pk=pk)
        bs = BookSerializer(instance=instance, data=request.data)
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return Response(bs.errors)

    def delete(self, request, pk):
        Book.objects.get(pk=pk).delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

五,GenericViewSet 分发逻辑

       class xxxView(GenericViewSet, ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):

from django.urls import path, re_path

from vset.views import BookView

urlpatterns = [
    # path("set", views.BookView.as_view({"http请求":"视图方法"})),
    path("books/", BookView.as_view({
        "get": "list",
        "post": "create"
    })),
    re_path("^books/(?P<pk>\d+)$", BookView.as_view({
        "get": "retrieve",
        "put": "update",
        "delete": "delete",
    })),
]

GenericViewSet ,分发逻辑

不带pk:

        ListModelMixin,列表查询 get

        CreateModelMixin:单条新增 post    

带pk:

        RetrieveModelMixin:单条查询 get

        UpdateModelMixin :单条更新 put

        DestroyModelMixin:单条删除 delete

六,ModelViewSet()  终极版

       继承 GenericViewSet, ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin,

七,注册路由

参考:自动生成路由_router.register_GG_Bonin的博客-CSDN博客

        router.register('book', BookView, base_name='book')

        detail: pk有关,默认是False, 控制生成的路由是:/user/login还是/user/pk/login

代替

   path("books/", BookView.as_view({
        "get": "list",
        "post": "create"
    })),
    re_path("^books/(?P<pk>\d+)$", BookView.as_view({
        "get": "retrieve",
        "put": "update",
        "delete": "delete",
    })),

八,查询:

        在Django中,Q对象用于构建复杂的查询条件,可以处理多个查询条件的组合和嵌套。Q对象可以使用位运算符(&、|、~)来表示逻辑运算符(AND、OR、NOT)

        1,django orm 的查询

下面是一些常见的Q对象的用法:

  1. 导入Q对象:

python复制代码

from django.db.models import Q
  1. 使用Q对象构建查询条件:

python复制代码

# 单个查询条件
query = Q(name='John')
# 多个查询条件的组合
query = Q(name='John') & Q(age__gt=20)
# 嵌套查询条件
query = Q(name='John') | (Q(age__gt=20) & Q(gender='M'))
  1. 在查询中使用Q对象:

python复制代码

from django.db.models import Q
from myapp.models import MyModel
# 构建查询条件
query = Q(name='John') | (Q(age__gt=20) & Q(gender='M'))
# 使用查询条件进行过滤
results = MyModel.objects.filter(query)

上述示例中,我们导入了Q对象,并使用它来构建了一个复杂的查询条件。我们将Q对象传递给filter()方法,它将返回满足条件的模型实例列表。

        2,原生查询

        参考:百度安全验证

        在Django执行原生SQL有以下三种方式

        a,extra:Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) 

django ORM之 extra() 函数 - 简书       Django不通过外键实现多表关联查询-阿里云开发者社区​​​​​​

'''
需求
不通过外键,使用django orm语法实现多个表之间的关联查询,类似如下sql的查询效果:
SELECT tb_project_version.*, tb_sprint.name, tb_project.name
FROM tb_project_version
JOIN tb_sprint ON tb_sprint.id=tb_project_version.sprint_id
JOIN tb_project ON tb_project.id=tb_project_version.project_id
 '''
#数据表Model设计
 
class Sprint(models.Model):
    id = models.AutoField(primary_key=True, verbose_name='自增id')
    name = models.CharField(max_length=50, verbose_name='迭代名称')
    ...略   
 
    class Meta:
        db_table = 'tb_sprint'
        verbose_name = '产品迭代表'
        verbose_name_plural = verbose_name
 
class Project(models.Model):
    id = models.AutoField(primary_key=True, verbose_name='自增id')
    name = models.CharField(max_length=50, verbose_name='项目名称')
    ...略
 
    class Meta:
        db_table = 'tb_project'
        verbose_name = '项目表'
        verbose_name_plural = verbose_name
 
 
class ProjectVersion(models.Model):
    id = models.AutoField(primary_key=True, verbose_name='自增id')
    name = models.CharField(max_length=50, verbose_name='版本名称')
    project_id = models.IntegerField(verbose_name='关联的项目ID')
    sprint_id = models.IntegerField(verbose_name='关联的迭代ID')
    ...略
 
    class Meta:
        db_table = 'tb_project_version'
        verbose_name = '项目版本表'
        verbose_name_plural = verbose_name

class ProjectVersionListAPIView(APIView):
    '''
    项目视图-版本管理
    '''
    # 查询列表数据
    def get(self, request, format=None):
        result = {}
        try:
            params =  request.GET
            page_size = int(params.get('pageSize'))
            page_no = int(params.get('pageNo'))
            name = params.get('name')
            project_id = params.get('projectId')
            sort = params.get('sort')
            if sort:
                sort_list = sort.split(',')
            else:
                sort_list = ['-id']
 
            startIndex = (page_no - 1) * page_size
            endIndex = startIndex + page_size
            filters = {'is_delete':0}
            if name:
                filters['name__startswith'] = name
            if project_id:
                filters['project_id'] = project_id



            projectVersions =  Project.objects.filter(**filters).extra(
            select={'project:'tb_project.name',
            'sprint':' tb_sprint.name',
            tables=['tb_project', 'tb_sprint'],
            where=['tb_project.id=tb_project_version.project_id', 'tb_sprint.id =tb_project_version.sprint_id']),
            rows = projectVersions.order_by(*sort_list)[startIndex:endIndex]
            rows = ProjectVersionSerializer(rows, many=True).data
            total = projectVersions.count() 
 
            projectVersions.order_by(*sort_list)[startIndex:endIndex]
            rows = ProjectVersionSerializer(rows, many=True).data
            total = projectVersions.count()
 
            result['msg'] =  '获取成功'
            result['success'] =  True
            result['data'] = {}
            result['data']['rows'] = rows
            result['data']['total'] = total
            return Response(result, status.HTTP_200_OK)
        except Exception as e:
            result['msg'] =  '%s' % e
            result['success'] =  False
            return Response(result, status.HTTP_500_INTERNAL_SERVER_ERROR)

        b,raw  :返回模型对象

        c,django connection  返回 【精选】django使用原生SQL查询数据库_django 原生sql-CSDN博客

# 工具类
def dictfetchall(cursor):
    "Return all rows from a cursor as a dict"
    columns = [col[0] for col in cursor.description]
    return [
        dict(zip(columns, row))
        for row in cursor.fetchall()
    ]


sql = "select * from student "
from django.db import connection
from common.utils import dictfetchall
cursor = connection.cursor()
cursor.execute(sql)
results = dictfetchall(cursor) # 列表套字典

更新

 @action(methods=['post'], detail=False, permission_classes=[IsPermittedOperator])
    def get_rec_total(self, request):
        keyword = request.data.get('keyword')
        in_start_at = request.data.get('in_start_at')
        in_end_at = request.data.get('in_end_at')
        out_start_at = request.data.get('out_start_at')
        out_end_at = request.data.get('out_end_at')
        pay_start_at = request.data.get('pay_start_at')
        pay_end_at = request.data.get('pay_end_at')
        color = request.data.get('color')
        pay_type = request.data.get('pay_type')
        operator_id = request.data.get('operator_id')
        from lt_finance.models import AmountOrder
        queryset = AmountOrder.objects.all()
        if keyword:
            queryset = queryset.filter(
                Q(vehicle_no__contains=keyword) | Q(out_trade_no__contains=keyword) | Q(parking_info__contains=keyword))
        if in_start_at:
            queryset = queryset.filter(start_at__gte=in_start_at)
        if out_start_at:
            queryset = queryset.filter(start_at__lte=out_start_at)
        if in_end_at:
            queryset = queryset.filter(end_at__gte=in_end_at)
        if out_end_at:
            queryset = queryset.filter(end_at__lte=out_end_at)
        if pay_start_at:
            queryset = queryset.filter(pay_at__gte=pay_start_at)
        if pay_end_at:
            queryset = queryset.filter(pay_at__lte=pay_end_at)
        if color:
            queryset = queryset.filter(color=int(color))
        if pay_type:
            queryset = queryset.filter(pay_type=int(pay_type))
        if operator_id:
            queryset = queryset.filter(operator_id=int(operator_id))
        if not request.user.is_superuser:
            queryset = queryset.filter(operator_id=request.user.account.operator_id)
        amount = queryset.aggregate(sum=Sum('amount'))['sum'] or 0
        return Response(data=amount)

九,更新

        1 单条更新

        #获取要更新的对象

        obj = MyModel.objects.get(id=1)

        # 更新数据

        obj.field1 = 'new value'

        obj.field2 = 'another value'

        obj.save()

        2 单条更新

 批量更新数据

MyModel.objects.filter(name='John').update(status='active')

        3 使用原始SQL更新数据

Django的ORM框架提供了`raw()`方法来执行原始SQL语句。例如:

from django.db import connection

# 执行原始SQL更新数据

with connection.cursor() as cursor:

cursor.execute("UPDATE myapp_mymodel SET field1='new value' WHERE id=1")

```

这段代码使用`connection.cursor()`方法获取数据库连接的游标对象,然后执行原始SQL语句来更新`MyModel`模型类中`id`为1的对象的`field1`字段。

        4. 使用表单更新数据

在Django中,我们还可以使用表单来更新数据库中的数据。表单可以提供一个用户友好的界面来输入数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值