记录一下工作中遇到的问题

最近在写restfulframework,感觉还是很便利的

首先贴一下文档地址

https://www.django-rest-framework.org/api-guide/filtering/

https://www.django-rest-framework.org/api-guide/serializers/

https://www.django-rest-framework.org/api-guide/relations/#manytomanyfields-with-a-through-model

使用GernricViewSet可以便捷的新增接口,在类中定义queryset指定模型,用serializer_class指定序列化类,用pagination_class指定分页类,再用filter_backends和filter_class做筛选,可以解决大部分curd问题,如下

class GitLabCommit(mixins.ListModelMixin, mixins.RetrieveModelMixin,viewsets.GenericViewSet):
#加RetriveModelMixin可以查询特定模型的信息
queryset = GitCommit.objects.all()
serializer_class = CommitSerializer
pagination_class = MyPageNumberPagination
filter_backends = (DjangoFilterBackend,)
filter_class = UserCommitFilter

其中模型类无需多言,序列化类形如下

class CommitSerializer(serializers.ModelSerializer):
author_email = serializers.CharField(source='author.email')
branch_name = serializers.CharField(source = "branch.branchName")
branch_project_name = serializers.CharField(source="branch.project.projectName") class Meta:
model = GitCommit
fields = "__all__"

fields这里也可以写成元组的形式

fields = ("StaffId","name","staff_name")

分页类类似这样

class MyCursorPagination(pagination.CursorPagination):
"""
Cursor 光标分页 性能高,安全
"""
page_size = 9
ordering = '-update_time'
page_size_query_param = "pages"
max_page_size = 20
cursor_query_description = '页面'
page_size_query_description = '每页条数' class MyPageNumberPagination(pagination.PageNumberPagination):
"""
普通分页,数据量越大性能越差
"""
page_size = 11
page_size_query_param = 'size'
page_query_param = 'page'
max_page_size = 20

这是过滤器类,可以直接定义查找字段或者通过方法进行复杂查找

class UserCommitFilter(filters.FilterSet):
user_id = filters.NumberFilter(field_name='author__StaffId', lookup_expr='exact')
start_date = filters.DateFilter(field_name='commitDate', lookup_expr='gte')
end_date = filters.DateFilter(field_name='commitDate', lookup_expr='lt')
commit_sum = filters.NumberFilter(method="get_sum") def get_sum(self,queryset,name,values):
if values == 1:
return queryset.annotate(total_addLines = Sum("addLines"),total_delLins = Sum("delLines"),total_totalLins = Sum("totalLines"))

这里有一个问题:如果序列化所涉及的模型是关联模型怎么办呢?

可以参考这个

https://zhuanlan.zhihu.com/p/27667372

这里特别说一下,对于多对多模型,可以通过嵌套来进行关联,如下

模型定义

class Staff(BaseTable):
StaffId = models.IntegerField(primary_key=True, help_text="工号")
email = models.CharField(max_length=50,default="",null=True,help_text="邮箱")
name = models.CharField(max_length=50,default="",null=True,help_text="姓名")
department = models.ForeignKey(Department,on_delete=models.CASCADE) def __str__(self):
return "%s:%s"%(self.StaffId,self.name)
class Meta:
db_table = "gitlab_measure_staff" class GitGroup(BaseTable):
id = models.AutoField(primary_key=True, help_text="ID")
name = models.CharField(max_length=100,default="",null=True,help_text="组名称")
members = models.ManyToManyField(Staff) class Meta:
db_table = "gitlab_measure_gitgroup"

序列化

class StaffSerializer(serializers.ModelSerializer):
staff_name = serializers.CharField(source="name")
class Meta:
model = Staff
fields = ("StaffId","name","staff_name") class GitGroupSerializer(serializers.ModelSerializer):
members = StaffSerializer(many=True,read_only=True)
class Meta:
model = GitGroup
fields = ("id","name","members")

如果此时又有一个project类中的group关联到gitgroup,希望在展示的时候展示出组中所有成员该怎么办呢?

