能否将Django ORM用于外部API返回的JSON对象?
问题描述
我有两个从外部API获取的JSON对象,希望对其执行count、filter、all等ORM操作。
获取comments数据的代码(views.py中)
comments_response = requests.get('https://jsonplaceholder.typicode.com/comments') comments_data = json.loads(comments_response.text)
comments_data输出示例
[ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" }, { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" } ]
获取posts数据的代码(views.py中)
posts_response = requests.get( 'https://jsonplaceholder.typicode.com/posts') posts_data = json.loads(posts_response.text)
posts_data输出示例
[ { "postId": 1, "id": 1, "name": "id labore ex et quam laborum", "email": "Eliseo@gardner.biz", "body": "laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium" }, { "postId": 1, "id": 2, "name": "quo vero reiciendis velit similique earum", "email": "Jayne_Kuhic@sydney.com", "body": "est natus enim nihil est dolore omnis voluptatem numquam\net omnis occaecati quod ullam at\nvoluptatem error expedita pariatur\nnihil sint nostrum voluptatem reiciendis et" } ]
请问:
- 能否对这类JSON对象使用Django ORM,例如执行
comments_data.objects.count('title')或comments_posts.objects.all()这类操作? - DRF的Serializer能否协助完成这类操作?
- 是否需要其他框架将JSON转换为可使用ORM的对象?
注:我已搜索相关问题,但大多讨论的是来自自有内部数据库的JSON数据,而我的数据来自外部API,并非自有数据库或可访问的数据库。
解答
1. 直接使用Django ORM不可行
Django ORM是为数据库Model实例设计的,它依赖数据库连接和表结构生成SQL查询。你当前的comments_data和posts_data只是Python原生的列表+字典结构,不属于Django Model实例,因此无法直接调用objects.count()、objects.all()这类ORM方法。
2. DRF Serializer可协助数据结构化,但不提供ORM操作
DRF Serializer的核心作用是数据序列化/反序列化,能把JSON转成规范的Python字典(或反过来),但本身不具备ORM式的查询能力。不过它可以帮你把杂乱的JSON数据转换成结构统一的对象,方便后续处理:
示例:用Serializer转换数据
先定义Serializer类:
from rest_framework import serializers class CommentSerializer(serializers.Serializer): userId = serializers.IntegerField() id = serializers.IntegerField() title = serializers.CharField() body = serializers.CharField() class PostSerializer(serializers.Serializer): postId = serializers.IntegerField() id = serializers.IntegerField() name = serializers.CharField() email = serializers.EmailField() body = serializers.CharField()
再将JSON数据转成结构化对象:
# 处理comments数据 comment_serializer = CommentSerializer(data=comments_data, many=True) if comment_serializer.is_valid(): comment_objects = comment_serializer.validated_data # 规范的字典列表 # 处理posts数据同理 post_serializer = PostSerializer(data=posts_data, many=True) if post_serializer.is_valid(): post_objects = post_serializer.validated_data
注意:转换后的comment_objects依然是字典列表,不是ORM模型实例,仍无法直接使用count()、filter()等方法,需要手动实现或借助工具库。
3. 可通过轻量工具库模拟ORM操作
如果想实现类似ORM的查询能力,有以下几种方案:
方案一:用Python原生语法手动实现
适合简单场景,无需额外依赖:
- count:统计总数或符合条件的数量
# 统计所有评论数量 total_comments = len(comment_objects) # 统计userId=1的评论数量 target_count = sum(1 for item in comment_objects if item['userId'] == 1) - filter:用列表推导式筛选数据
# 筛选标题包含"reprehenderit"的评论 filtered_comments = [item for item in comment_objects if 'reprehenderit' in item['title']]
方案二:用Pandas实现类ORM查询
Pandas的DataFrame提供了类似数据库的查询能力,适合数据量较大或需要复杂统计的场景:
import pandas as pd # 转成DataFrame comment_df = pd.DataFrame(comment_objects) # 统计总数 total = comment_df.shape[0] # 筛选userId=1的记录 filtered = comment_df[comment_df['userId'] == 1] # 统计标题包含特定字符串的数量 match_count = comment_df[comment_df['title'].str.contains('reprehenderit')].shape[0]
方案三:用SQLAlchemy内存数据库模拟完整ORM操作
把数据导入内存SQLite数据库,用SQLAlchemy的ORM语法操作,完全贴合Django ORM的使用习惯:
from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker # 创建内存数据库引擎 engine = create_engine('sqlite:///:memory:') Base = declarative_base() # 定义模型(和Django Model语法类似) class Comment(Base): __tablename__ = 'comments' id = Column(Integer, primary_key=True) userId = Column(Integer) title = Column(String) body = Column(String) # 创建表并导入数据 Base.metadata.create_all(engine) Session = sessionmaker(bind=engine) session = Session() for item in comment_objects: session.add(Comment(**item)) session.commit() # 执行ORM式操作 # 统计总数 total = session.query(Comment).count() # 筛选userId=1的记录 filtered_comments = session.query(Comment).filter(Comment.userId == 1).all() # 获取所有记录 all_comments = session.query(Comment).all()
内容的提问来源于stack exchange,提问作者user18489452
相关产品推荐
相关产品推荐

