DRF框架学习笔记

前言

工作中需要用的一些情况记录。方便学习。

Model

class Scripts(models.Model):
    """
    脚本
    """
    IS_SYSTEM = [(0, u'自定义'), (1, u'系统内置')]
    IS_DELETE = [(0, u'未删除'), (1, u'已删除')]

    is_system = models.SmallIntegerField(verbose_name=u"是否系统内置", choices=IS_SYSTEM, default=0)
    os_type = models.CharField(verbose_name=u"系统类型唯一标识", max_length=50)
    script_type = models.CharField(verbose_name=u"脚本类型", max_length=50)
    script_content = models.TextField(verbose_name=u"脚本内容")
    is_delete = models.BooleanField(verbose_name=u"是否删除", choices=IS_DELETE, default=False)

    class Meta:
        db_table = "scripts"
        verbose_name = u"脚本"


class Indexes(models.Model):
    """
    自定义指标项
    """
    IS_CHANGEABLE = [(0, u'不可修改'), (1, u'可修改')]
    IS_DELETE = [(0, u'未删除'), (1, u'已删除')]

    name = models.CharField(verbose_name=u"指标项名称", max_length=20)
    key = models.CharField(verbose_name=u"巡检项字段", max_length=50)
    detection_type = models.CharField(verbose_name=u"检测类型唯一标识", max_length=50)
    algorithm_method = models.CharField(verbose_name=u"对比方式", max_length=50, null=True)
    algorithm_value = models.CharField(verbose_name=u"对比值", max_length=200, null=True)
    scripts = models.ForeignKey(Scripts, verbose_name=u"脚本id", null=True)
    is_delete = models.BooleanField(verbose_name=u"是否删除", choices=IS_DELETE, default=False)
    create_user = models.CharField(verbose_name=u"创建人", max_length=50, null=True)
    create_time = models.DateTimeField(verbose_name=u"创建时间", default=datetime.datetime.now)
    remark = models.TextField(verbose_name=u"备注", null=True, blank=True)

    class Meta:
        db_table = "indexes"
        verbose_name = u"指标项"

Router

from rest_framework import routers
from apps.indexes import views

router = routers.DefaultRouter(trailing_slash=True)
router.register(r'indexes', views.IndexesModelViewSet, base_name='indexes')
router.register(r'scripts', views.ScriptsViewSet, base_name='scripts')
urlpatterns = router.urls

trailing_slash=True代表url末尾加上’/’,SimpleRouter默认是True。
DefaultRouter比SimpleRouter多一个root api,可以看到类视图集
base_name路由名称前缀。viewset里面queryset不存在,必须写base_name。

在这里插入图片描述

ViewSet

class ScriptsViewSet(component_viewsets.ModelViewSet):
    serializer_class = ScriptSerializer
    queryset = Scripts.objects.all()
class IndexesModelViewSet(component_viewsets.ModelViewSet):
    serializer_class = IndexesModelSerializer
    queryset = Indexes.objects.filter(is_delete=0)

Serializer

默认的Serializer需要把model对应的字段全部罗列出来

class IndexesSerializer(serializers.Serializer):
    name = serializers.CharField(label=u"指标项名称", required=True)
    key = serializers.CharField(label=u"巡检项字段", required=False)
    ...等等

HyperlinkedModelSerializer 会返回url字段,url字段当做主键,而不是id。

在这里插入图片描述

ModelSerializer使用简单方便快捷,字段与模型类字段对应

class ScriptSerializer(serializers.ModelSerializer):
    class Meta:
        model = Scripts
        exclude = ('is_delete',)
class IndexesModelSerializer(serializers.ModelSerializer):

    scripts = ScriptSerializer(required=False)
    class Meta:
        model = Indexes
        # fields = ['name', 'key']
        # 显示所有字段
        # fields = '__all__'
        # 除了某个字段,其他都显示
        exclude = ('is_delete',)
        # 查到下一级 ,2代表两级
        depth = 1

        # 指明只读字段
        read_only_fields = ('id', )
        
        validators = [UniqueTogetherValidator(queryset=Indexes.objects.all(),
                                              fields=('name','key'),
                                              message='name和key已经同时存在')]


    def create(self, validated_data):
    	# 重写创建
        with transaction.atomic():
            script_data = validated_data.pop('scripts')
            script = Scripts.objects.create(**script_data)
            index = Indexes.objects.create(scripts=script, **validated_data)
            return index

    def destroy(self, instance):
    	# 重写删除
        instance.is_delete = 1
        instance.save()

    def update(self, instance, validated_data):
    	# 重写更新
        with transaction.atomic():
            # raise_errors_on_nested_writes('update', self, validated_data)
            info = model_meta.get_field_info(instance)
            # 更新脚本
            script_data = validated_data.pop('scripts')
            Scripts.objects.update(**script_data)
            #
            for attr, value in validated_data.items():
                if attr in info.relations and info.relations[attr].to_many:
                    set_many(instance, attr, value)
                else:
                    setattr(instance, attr, value)
            instance.save()
            return instance

    # 添加一个新的字段
    def to_representation(self, instance):
        data = super(IndexesModelSerializer, self).to_representation(instance)
        data['test']='test'
        return data

