Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用distinct()为Django ListView中的每个标题项仅显示子模型中的一条记录_Python_Django_Sqlite_Django Views - Fatal编程技术网

Python 如何使用distinct()为Django ListView中的每个标题项仅显示子模型中的一条记录

Python 如何使用distinct()为Django ListView中的每个标题项仅显示子模型中的一条记录,python,django,sqlite,django-views,Python,Django,Sqlite,Django Views,我在Django应用程序中使用了两个相关的模型。在模型中创建的对象将使用listview类显示。在子模型中,我可以基于某个关键日期创建多行。当我尝试显示两个模型中的值时,将显示相应FK字段的所有子对象(如果存在多条记录) 让我把情况说清楚如下: models.py views.py 现在,物料价格会定期变化,并且每个关键日期的每种物料都会有多个价格项(price\u valid\u from\u date)。我的目标是显示存在价格文件的所有材料的最新价格。我的困境是如何为同一材料/文件组合选择多

我在Django应用程序中使用了两个相关的模型。在模型中创建的对象将使用listview类显示。在子模型中,我可以基于某个关键日期创建多行。当我尝试显示两个模型中的值时,将显示相应FK字段的所有子对象(如果存在多条记录)

让我把情况说清楚如下:

models.py views.py 现在,物料价格会定期变化,并且每个关键日期的每种物料都会有多个价格项(
price\u valid\u from\u date
)。我的目标是显示存在价格文件的所有材料的最新价格。我的困境是如何为同一材料/文件组合选择多个价格项目中的一个。我的代码行
'mat\u price\u item\u list':MatPriceItems.objects.distinct().order\u by('price\u doc\u header'),
当然不会产生任何结果(所有价格项都显示在连续的列中)

是否有办法在列表视图中只显示一个价格项目?

编辑 下图显示了材料不同日期的价格。我想得到的只是显示某一特定材料的最新(有效)日期的价格。因此,在即时情况下(如图所示),应仅显示2020年3月4日每种商品的价格MSHSD

编辑2 这就是标题文档编号(此处编号为32)实例的子模型数据的外观(使用数据浏览器从子表中获取图像):

列为:子对象。物料编号/价格/有效期自/有效期至/Hdr文件编号/子Obj行编号

我的想法是:我不能只从文档编号集合中提取第一个对象(子集)吗?在即时情况下(参考图片),文件编号32有三个子项(轴承编号148149156)。是否不可能只拾取项目编号156并丢弃其余项目

我试过:

MatPriceItems.objects.order\u by('-price\u valid\u to\u date')。first()

但引发错误
“MatPriceItems”对象不可编辑


什么使我能够获取标题项目的唯一项目并显示它?

我相信您需要以下内容:

class MatPriceListView(ListView):
    template_name = "mat_price_list.html"
    context_object_name = 'matprice'
    model = MatPriceDoc

    def get_context_data(self, **kwargs):
        context = super(MatPriceListView, self).get_context_data(**kwargs)
        context.update({
            'mat_price_item_list': MatPriceItems.objects.all().('-price_doc_header').first(),
        })
        return context

    def get_queryset(self):
        return MatPriceDoc.objects.order_by('mat_num')
关键的变化是:

MatPriceItems.objects.all().order_by('-price_doc_header').first()
这样,您就可以按
price\u doc\u标题
降序订购(因此该值的前面是负数)。然后在返回的
对象中获取
.first()

同样,以下内容也是有效的:

MatPriceItems.objects.all().order_by('price_doc_header').last()
您还可以在ORM中使用Django的内置聚合:

from django.db.models import Max

MatPriceItems.objects.all().aggregate(Max('price_doc_header'))
综上所述,我认为代码可读性的最佳解决方案是使用Django的内置
Max
函数:

from django.db.models import Max

class MatPriceListView(ListView):
    template_name = "mat_price_list.html"
    context_object_name = 'matprice'
    model = MatPriceDoc

    def get_context_data(self, **kwargs):
        context = super(MatPriceListView, self).get_context_data(**kwargs)
        context.update({
            'mat_price_item_list': MatPriceItems.objects.all().aggregate(Max('price_doc_header'))
        })
        return context

    def get_queryset(self):
        return MatPriceDoc.objects.order_by('mat_num')
因为它准确地告诉任何同事你在做什么:取最大值


更新:再看一眼你的问题-我相信你可能还需要做一些
.filter()
…然后为
Max
做一个
.annotate()

我相信你需要以下几点:

class MatPriceListView(ListView):
    template_name = "mat_price_list.html"
    context_object_name = 'matprice'
    model = MatPriceDoc

    def get_context_data(self, **kwargs):
        context = super(MatPriceListView, self).get_context_data(**kwargs)
        context.update({
            'mat_price_item_list': MatPriceItems.objects.all().('-price_doc_header').first(),
        })
        return context

    def get_queryset(self):
        return MatPriceDoc.objects.order_by('mat_num')
关键的变化是:

MatPriceItems.objects.all().order_by('-price_doc_header').first()
这样,您就可以按
price\u doc\u标题
降序订购(因此该值的前面是负数)。然后在返回的
对象中获取
.first()

同样,以下内容也是有效的:

MatPriceItems.objects.all().order_by('price_doc_header').last()
您还可以在ORM中使用Django的内置聚合:

from django.db.models import Max

MatPriceItems.objects.all().aggregate(Max('price_doc_header'))
综上所述,我认为代码可读性的最佳解决方案是使用Django的内置
Max
函数:

from django.db.models import Max

class MatPriceListView(ListView):
    template_name = "mat_price_list.html"
    context_object_name = 'matprice'
    model = MatPriceDoc

    def get_context_data(self, **kwargs):
        context = super(MatPriceListView, self).get_context_data(**kwargs)
        context.update({
            'mat_price_item_list': MatPriceItems.objects.all().aggregate(Max('price_doc_header'))
        })
        return context

    def get_queryset(self):
        return MatPriceDoc.objects.order_by('mat_num')
因为它准确地告诉任何同事你在做什么:取最大值


更新:再看一眼你的问题-我相信你可能还需要做一些
.filter()
…然后为
Max
做一个
.annotate()

我还添加了我现在认为正确的答案,基于对你问题的重读

我觉得这个问题需要简化为:

MatPriceItems.objects.all().select_related(
    'mat_price_docs'
).order_by(
    'price_doc_header__mat_num'
)
i、 e

为了实现这一点,您还可以将
相关的\u name
参数添加到
价格\u单据头
ForeignKey
字段中

class MatPriceItems(models.Model):
    price_doc_header = models.ForeignKey(MatPriceDoc, related_name='mat_price_docs', on_delete=...)
    price_item_num = models.CharField(max_length=3, default=10,...)
    price_valid_from_date = models.DateField(null=True, verbose_name='From date')
    price_valid_to_date = models.DateField(null=True, verbose_name='To date')
    mat_price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True,...)
一如既往,对模型的任何更改-请重新运行
makemigarations
migrate
管理命令

编辑:您甚至可以使用注释链接到ForeignKey来定义新的查询集:

def get_queryset(self):
        return MatPriceItems.objects.all().order_by(
                    'price_doc_header__mat_num'
               ).annotate(
                    mat_price_doc_number = F('price_doc_header__mat_price_doc_number')
                    ...
               )

注意:您可以从django.db.models import F

导入F()表达式,根据对您的问题的重读,我现在还添加了我认为正确的答案

我觉得这个问题需要简化为:

MatPriceItems.objects.all().select_related(
    'mat_price_docs'
).order_by(
    'price_doc_header__mat_num'
)
i、 e

为了实现这一点,您还可以将
相关的\u name
参数添加到
价格\u单据头
ForeignKey
字段中

class MatPriceItems(models.Model):
    price_doc_header = models.ForeignKey(MatPriceDoc, related_name='mat_price_docs', on_delete=...)
    price_item_num = models.CharField(max_length=3, default=10,...)
    price_valid_from_date = models.DateField(null=True, verbose_name='From date')
    price_valid_to_date = models.DateField(null=True, verbose_name='To date')
    mat_price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True,...)
一如既往,对模型的任何更改-请重新运行
makemigarations
migrate
管理命令

编辑:您甚至可以使用注释链接到ForeignKey来定义新的查询集:

def get_queryset(self):
        return MatPriceItems.objects.all().order_by(
                    'price_doc_header__mat_num'
               ).annotate(
                    mat_price_doc_number = F('price_doc_header__mat_price_doc_number')
                    ...
               )

注意:您可以从django.db导入F()表达式,作为
。models import F

您使用的是什么数据库?@WillemVanOnsem:我使用sqlite3进行测试。Distinct将返回表中所有的Distinct记录,而不是一条……也许您需要
对u进行排序,然后使用
。first()
,以获得“最大值”你能澄清一下是什么吗