这里可以使用depth指定查询的深度

class ProjectSerializer(serializers.ModelSerializer):
gitGroup_name = serializers.CharField(source='gitGroup.name')
gitGroup_id = serializers.CharField(source="gitGroup.id")
department_name = serializers.CharField(source="department.name") class Meta:
model = GitProject
fields = "__all__"
depth = 2

这样在结果中就能看到展示的组和成员了,因为在serilizers.ModelSerializer中的get_field()方法中会根据调用self.build_field,将depth传入,build_field方法会调用self.buid_nested_field方法来,再返回一个ModelSerializer类,再在外层函数中循环调用来获取层层对象,最多不超过10层

        for field_name in field_names:
# If the field is explicitly declared on the class then use that.
if field_name in declared_fields:
fields[field_name] = declared_fields[field_name]
continue extra_field_kwargs = extra_kwargs.get(field_name, {})
source = extra_field_kwargs.get('source', '*')
if source == '*':
source = field_name # Determine the serializer field class and keyword arguments.
field_class, field_kwargs = self.build_field(
source, info, model, depth
) # Include any kwargs defined in `Meta.extra_kwargs`
field_kwargs = self.include_extra_kwargs(
field_kwargs, extra_field_kwargs
) # Create the serializer field.
fields[field_name] = field_class(**field_kwargs)
    def build_field(self, field_name, info, model_class, nested_depth):
"""
Return a two tuple of (cls, kwargs) to build a serializer field with.
"""
if field_name in info.fields_and_pk:
model_field = info.fields_and_pk[field_name]
return self.build_standard_field(field_name, model_field) elif field_name in info.relations:
relation_info = info.relations[field_name]
if not nested_depth:
return self.build_relational_field(field_name, relation_info)
else:
return self.build_nested_field(field_name, relation_info, nested_depth) elif hasattr(model_class, field_name):
return self.build_property_field(field_name, model_class) elif field_name == self.url_field_name:
return self.build_url_field(field_name, model_class) return self.build_unknown_field(field_name, model_class)
    def build_nested_field(self, field_name, relation_info, nested_depth):
"""
Create nested fields for forward and reverse relationships.
"""
class NestedSerializer(ModelSerializer):
class Meta:
model = relation_info.related_model
depth = nested_depth - 1
fields = '__all__' field_class = NestedSerializer
field_kwargs = get_nested_relation_kwargs(relation_info) return field_class, field_kwargs

最新文章

  1. 复习练习(03)jquery Css方法一步步升级
  2. 进程外session
  3. C#基础知识点
  4. UVa 11235 (RMQ) Frequent values
  5. Codeforces 474C Captain Marmot 给定4个点和各自旋转中心 问旋转成正方形的次数
  6. c# 调用 友盟api
  7. 背包问题递归java
  8. BZOJ 3479: [Usaco2014 Mar]Watering the Fields(最小生成树)
  9. C++ 中 double、 long double、long 和 long long
  10. LeetCode 第五题 最长的回文字符串 (JAVA)
  11. Confluence 6 使用 Apache 和 mod_proxy 的基本配置
  12. online ddl与pt-osc详解
  13. js 判断浏览器型号
  14. 2.oracle之用户管理sql
  15. django 拷贝一个 model 实例
  16. Linux命令区
  17. const 关键字总结
  18. grunt源码解析:整体运行机制&grunt-cli源码解析
  19. OpenVPN选项topology subnet实现子网掩码24的子网地址扩展
  20. calcite介绍

热门文章

  1. 【C++】C++中的动态内存解析
  2. Kafka的安装与使用(转)
  3. Flume监控指标项
  4. swap 释放
  5. PHP打印日志类
  6. RabbitMQ的应用总结
  7. 【Gitlab】宝塔gitlab 修改管理员账号密码
  8. Html JavaScript网页制作与开发完全学习手册
  9. 【python基础】setproctitle的安装与使用
  10. Xamarin.Android UnauthorizedAccessException: Access to the path is denied