Python列表数据到Django ORM查询
比如说,我有一个列表数据,例如:Python列表数据到Django ORM查询,python,django,django-orm,Python,Django,Django Orm,比如说,我有一个列表数据,例如: data = [ {'id': 1, 'name': 'brad', 'color': 'red', 'tags': [], 'author': {'name': 'admin'}}, {'id': 2, 'name': 'sylvia', 'color': 'blue', 'tags': [], 'author': {'name': 'user'}}, {'id': 3, 'name': 'sylwia', 'color': 'gree
data = [
{'id': 1, 'name': 'brad', 'color': 'red', 'tags': [], 'author': {'name': 'admin'}},
{'id': 2, 'name': 'sylvia', 'color': 'blue', 'tags': [], 'author': {'name': 'user'}},
{'id': 3, 'name': 'sylwia', 'color': 'green', 'tags': [], 'author': {'name': 'admin'}},
{'id': 4, 'name': 'shane', 'color': 'red', 'tags': [], 'author': {'name': 'admin'}},
{'id': 5, 'name': 'shane', 'color': 'red', 'tags': ['python', 'django'], 'author': {'name': 'user'}}
]
我想让它成为现实,比如Django所做的:
ModelName.objects.filter(color__icontains="gree")
这就是我所做的
import operator
from collections import namedtuple
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
class DataQuerySet:
"""
Custom ORM for List dict data,
https://stackoverflow.com/a/58351973/6396981
"""
allowed_operations = {
'gt': operator.gt,
'lt': operator.lt,
'eq': operator.eq,
'icontains': operator.contains
}
def __init__(self, data):
self.data = data
def all(self):
return self.data
def filter(self, **kwargs):
"""
>>> kwargs = {'name': 'sylwia', 'id__gt': 1}
>>> DataQuerySet().filter(**kwargs)
[{'id': 3, 'name': 'sylwia', 'color': 'green'}]
"""
operation = namedtuple('Q', 'op key value')
def parse_filter(item):
"""item is expected to be a tuple with exactly two elements
>>> parse_filter(('id__gt', 2))
Q(op=<built-in function gt>, key='id', value=2)
>>> parse_filter(('id__ ', 2))
Q(op=<built-in function eq>, key='id', value=2)
>>> parse_filter(('color__bad', 'red'))
Traceback (most recent call last):
...
AssertionError: 'bad' operation is not allowed
"""
key, *op = item[0].split('__')
# no value after __ means exact value query, e.g. name='sylvia'
op = ''.join(op).strip() or 'eq'
assert op in self.allowed_operations, f'{repr(op)} operation is not allowed'
return operation(self.allowed_operations[op], key, item[1])
filtered_data = self.data.copy()
for item in map(parse_filter, kwargs.items()):
filtered_data = [
entry for entry in filtered_data
if item.op(entry[item.key], item.value)
]
return filtered_data
def get(self, **kwargs):
"""
>>> DataQuerySet().get(id=3)
[{'id': 3, 'name': 'sylwia', 'color': 'green'}]
"""
operation = namedtuple('Q', 'op key value')
def parse_get(item):
key, *op = item[0].split('__')
return operation(self.allowed_operations['eq'], key, item[1])
filtered_data = self.data.copy()
for item in map(parse_get, kwargs.items()):
filtered_data = [
entry for entry in filtered_data
if item.op(entry[item.key], item.value)
]
if len(filtered_data) > 1:
raise MultipleObjectsReturned(filtered_data)
elif len(filtered_data) < 1:
raise ObjectDoesNotExist(kwargs)
return filtered_data[0]
上述测试只是正常工作,但当我们想做更多工作时,似乎有问题:
print(d.objects.filter(tags__in=['python']))
print(d.objects.filter(author__name='admin'))
print(d.objects.filter(author__name__icontains='use'))
最后,我找到了一个很好的模块来处理这种情况,它调用了,下面是测试:
from reobject.models import Model, Field
from reobject.query.parser import Q as Query
data = [
{'name': 'brad', 'color': 'red', 'tags': [], 'author': {'name': 'admin'}},
{'name': 'sylvia', 'color': 'blue', 'tags': [], 'author': {'name': 'user'}},
{'name': 'sylwia', 'color': 'green', 'tags': [], 'author': {'name': 'admin'}},
{'name': 'shane', 'color': 'red', 'tags': [], 'author': {'name': 'admin'}},
{'name': 'shane', 'color': 'red', 'tags': ['python', 'django'], 'author': {'name': 'user'}}
]
class Book(Model):
name = Field()
color = Field()
tags = Field()
author = Field()
for item in data:
Book(**item)
Book.objects.all()
Book.objects.get(name='brad')
Book.objects.filter(name='brad')
Book.objects.filter(author__name='admin')
Book.objects.filter(tags__contains='python')
Book.objects.filter(Query(author__name='admin') | Query(author__name='user'))
与此同时,它仍然存在也许是因为它已经被拿走了
看,它看起来像你想要的want@AbdulAzizBarkat我已经试过了,但它对
中的标签不起作用
还有作者姓名
from reobject.models import Model, Field
from reobject.query.parser import Q as Query
data = [
{'name': 'brad', 'color': 'red', 'tags': [], 'author': {'name': 'admin'}},
{'name': 'sylvia', 'color': 'blue', 'tags': [], 'author': {'name': 'user'}},
{'name': 'sylwia', 'color': 'green', 'tags': [], 'author': {'name': 'admin'}},
{'name': 'shane', 'color': 'red', 'tags': [], 'author': {'name': 'admin'}},
{'name': 'shane', 'color': 'red', 'tags': ['python', 'django'], 'author': {'name': 'user'}}
]
class Book(Model):
name = Field()
color = Field()
tags = Field()
author = Field()
for item in data:
Book(**item)
Book.objects.all()
Book.objects.get(name='brad')
Book.objects.filter(name='brad')
Book.objects.filter(author__name='admin')
Book.objects.filter(tags__contains='python')
Book.objects.filter(Query(author__name='admin') | Query(author__name='user'))