restfulframework引用多对多外键
记录一下工作中遇到的问题
最近在写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
restfulframework引用多对多外键的更多相关文章
- Python sqlalchemy orm 多对多外键关联
多对多外键关联 注:使用三张表进行对应关联 实现代码: # 创建3个表 配置外键关联 # 调用Column创建字段 加类型 from sqlalchemy import Table, Column, ...
- Django框架表关系外键-多对多外键(增删改查)-正反向的概率-多表查询(子查询与联表查询)
目录 一:表关系外键 1.提前创建表关系 2.目前只剩 书籍表和 书籍作者表没创建信息. 3.增 4.删 5.修改 二:多对多外键增删改查 1.给书籍绑定作者 2.删 3.修改 4.清空 三:正反向的 ...
- 测试脚本配置、ORM必知必会13条、双下划线查询、一对多外键关系、多对多外键关系、多表查询
测试脚本配置 ''' 当你只是想测试django中的某一个文件内容 那么你可以不用书写前后端交互的形式而是直接写一个测试脚本即可 脚本代码无论是写在应用下的test.py还是单独开设py文件都可以 ' ...
- postgreSQL外键引用查询 查询外键被那些表占用
根据一个表名,查询所有外键引用它的表,以及那些外键的列名key_column_usage(系统列信息表),pg_constraint(系统所有约束表) SELECT x.table_name, x.c ...
- Python SQLAlchemy多对多外键关联时表结构
# 创建多对多表结构 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.engine import cre ...
- Constraint6:更新外键约束(Foreign Key Constraint)的引用列
在SQL Server中,表之间存在引用关系,引用关系通过创建外键约束(Foreign Key Constraint)实现.如果一个Table中的column被其他Table引用,那么该表是参考表,或 ...
- SQLSERVER清空(Truncate)被外键引用的数据表
前言:我们知道SQLSERVER清空数据表有两种方式Delete和Truncate,当然两者的不同大家也都知道(不清楚的可以MSDN).不过这个错误“Cannot truncate table be ...
- 第二百八十节,MySQL数据库-外键链表之一对多,多对多
MySQL数据库-外键链表之一对多,多对多 外键链表之一对多 外键链表:就是a表通过外键连接b表的主键,建立链表关系,需要注意的是a表外键字段类型,必须与要关联的b表的主键字段类型一致,否则无法创建索 ...
- MySQL数据库之-foreign key 外键(一对多、多对多、一对一)、修改表、复制表
摘要: 外键 一对多 外键 多对多 外键 一对一 --------------------------------------------------------------------------- ...
随机推荐
- C#-DllImport 路径问题
原文:C# DllImport 相对路径无法找到dll DllImport DLL查找顺序:1.应用程序所在目录2.Windows目录和Windows\System32目录3.环境变量目录 只需要你把 ...
- MySQL语句和命令大全
前言 这里记录的是这两年学习工作过程中遇到的常用的 MySQL 语句和命令,部分是网上收集来的,出处已经不记得了,这里先谢过这些大佬.本文包括常见 SQL 语句,还有部分运维语句和命令,没有做详细的说 ...
- redis创建集群至少需要几个节点?至少需要几个master节点?
描述: 这也算个思考吧,通过redis-trib.rb可创建redis集群,然后通过--replicas后面接的数字,表示1个主节点对应几个从节点,那么我就做了如下的测试,想要达到的效果就是有6个节点 ...
- Flutter的Padding、Raw、Column、Expanded组件的基本使用
Padding组件: Padding组件的基本使用代码: import 'package:flutter/material.dart'; import 'package:flutter_testdem ...
- 关于Spring Cloud的思考和总结
博主开发使用了Spring Cloud,使用过程中的一些学习和经验,体会通过本博文进行记录. 以前的架构,单体应用: 加入ESB,通过总线进行调用: 微服务架构: 区别: SOA架构主要针对企业级,采 ...
- ios评分功能实现
/** * 只能评分,不能编写评论 * 有次数限制,一年只能使用三次 * 使用次数超限后,需要跳转appstore */ - (IBAction)systemComentBtnAction:( ...
- Spark实战系列目录
1 Spark rdd -- action函数详解与实战 2 Spark rdd -- transformations函数详解与实战(上) 3 Spark rdd -- transformations ...
- Apache限制IP并发数和流量控制
使用mod_limitipconn模块限制IP并发连接数安装: wget http://dominia.org/djao/limit/mod_limitipconn-0.24.tar.bz2 tar ...
- python 解决 idea 或者 pucharm 编译器在引入自定义的 py 文件的类时,没有提示的问题
1,问题描述: 假设我们有两个问价 a.py 和 b.py 其中分别有 A 类 和 B 类,现在我们想在 b.py 中引用 A 类 语法为 from a import A 虽然这是正确的语法,但是 ...
- 查看Oracle表空间以及用户与其默认表空间情况
Oracle中一个表空间可能是多个用户的默认表空间,下面语句统计了用户及其默认表空间情况,如果用户多个,用户之间通过逗号分隔. select t.default_tablespace, to_char ...