Python中如何实现一款no-sql风格的Rest API查询框架,支持Django ORM和peewee

RestfulAPI 解析

实现一款 no-sql 风格的参数解析框架rest-query,(like: /?select=id,name,author{id,name,school{*}})&id=gte.20&author.name=wwxiong&order=id.desc)。

目前实现了Django ORMPeewee ORM

Django DEMO

定义模型

class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50)
    age = models.IntegerField()

class Book(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=50) author = models.ForeignKey(Author)

定义试图

from django.views.generic import ListView
from django.views.generic.detail import DetailView
from django_rest_query import RestQueryDetailViewMixin, RestQueryListViewMixin
from .models import Author, Book

class BookDetail(RestQueryDetailViewMixin, DetailView): model = Book

class BookList(RestQueryListViewMixin, ListView): model = Book

class AuthorDetail(RestQueryDetailViewMixin, DetailView): model = Author

class AuthorList(RestQueryListViewMixin, ListView): model = Author

这样我们就实现了AuthorBook的查询 API 了。

API

查询姓名为dracarysX的作者,并只返回id, name:

curl http://localhost/authors?select=id,name

查询书籍id大于 100,且作者姓名在['x', 'y', 'z']中,并返回书籍的id, name和作者的id, name,并按照书籍id倒序排序。

curl http://localhost/books?select=id,name,author{id,name}&id=gt.100&author.name=in.x,y,z&order=id.desc

返回数据:

{
    "count": 2,
    "object_list": [
        {
            "id": 2,
            "name": "Javascript",
            "author": {
                "name": "x",
                "id": 2
            }
        },
        {
            "id": 1,
            "name": "Python",
            "author": {
                "name": "y",
                "id": 1
            }
        }
    ],
    "is_paginated": false,
    "page": 1
}

有兴趣的可以直接查看项目中的 DEMO:https://github.com/dracarysX/django-rest-query/tree/master/demo

PS

目前仅仅实现了 Django orm 和 Peewee 的解析。感兴趣的同学可以多多提意见和 issue,谢谢。


Python中如何实现一款no-sql风格的Rest API查询框架,支持Django ORM和peewee

4 回复

感觉类似 Graph API ?


要实现一个支持Django ORM和Peewee的NoSQL风格REST API查询框架,核心是解析URL查询参数并将其转换为ORM的查询条件。下面是一个基于Django REST framework和Peewee的简单实现示例。

首先,安装必要的包:

pip install django djangorestframework peewee

1. Django ORM 实现

创建一个Django视图,解析查询参数:

# views.py
from django.db.models import Q
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import YourModel

class NoSQLStyleAPIView(APIView):
    def get(self, request):
        query_params = request.query_params
        queryset = YourModel.objects.all()
        
        # 解析查询参数,例如:?name=John&age__gt=25
        for key, value in query_params.items():
            if '__' in key:
                # 处理带操作符的查询,如 age__gt
                field, op = key.split('__', 1)
                lookup = f'{field}__{op}'
                queryset = queryset.filter(**{lookup: value})
            else:
                # 精确匹配
                queryset = queryset.filter(**{key: value})
        
        # 支持OR查询,例如:?q=name:John,age:25
        q_param = query_params.get('q', '')
        if q_param:
            q_objects = Q()
            for pair in q_param.split(','):
                if ':' in pair:
                    field, val = pair.split(':', 1)
                    q_objects |= Q(**{field: val})
            queryset = queryset.filter(q_objects)
        
        # 序列化并返回结果
        from .serializers import YourModelSerializer
        serializer = YourModelSerializer(queryset, many=True)
        return Response(serializer.data)

2. Peewee 实现

对于Peewee,实现类似逻辑:

# peewee_view.py
from peewee import Model, CharField, IntegerField
from playhouse.shortcuts import model_to_dict
import json

# 定义Peewee模型
db = SqliteDatabase('my_database.db')
class YourPeeweeModel(Model):
    name = CharField()
    age = IntegerField()
    
    class Meta:
        database = db

def no_sql_style_api(request):
    query_params = request.GET
    query = YourPeeweeModel.select()
    
    # 解析查询参数
    for key, value in query_params.items():
        if '__' in key:
            field, op = key.split('__', 1)
            # 将操作符映射到Peewee的查询方法
            if op == 'gt':
                query = query.where(getattr(YourPeeweeModel, field) > value)
            elif op == 'lt':
                query = query.where(getattr(YourPeeweeModel, field) < value)
            else:
                # 其他操作符处理
                pass
        else:
            query = query.where(getattr(YourPeeweeModel, key) == value)
    
    # 支持OR查询
    q_param = query_params.get('q', '')
    if q_param:
        from peewee import fn
        conditions = []
        for pair in q_param.split(','):
            if ':' in pair:
                field, val = pair.split(':', 1)
                conditions.append((getattr(YourPeeweeModel, field) == val))
        if conditions:
            query = query.where(fn.OR(*conditions))
    
    # 转换为字典并返回JSON
    results = [model_to_dict(obj) for obj in query]
    return json.dumps(results)

总结建议 这个框架的核心是灵活解析查询参数并映射到ORM的查询方法,根据需求扩展操作符和逻辑即可。

楼主看过 postgrest 这个项目吗

嗯,就是看了这个项目才开始做的。

回到顶部