django学习记录2)

Model篇

使用django可快速定义数据结构,博客中使用的数据库是mysql,首先上个例子:


from django.contrib.auth import get_user_model
from django.db import models
from django_mysql.models import Model

class Check(Model):
    STATUS_TYPE = (
        (0, '未审核'),
        (1, '驳回'),
        (2, '通过')
    )

    check_content = models.JSONField() 
    remark = models.TextField(null=True, blank=True)
    file = models.JSONField(null=True, default=[])  # 多个附件信息地址 {"file":[]}
    status = models.IntegerField(choices=STATUS_TYPE, default=0)
    uid = models.ForeignKey(get_user_model(), models.CASCADE, to_field='username', null=True, blank=True,db_column='uid')  # 审核人
    reject_reason = models.CharField(max_length=16, null=True, blank=True)  # 驳回项
    time = models.DateTimeField(auto_now=True)  # 时间 审核资料最后更新的时间

字段解释:

定义了一张名为Check的表,在mysql中的表名就是APP_check,假设我的APP是api,那么数据库的表名就是api_check

check表共有 check_content,remark,file,status,uid,reject_reason,time这些属性,这里列举了我常用的字段类型:

check_content :json类型,需要mysql(5.7以上支持)

remark:长文本类型,属性是可以为空,

file:json类型,默认值是空数组[]

status:整型,可选的值从STATUS_TYPE中进行选择,默认值是0,

uid:外键类型,与表get_user_model(就是django中默认生成的auth_user表)中的username进行关联(外键关联项必须是unique),在check表中的字段名字是uid,如果不这样指定会默认生成外键表_uid这样的名字

reject_reason:char类型,长度是16,

time:datetime类型,属性auto_now是每次更新都会自动修改为当前时间,如果只希望这个时间在创建的时候更新,其余操作不变,那么设为属性auto_now_add=True

其他字段类型参考:

Django 模型(Model)字段类型级参数详解_一念永恒-CSDN博客

 

定义后执行

1. python manage.py  makemigrations  记录我们对models.py的所有改动,并且将这个改动迁移到migrations这个文件下生成一个文件例如:0001_initial.py

2. python manage.py migrate  把这些改动作用到数据库也就是执行migrations里面新改动的迁移文件更新数据库,比如创建数据表,或者增加字段属性(注:必须手动去mysql中创建数据库,才能建表,django没有新建数据库的能力)

2. python manage.py sqlmigrate APPNAME 0001_initial  生成对应的sql语句,可以手动去mysql中执行

 

以上操作可以在MySQL中操作表,但是无法直接使用这些字段与前端进行操作,此时需要用到serializers

 

serializers篇

serializers的作用是序列化数据结构,可以通过serializers把表的数据结构序列化成json,在前后端之间进行交互,还可以进行数据校验等功能,举一个例子:

from api.models  import  Check 
from rest_framework import serializers

class CheckSerializer(serializers.ModelSerializer):
    telephone = serializers.SerializerMethodField()

    class Meta:
        model = Check
        fields = '__all__'
    
    def get_telephone(self, obj):
        return obj.uid.telephone

z这里定义了Check表的序列化组件

fields = '__all__'意味着返回所有数据,也可以定义返回部分数据,比如:

fields = (check_content,remark)

如果还想在json中多加些字段(不是本表的字段)一起返回,可以在类中进行定义,比如这里还想返回用户的电话号码,同时定义get_telephone,在函数内返回obj当前Check对象的uid外键的telephone属性。

 

现在我们定义好数据表了,也可以将数据进行序列化,就要开始写接口了,前端需要对这些数据进行增删该查,涉及到views模块

 

views篇

django提供两种接口定义的类可以继承,通用视图APIView和视图集ViewSet,

django自己本身就继承了很多子类供使用:

  1. GenericAPIView是继承自APIView,GenericAPIView肯定在APIView的基础上 封装了一些属性和方法:增加了对于列表视图和详情视图可能用到的通用方法和属性的支持

           属性:queryset 设置结果集、serializer_class 设置序列化器、lookup_field 查询指定的对象

 方法:get_queryset(self) 返回视图使用的查询集、get_serializer(self,_args, *_kwargs) 返回序列化器对象、get_object(self) 返回详情视图所需的模型类数据对象

  1. CreateAPIView:提供post方法处理程序。

    ListAPIView:用于只读端点以表示模型实例的集合。提供get方法处理程序。

    RetrieveAPIView:用于表示单个模型实例的只读端点。提供get方法处理程序。

    DestroyAPIView:用于单个模型实例的仅删除端点。提供delete方法处理程序。

    UpdateAPIView:用于单个模型实例的仅更新端点。提供put和patch方法处理程序。

    ListCreateAPIView:用于读写端点以表示模型实例的集合。提供get和post方法处理程序。

    RetrieveUpdateAPIView:用于读取或更新端点以表示单个模型实例。提供get,put并且patch方法处理。

    RetrieveDestroyAPIView:用于读取或删除端点以表示单个模型实例。提供get和delete方法处理程序。

    RetrieveUpdateDestroyAPIView:用于读写 - 删除端点以表示单个模型实例。提供get,put,patch和delete方法处理。
    以上转自:https://blog.csdn.net/qq_31742423/article/details/83241461

