<p>这是你的意思吗?在</p>
<p>此解决方案不依赖于外部库和使用
**kwargs、发电机/外壳和@property decorator。所以从学习的角度来看这可能很有趣。在</p>
<p>如果您设法使用Django读取列表中的数据,那么对于Django兼容性,作为我的代码,这可能会更好。
这取决于你的目标是什么。(完美地模仿django过滤器)或者(学习如何做一个不那么完美的模仿,但是拥有完整的源代码而没有依赖关系)</p>
<pre><code>DATA = [
{'id': 1, 'name': 'brad', 'color':'red'},
{'id': 2, 'name': 'sylvia', 'color':'blue'},
{'id': 3, 'name': 'paul', 'color':'red'},
{'id': 4, 'name': 'brandon', 'color':'yello'},
{'id': 5, 'name': 'martin', 'color':'green'},
{'id': 6, 'name': 'annie', 'color':'gray'},
]
class UnknownOperator(Exception):
""" custom exception """
class FilterData:
def __init__(self, data):
self.data = data
def _filter_step(self, key, value, data):
if not "__" in key:
return (entry for entry in data if entry[key] == value)
else:
key, operator = key.split("__")
if operator == "gt": # greater than
return (entry for entry in data if entry[key] > value)
elif operator == "lt": # less than
return (entry for entry in data if entry[key] < value)
elif operator == "startswith": # starts with
return (entry for entry in data if entry[key].startswith(value))
elif operator == "in": # starts with
return (entry for entry in data if entry[key] in value)
else:
raise UnknownOperator("operator %s is unknown" % operator)
def _exclude_step(self, key, value, data):
if not "__" in key:
return (entry for entry in data if entry[key] != value)
else:
key, operator = key.split("__")
if operator == "gt": # greater than
return (entry for entry in data if entry[key] <= value)
elif operator == "lt": # less than
return (entry for entry in data if entry[key] >= value)
elif operator == "startswith": # starts with
return (entry for entry in data if not entry[key].startswith(value))
elif operator == "in": # starts with
return (entry for entry in data if entry[key] not in value)
else:
raise UnknownOperator("operator %s is unknown" % operator)
def filter(self, **kwargs):
data = (entry for entry in self.data)
for key, value in kwargs.items():
data = self._filter_step(key, value, data)
return FilterData(data)
def exclude(self, **kwargs):
data = (entry for entry in self.data)
for key, value in kwargs.items():
data = self._exclude_step(key, value, data)
return FilterData(data)
def all(self):
return FilterData(self.data)
def count(self):
cnt = 0
for cnt, entry in enumerate(self.data, 1):
pass
return cnt
def __iter__(self):
for entry in self.data:
yield entry
# make it even more look like django managers / filters
class DataManager:
def __init__(self, data):
self.data = data
@property
def objects(self):
return FilterData(self.data)
fdata = FilterData(DATA)
assert [v["id"] for v in fdata.filter(name="paul")] == [3]
assert [v["id"] for v in fdata.filter(color="red")] == [1, 3]
assert [v["id"] for v in fdata.filter(id__gt=2)] == [3, 4, 5, 6]
assert [v["id"] for v in fdata.filter(color__startswith="gr")] == [5, 6]
fmgr = DataManager(DATA)
assert [v["id"] for v in fmgr.objects.filter(name="paul")] == [3]
assert [v["id"] for v in fmgr.objects.filter(color="red")] == [1, 3]
assert [v["id"] for v in fmgr.objects.filter(id__gt=2)] == [3, 4, 5, 6]
assert [v["id"] for v in fmgr.objects.filter(color__startswith="gr")] == [5, 6]
assert [v["id"] for v in fmgr.objects.filter(color__startswith="gr", id__lt=6)] == [5]
assert [v["id"] for v in fmgr.objects.filter(color__startswith="gr", id__lt=6)] == [5]
assert [v["id"] for v in fmgr.objects.filter(color__startswith="gr").filter(id__lt=6)] == [5]
assert fmgr.objects.filter(color__startswith="gr").filter(id__lt=6).count() == 1
assert fmgr.objects.filter(id__gt=2).count() == 4
assert fmgr.objects.count() == 6
assert [v["id"] for v in fmgr.objects.all()] == list(range(1, 7))
</code></pre>