day9

反向工程

# 正向工程 - 模型变表 - 项目规模较小没有专业的DBA
# python manage.py makemigration<应用名>
# 反向工程 - 表变模型 -项目规模较大公司由专业DBA
# python manage.py inspectdb > /models.py
# 由数据库迁移数据
from django.db import models

class District(models.Model):
    distid = models.IntegerField(primary_key=True)
    parent = models.ForeignKey(to='self',on_delete=models.PROTECT,db_column='pid',blank=True, null=True)
    name = models.CharField(max_length=255)
    ishot = models.BooleanField(default=False)
    intro = models.CharField(max_length=255,default='')

    class Meta:
        managed = False
        db_table = 'tb_district'

过滤数据

django-filter库包含一个DjangoFilterBackend

如果需要过滤数据(对数据接口设置筛选条件、排序条件等),可以使用django-filter三方库来实现。

pip install django-filter
INSTALLED_APPS = [
    
    'django_filters',

]
REST_FRAMEWORK = {
    # 默认的后端过滤器
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.OrderingFilter',
    ),
    
}
过滤器api/utils

    """自定义记录数据过滤器"""
class RecordFilterSet(django_filters.FilterSet):
    #过滤器
    # carno调用自定义方法
    carno = django_filters.CharFilter(method='filter_by_carno')
    # gte最小值 lte最大值
    min_date = django_filters.DateTimeFilter(field_name='makedate',lookup_expr='gte')
    max_date = django_filters.DateTimeFilter(field_name='makedate',lookup_expr='lte')

    @staticmethod
    def filter_by_carno(queryset,name,value):
    # 置换空格
        value = normalize(value)
        # 设置过滤条件car的carno、owner属性(模糊)/value为?carno=川A12345&owner=王 中的值
        return queryset.filter(Q(car__carno=value)|
                               Q(car__owner__contains=value))

    class Meta:
        model = Record
        # 根据这些项进行过滤
        fields = ('carno','min_date','max_date')
  视图函数
  # 设置缓存过期时间为1S,缓存调用默认缓存,在settings文件中修改,修改数据和查找的缓存
@method_decorator(decorator=cache_page(timeout=1, cache='default'),name='retrieve')
@method_decorator(decorator=cache_page(timeout=1, cache='default'),name='list')
class RecordViewSet(ModelViewSet):
    """违章记录视图集合"""
    # 内连接查询
    queryset = Record.objects.all().select_related('car')
    # 限流类
    throttle_classes = ()
    # 序列化器
    serializer_class = RecordSerializer
    # 后端过滤器
    filter_backends = (DjangoFilterBackend,OrderingFilter)
    # 排序方式
    ordering = ('-makedate')
    # 排序类调用自定义排序类
    filterset_class = RecordFilterSet

drf的第三种方法

fbv在视图里使用函数处理请求。

cbv在视图里使用类处理请求。

定义序列化器api/serializers

class DistrictSerializer(serializers.ModelSerializer):


    class Meta:
        model = District
        exclude = ('parent','ishot')


class DistrictDetailSerializer(serializers.ModelSerializer):
# 在这个模型中,没有这个字段使用SerializerMethodField,当用户获取这个数据,调用函数返回给用户
    cities =  serializers.SerializerMethodField()
    # 定义静态方法,回调函数
    # parent=district进行筛选
    # 返回data数据
    @staticmethod
    # 当传入district的时候回调方法get_cities
    def get_cities(district):
    # 取到parent=district的对象
        cities = District.objects.filter(parent=district)
        return DistrictSerializer(cities,many=True).data

    class Meta:
        model = District
        fields = ('distid','name','intro','cities')

使用装饰器,编写函数方法的视图函数

@api_view(['GET'])
@cache_page(timeout=None, cache='api')
def provinces(request):
# queryset获取查询对象
    queryset = District.objects.filter(parent__isnull=True)
    # 进行序列化 调用Serializer
    serializer = DistrictSerializer(queryset, many=True)
    # 返回数据,通过data属性可以获取序列化后的数据
    return Response(serializer.data)


@api_view(['GET'])
def get_districts(request,distid):
# distid = url传入的进行筛选
    district = District.objects.filter(distid=distid).first()
    serializer = DistrictDetailSerializer(district)
    return Response(serializer.data)
urlpatterns = [
    path('districts/', get_provinces),
    path('districts//', get_districts),
  ]   # 映射url districts/130000/

使用了Django自带的视图装饰器(@cache_page)来实现对API接口返回数据的缓存。可以使用多种装饰器 但需要在api_view下使用

函数方法中的分页器使用

获取url参数,127.0.0.1:8000/?page=

# 非法数值则返回1 数值为空也返回1 如 127.0.0.1:8000/?page=asdsa
page = int(request.GET.get('page','1'))
size = int(request.GET.get('size','5'))
print(size,page)
queryset = District.objects.filter(parent__isnull=True)
# 每5份内容分页一次
paginator = Paginator(queryset,size)
serializer = DistrictSerializer(paginator.page(page).object_list,many=True)
return Response(serializer.data)

使用APIView及其子类/使用ViewSet及其子类

让浏览器能够发起DELETE/PUT/PATCH

 

你可能感兴趣的:(day9)