我有一个奇怪的需求,一位客户要我实施一个webapp来支持他的数据库。因为我喜欢Django,所以我决定使用它。
我遇到的额外需求如下:用户应该有额外的“权力”来创建模型约束,例如检查IntegerField的范围,所有这些都不知道Python的任何内容。
所以,我有一些想法,但我不确定(如果有的话)是正确的。这是我的想法:
这个请求是否可以解决?你能给我一个最简单的方法吗?
提前致谢,
- 弗拉维奥
答案 0 :(得分:1)
是的,确实可能。我们将使用custom object manager和dynamic Q objects来解决问题。这是一个例子。
创建适当的模型来存储有关约束的信息。请注意,我们将ForeginKey创建为ContentType
,以便将约束绑定到特定的模型类。
#your_app/models.py
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
class PerUserConstraint(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
field_name = models.CharField(max_length = 255)
predicate = models.CharField(max_length = 255) #for example, 'contains' etc.
filter_value = models.CharField(max_length = 255)
创建自定义管理器,将其注册到您的模型中。
#your_app/models.py
from django.db.models.query_utils import Q
class ConstraintedManager(models.Manager):
def get_constrainted_query(self, user):
qs = self.model.objects.all()
content_type = ContentType.objects.get_for_model(self.model.__class__)
constraints = PerUserConstraint.objects.filter(
user = user,
content_type = content_type
)
if constraints:
filters = []
for constraint in constraints:
filters.append(('%s__%s' % (constraint.field_name, constraint.predicate), constraint.value)
# at this point filters should look like this:
# [('question__contains', 'dinner'), ('question__contains', 'meal')]
q_list = [Q(x) for x in filters]
return qs.filter(reduce(operator.and_, q_list))
# which is something like
# return qs.filter(Q(question__contains = 'dinner') & Q(question__contains = 'meal'))
else:
return qs
class YourModel(models.Model):
#some fields
...
c = ConstraintedManager()
因此,在您的观看中,您可以像这样使用它:YourModel.c.get_constrainted_query(user)
请注意,我没有测试此代码,但我希望您已经掌握了这个概念。