APIView

在APIView中,可以定义get post delete等方法,上例子:这里是资料附件的上传下载和删除接口

支持定义的属性:
authentication_classes列表或元祖,身份认证类
permissoin_classes列表或元祖,权限检查类

# 提测资料审核附件 的上传和下载
class CheckAttachmentAPIView(APIView):
    permission_classes = (IsAuthenticated,)
    authentication_classes = (BasicAuthentication,
                              JWTAuthentication,
                              TokenAuthentication,
                              SessionAuthentication,
                              )

    def post(self, request, format=None):
        files = request.FILES
        file = files.get('file')
        if file is None:
            raise exceptions.NotAcceptable('upload fail, file param not found')
        c_id = request.data.get('id', None)
        if c_id is None:
            raise exceptions.NotAcceptable('upload fail, check id param not found')
        else:
            try:
                check = SubmitCheck.objects.get(id=c_id)
            except:
                raise exceptions.NotAcceptable('check is not exist')
        file_absolute_path = './checkfile/'
        try:
            os.mkdir(file_absolute_path)
        except:
            pass
        finally:
            try:
                os.mkdir(file_absolute_path + str(check.id))
            except:
                pass
        file_name = file_absolute_path + str(check.id) + '/' + file.name
        file_handler = open(file_name, 'wb')
        try:
            for chunk in file.chunks():  # 分块写入文件
                file_handler.write(chunk)
        finally:
            file_handler.close()
        check_file = check.file  # json :[]
        check_file.append(file.name)
        SubmitCheck.objects.filter(id=c_id).update(file=check_file)
        return JSONResponse(data=file.name)

    def get(self, request, format=None):
        file_name = request.query_params.get('file')
        c_id = request.query_params.get('id')
        if c_id is None:
            raise exceptions.NotAcceptable('download fail, check id param not found')
        else:
            try:
                check = SubmitCheck.objects.get(id=c_id)
            except:
                raise exceptions.NotAcceptable('check is not exist')
        file_absolute_path = './checkfile/'
        file_path = file_absolute_path + str(check.id) + '/' + file_name
        file_handler = open(file_path, 'rb')
        response = FileResponse(file_handler)
        response['Content-Type'] = 'application/octet-stream'
        response["Access-Control-Expose-Headers"] = 'Content-Disposition'
        response['Content-Disposition'] = 'attachment;filename="{}"'.format(file_name)
        return response

    def delete(self, request, format=None):
        file_name = request.data.get('file', None)
        c_id = request.data.get('id', None)
        if c_id is None or file_name is None:
            raise exceptions.NotAcceptable('delete fail, file or id param not found')
        else:
            try:
                check = SubmitCheck.objects.get(id=c_id)
            except:
                raise exceptions.NotAcceptable('check is not exist')
        file_absolute_path = './checkfile/'
        file_path = file_absolute_path + str(check.id) + '/' + file_name
        os.remove(file_path)
        check_file = check.file  # json :[]
        check_file.remove(file_name)
        SubmitCheck.objects.filter(id=c_id).update(file=check_file)
        return JSONResponse()

视图集Viewset

Viewset继承(ModelViewSet,其本身定义好增post删delete改patch查get接口,我们只需要指定字段,也可重写方法,自己定义返回的数据结构,上例子:

class CheckViewSet(ModelViewSet):
    serializer_class = CheckSerializer
    pagination_class = JSONPagination
    filter_fields = ('id',)
    queryset = Check.objects.all().order_by('-time')
    permission_classes = (IsAuthenticated,)
    authentication_classes = (BasicAuthentication,
                              JWTAuthentication,
                              TokenAuthentication,
                              SessionAuthentication,
                              )

    def update(self, request, *args, **kwargs):
        data = request.data
        status = data.get('status', None)
        data.pop('uid')
        request._full_data = data
        return super().update(request, *args, **kwargs)

    def create(self, request, *args, **kwargs):  # 创建
        data = request.data
        data['user'] = request.user
        data['status'] = 0
        request._full_data = data
        return super().create(request, *args, **kwargs)

    def get_queryset(self):
        user = self.request.user
        wait_for_me = self.request.query_params.get('wait_for_me', 'False')
        if user.is_staff or user.is_superuser:
            res = Check.objects.all().filter(user=user).order_by('-time')
            return res
 

 

在APIView  和ViewSet中,都需要定义serializer_class = CheckSerializer,来知名用的那个序列化组件。

定义好view之后,需要在urls.py中定义路由:

router.register(r'check', CheckViewSet, 'check')
urlpatterns = [
    url(r'^submit-check/attachment$', SubmitCheckAttachmentAPIView.as_view())
]

通过上述操作,可以完成数据库的定义、表的创建,通过接口对数据进行简单的增删改查,在下一篇接着介绍,复杂的数据库操作,django还是有点东西

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值