django - 基础模型的自定义管理器。用于过滤具有不同属性的子类的模型
问题描述
假设我有以下类,它为具有时间间隔的数据实现了一个基本模型(我不在这里写整个实现,我不能使用第三方库)。
class BaseHistorizationModel(models.Model):
value = models.DecimalField(decimal_places=2, max_digits=5)
date_begin = models.DateField(db_index=True, blank=True, null=True)
date_end = models.DateField(db_index=True, blank=True, null=True)
class Meta:
abstract = True
ordering = [F("date_begin").asc(nulls_last=True)]
@classmethod
def get_values_between(cls, date_begin, date_end):
instances = cls.get_instances_between(date_begin, date_end)
return [(i.date_begin, i.value) for i in instances}
@classmethod
def get_instances_between(cls, date_begin, date_end):
begin_overlap = cls._get_begin_overlap(date_begin, date_end)
end_overlap = cls._get_end_overlap(date_begin, date_end)
insides = cls.object.filter(
date_begin__gte=date_begin,
date_end__lte=date_end,
)
over = cls._get_overlap(date_begin, date_end)
return to_list(
over if over else (begin_overlap, insides, end_overlap)
)
@classmethod
def _get_begin_overlap(cls, date_begin, date_end):
try:
overlap = cls.objects.get(
Q(date_begin__lt=date_begin)
& Q(date_end__gt=date_begin)
& Q(date_end__lt=date_end)
)
except cls.ObjectDoesNotExist:
overlap = None
return overlap
...
然后我有其他类继承自BaseHistorizationModel
,例如:
class NbOccupant(BaseHistorizationModel):
value = models.IntegerField()
building = models.ForeignKey(
Building,
on_delete=models.CASCADE,
related_name="nb_occupants",
)
class Temperature(BaseHistorizationModel):
value = models.IntegerField()
city = models.ForeignKey(
City,
on_delete=models.CASCADE,
related_name="temperatures",
)
我不清楚如何将我的方法get_values_between_date
用于子类。对于这些类,我需要首先使用他们自己的外键过滤我的数据,我希望能够执行以下操作:
nb_occupants = NbOccupant.get_values_between_date(start, end, building__name="palais de l'elysee")
temperatures = Temperature.get_values_between(start, end, city__name="Grenoble")
我最终得到以下结果:
class BaseHistorization(models.Model):
...
@classmethod
def get_values_between(date_begin, date_end, **extra_query):
instances = cls.get_instances_between(date_begin, date_end, extra_query)
return {i.date_begin: i.value for i in instances}
...
@classmethod
def _get_begin_overlap(date_begin, date_end, extra_query):
query = (
Q(date_begin__lt=date_begin)
& Q(date_end__gt=date_begin)
& Q(date_end__lt=date_end)
)
try:
overlap = cls.objects.filter(query, **extra_query)
except cls.ObjectDoesNotExist:
overlap = None
return overlap
这似乎有点复杂,我需要将 extra_query 通过我的所有功能传递到cls.objects.get
or cls.objects.filter
。我有很多这样的函数调用。我认为CustomManager
可以帮助我,但我不完全明白如何。或者也许我可以做点别的。
解决方案
推荐阅读
- git - 使用 go-git 从 GitHub Enterprise 克隆存储库
- vba - 第二次 For 循环在我第二次运行 Sub 之前不起作用
- python - TensorFlow 训练数据错误。值错误
- ejabberd - 禁止帐户的 Ejabberd 钩子
- laravel - 登录不适用于 VueJS 和 Laravel
- c# - 如何获取 DirectoryInfo 列表,其中目录名称包含存储在 List 中的字符串
? - python - 尝试从 json 文件中获取数据时出错
- python - 如何运行 python 2.7.15 和 3.6.4 的两个版本以及如何将软件包安装到特定版本的 python?
- html - Flex:对齐按钮向右对齐,内容向左对齐
- google-cloud-platform - 从 Google Cloud Storage 读取 Dataproc