Django查询操作表中带有IN、OUT值和日期时间字段的当前库存列表。

huangapple go评论59阅读模式
英文:

Django Query for current stock list from operations table field with IN, OUT value and field with date and time

问题

下面是根据您提供的代码部分的翻译:

# 选择操作类型为IN的记录
in_entries = Operations.objects.filter(ops_type=Operations.OPS.IN.value)

# 选择操作类型为OUT,且与外部引用(OuterRef)的serial字段匹配的记录,并计算最新的OUT时间
out_entries = Operations.objects.filter(
    ops_type=Operations.OPS.OUT.value,
    serial=OuterRef('serial')
).values('serial').annotate(
    latest_out_datetime=Subquery(
        Operations.objects.filter(
            ops_type=Operations.OPS.OUT.value,
            serial=OuterRef('serial')
        ).annotate(
            datetime=ExpressionWrapper(F('date') + F('time'), output_field=DateTimeField())
        ).order_by('-datetime').values('datetime')[:1]
    )
)

# 对于选择的IN记录,计算日期和时间,以及最新的OUT时间,并筛选出可用库存
available_stock = in_entries.annotate(
    in_datetime=ExpressionWrapper(F('date') + F('time'), output_field=DateTimeField()),
    latest_out_datetime=F('serial__latest_out_datetime')
).filter(
    Q(latest_out_datetime__isnull=True) | Q(in_datetime__gt=F('latest_out_datetime'))
)

# 创建可用库存的序列列表
stock_list = [stock.serial for stock in available_stock]

print("可用库存列表:", stock_list)

请注意,上述翻译仅包括代码部分,不包括问题或其他信息。如果您有任何进一步的问题或需要进一步的帮助,请告诉我。

英文:

Django Query for below case to find list of available stock based on ops_type=IN entry with date and time and ops_type=OUT entry with date and time.

date and time field are separate because the data is uploaded from sheet and needs to be in same format to process.

Operations model is as follows

class Operations(BaseModel):
    class OPS(IntEnum):
        IN = 0
        OUT = 1

        @classmethod
        def choices(cls):
            return [(key.value, key.name) for key in cls]

    date = models.DateField()
    time = models.TimeField(default=None, null=True)
    ops_type = models.IntegerField(choices=OPS.choices())
    serial = models.CharField(max_length=255, default=None, null=True, db_index=True)
    product = models.CharField(max_length=255, default=None)

Error: Cannot resolve keyword 'latest_out_datetime' into field. Join on 'serial' not permitted.

from django.db.models import F, Q, Subquery, OuterRef, ExpressionWrapper, DateTimeField
from datetime import datetime

in_entries = Operations.objects.filter(ops_type=Operations.OPS.IN.value)

out_entries = Operations.objects.filter(
    ops_type=Operations.OPS.OUT.value,
    serial=OuterRef('serial')
).values('serial').annotate(
    latest_out_datetime=Subquery(
        Operations.objects.filter(
            ops_type=Operations.OPS.OUT.value,
            serial=OuterRef('serial')
        ).annotate(
            datetime=ExpressionWrapper(F('date') + F('time'), output_field=DateTimeField())
        ).order_by('-datetime').values('datetime')[:1]
    )
)

available_stock = in_entries.annotate(
    in_datetime=ExpressionWrapper(F('date') + F('time'), output_field=DateTimeField()),
    latest_out_datetime=F('serial__latest_out_datetime')
).filter(
    Q(latest_out_datetime__isnull=True) | Q(in_datetime__gt=F('latest_out_datetime'))
)

stock_list = [stock.serial for stock in available_stock]

print("List of available stock:", stock_list)

答案1

得分: 1

以下是翻译好的内容:

这里的一些代码没有意义。例如,为什么在 out_entries 中有两个 OuterRef?为什么没有用 Subquery 包装起来?

我认为你在这里使实现过于复杂了。我认为你可以简单尝试如下:

from django.db.models import Q, Max, F

in_entries = Operations.objects.annotate(
    datetime=ExpressionWrapper(
        F('date') + F('time'),
        output_field=DateTimeField()
    )
   .values('serial')
   .annotate(
        max_out_date=Max(
            'datetime',
            filter=Q(
                serial=F('serial'),
                ops_type=Operations.OPS.OUT.value
            )
        )
    ).filter(ops_type=Operations.OPS.IN.value).values('serial', 'max_out_date')

有关更多信息,请参阅 Django 聚合速查表 中的文档。

英文:

Some of the code here does not make sense. For example why do you have two OuterRef in out_entries? Why it is not wrapped with Subquery?

I think you are making the implementation overcomplicated here. I think you can simply try like this:

from django.db.models import Q, Max, F

in_entries = Operations.objects.annotate(
    datetime=ExpressionWrapper(
        F('date') + F('time'),
        output_field=DateTimeField()
    )
   .values('serial')
   .annotate(
        max_out_date=Max(
            'datetime',
            filter=Q(
                serial=F('serial'),
                ops_type=Operations.OPS.OUT.value
            )
        )
    ).filter(ops_type=Operations.OPS.IN.value).values('serial', 'max_out_date')

For more information, please see the Django aggregation cheat sheet in the documentation.

huangapple
  • 本文由 发表于 2023年5月7日 03:33:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76190755.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定