Bel*_*dez 9 python django django-models
我一直在寻找一种优雅的方式来代表Django模型中的多选工作日领域(周一,周二,周三......).我最初想的是使用按位数学运行整数字段,但我不确定这是否可行.
这将是一个主要阅读的领域.我希望Queryset方法类似于Entry.objects.get(weekdays__contains=MONDAY)Where MONDAY将是一个常量.
也许有人可以提出更好的解决方案?或者也许有人做过类似的事情并且有一些他们可以贡献的示例代码?
Wil*_*rdy 14
这是一个老问题,但我想我会展示如何在Django中合理地完成它.
这是一个帮助类,用于准备您的选择:
class BitChoices(object):
def __init__(self, choices):
self._choices = []
self._lookup = {}
for index, (key, val) in enumerate(choices):
index = 2**index
self._choices.append((index, val))
self._lookup[key] = index
def __iter__(self):
return iter(self._choices)
def __len__(self):
return len(self._choices)
def __getattr__(self, attr):
try:
return self._lookup[attr]
except KeyError:
raise AttributeError(attr)
def get_selected_keys(self, selection):
""" Return a list of keys for the given selection """
return [ k for k,b in self._lookup.iteritems() if b & selection]
def get_selected_values(self, selection):
""" Return a list of values for the given selection """
return [ v for b,v in self._choices if b & selection]
Run Code Online (Sandbox Code Playgroud)
使用PositiveIntegerField定义您的模型,以及您想要的选择:
WEEKDAYS = BitChoices((('mon', 'Monday'), ('tue', 'Tuesday'), ('wed', 'Wednesday'),
('thu', 'Thursday'), ('fri', 'Friday'), ('sat', 'Saturday'),
('sun', 'Sunday')
))
Run Code Online (Sandbox Code Playgroud)
这意味着您可以访问以下值:
>>> print list(WEEKDAYS)
[(1, 'Monday'), (2, 'Tuesday'), (4, 'Wednesday'), (8, 'Thursday'), (16, 'Friday'), (32, 'Saturday'), (64, 'Sunday')]
>>> print WEEKDAYS.fri
16
>>> print WEEKDAYS.get_selected_values(52)
['Wednesday', 'Friday', 'Saturday']
Run Code Online (Sandbox Code Playgroud)
现在使用PositiveIntegerField以下选项定义您的模型:
class Entry(models.Model):
weekdays = models.PositiveIntegerField(choices=WEEKDAYS)
Run Code Online (Sandbox Code Playgroud)
你的模型已经完成.对于查询,以下功能:
Entry.objects.extra(where=["weekdays & %s"], params=[WEEKDAYS.fri])
Run Code Online (Sandbox Code Playgroud)
可能有一种方法可以创建一个Q()整齐地打包查询的对象子类,所以它们看起来像这样:
Entry.objects.filter(HasBit('weekdays', WEEKDAYS.fri))
Run Code Online (Sandbox Code Playgroud)
或者甚至破解F()子类来创建这样的东西:
Entry.objects.filter(weekdays=HasBit(WEEKDAYS.fri))
Run Code Online (Sandbox Code Playgroud)
但我现在没有时间去探索这个问题..where工作正常,可以抽象成一个查询集函数.
最后一个考虑因素是,您可能会点亮以创建自定义模型字段,该字段将数据库中的位掩码转换为列表或在Python中设置.然后,您可以使用SelectMultiple窗口小部件(或CheckboxSelectMultiple)允许用户在管理员中选择其值.
| 归档时间: |
|
| 查看次数: |
4718 次 |
| 最近记录: |