Validate

1、对于单个字段判断是否已存在,序列化器里面加上

 name = serializers.CharField(
     validators=[UniqueValidator(queryset=Indexes.objects.all(), message=u'name已存在')])

2、对于多个字段判断是否唯一的校验

 class Meta:
     model = Indexes
     exclude = ('is_delete',)
     # 对于多个字段判断是否唯一的校验
     validators = [UniqueTogetherValidator(queryset=Indexes.objects.all(),
                                           fields=('name','key'),
                                           message='name和key已经同时存在')]

3、对于单个字段的校验

def validate_name(self, value):
    import re
    pattern = re.compile('[0-9]+')
    result = pattern.findall(value)
    if not result:
        raise serializers.ValidationError(u"name必须包含数字")
    return value

4、对于请求数据整体的校验

 def validate(self, data):
     if data['name']==data['group_key']:
         raise serializers.ValidationError(u"name和key不能一样")
     return data

Permission

针对视图集所有操作的权限

class IndexesModelViewSet(component_viewsets.ModelViewSet):
    serializer_class = IndexesModelSerializer
    queryset = Indexes.objects.filter(is_delete=0)
    permission_classes = (IsAdmin,  )

针对单个操作的权限

   @list_route(methods=["DELETE"], permission_classes=(DeletePermission, ))
    def test(self, request):
        return Response({"test":u"测试"})
class IsAdmin(permissions.BasePermission):
    message = u"对不起,您没有该操作的权限,请联系管理员。"

    def has_permission(self, request, view):

        if request.user.is_superuser:
            return True

        return False


class DeletePermission(permissions.BasePermission):
    """
    删除权限
    """
    message = u"您没有删除权限"

    def has_permission(self, request, view):
        # 对GET方法豁免,存在接口信息越权的问题!
        if request.method in permissions.SAFE_METHODS:
            return True

        if view.action == 'destroy':
            # 逻辑处理

            return Indexes.objects.filter(id=request.data.get('id')).exists()
        return True

has_permission是针对所有对象的权限控制。
has_object_permission针对某一个对象的权限控制。

其他

查询列表功能。不重写list。
需要安装pip install django_filters

from django_filters import rest_framework
class IndexesModelViewSet(component_viewsets.ModelViewSet):
    serializer_class = IndexesModelSerializer
    queryset = Indexes.objects.filter(is_delete=0)
    permission_classes = (IsAdmin, DeletePermission)
    filter_backends = (rest_framework.DjangoFilterBackend, )
    filter_fields = ("name", )

ok。
自定义分页,统一返回数据格式等可以在上一篇restframework博客中学习到。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DRF(Django Rest Framework)框架可以让你自定义错误处理。你可以定义一个自定义异常类来处理特定的错误,并在视图中抛出该异常。然后,在配置的异常处理器中对该异常进行处理。你也可以重写DRF的默认异常处理器来处理所有错误。 ### 回答2: 在DRF框架中,我们可以通过自定义错误处理来提供更加友好和详细的错误提示信息。自定义错误处理可以帮助我们在API开发过程中能够迅速定位和解决问题,提高开发效率。 首先,我们可以通过重写DRF中的异常处理器来自定义错误响应。通过继承`exception_handler`方法,我们可以在该方法中检查不同的异常类型,并返回相应的错误响应。可以处理的异常类型包括`APIException`、`PermissionDenied`、`AuthenticationFailed`等。 在自定义错误响应中,我们可以设置不同的错误码、错误信息和HTTP状态码,以确保错误响应符合我们的需求。例如,我们可以根据不同的异常返回不同的错误码以及对应的错误信息,可以参考HTTP状态码的规范来制定自己的错误码。 除了自定义错误响应外,我们还可以对DRF中的验证器进行自定义。通过继承DRF中的验证器类,我们可以自定义各种验证规则,以满足不同的业务需求。在自定义验证器中,我们可以通过重写验证方法来实现特定的验证逻辑。 另外,我们还可以自定义错误处理的日志记录。通过重写`handle_exception`方法,我们可以在捕获异常时,将异常的相关信息记录到日志中,便于后续排查问题。在日志记录中,我们可以输出异常的类型、错误信息、请求参数等,以便于定位问题所在。 总之,通过DRF框架的自定义错误处理功能,我们可以灵活地定制错误响应、验证规则和日志记录等,提高API开发的可维护性和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值