以下是我们为处理这种情况而实施的模型。
class ConsortiumRule(OrganizationModel):
BY_EMPLOYEE = 1
BY_CLIENT = 2
BY_OCCUPATION = 3
BY_CLASSIFICATION = 4
TYPES = (
(BY_EMPLOYEE, 'Include a specific employee'),
(BY_CLIENT, 'Include all employees of a specific client'),
(BY_OCCUPATION, 'Include all employees of a speciified client ' + \
'that have the specified occupation'),
(BY_CLASSIFICATION, 'Include all employees of a specified client ' + \
'that have the specified classifications'))
consortium = models.ForeignKey(Consortium, related_name='rules')
type = models.PositiveIntegerField(choices=TYPES, default=BY_CLIENT)
negate_rule = models.BooleanField(default=False,
help_text='Exclude people who match this rule')
class ConsortiumRuleParameter(OrganizationModel):
""" example usage: two of these objects one with "occupation=5" one
with "occupation=6" - both FK linked to a single Rule
"""
rule = models.ForeignKey(ConsortiumRule, related_name='parameters')
key = models.CharField(max_length=100, blank=False)
value = models.CharField(max_length=100, blank=False)
起初我反对这种解决方案,因为我不喜欢在 CharField 中存储对其他对象的引用的想法(选择了 CharField,因为它是最通用的。后来,我们可能有一个匹配任何人的规则名字以“Jo”开头)。但是,我认为这是将这种映射存储在关系数据库中的最佳解决方案。这是一个好方法的一个原因是它相对容易清理悬挂的引用。例如,如果一家公司被删除,我们只需要做:
ConsortiumRuleParameter.objects.filter(key='company', value=str(pk)).delete()
如果将参数存储为序列化对象(例如,评论中建议的 Q 对象),这将更加困难和耗时。