简体   繁体   English

Django 查询集在查询中获取空值

[英]Django queryset get empty values in query

So I'm trying to get all the values to be able to display in my templates.所以我试图让所有的值能够显示在我的模板中。 However I have encountered myself with this problem:但是我遇到了这个问题:

I have these models:我有这些模型:

class Project(models.Model):
    projectId = models.AutoField(primary_key=True, db_column="Id", db_index=True, verbose_name='Project ID')
    description = models.CharField(max_length=900)

class PM(models.Model):
    PMid = models.AutoField(primary_key=True, db_column="Id", db_index=True)
    PMNumber = models.CharField(max_length=50, unique=True, db_column="PMNumber")
    description = models.CharField(max_length=600)
    projectId = models.ForeignKey(Project, on_delete=models.CASCADE,
                                  db_column="ProjectID", related_name='+')

And I'm trying to get all the projects with their respective PMNumber.我正在尝试使用它们各自的 PMNumber 获取所有项目。 For which I'm trying something like this:我正在尝试这样的事情:

fpm = PM.objects.all()
projects = []
for i in fpm:
   projects.append({'ProjectName': i.projectId.description, 'PMNumber': i.PMNumber})

After that the result is like this之后结果是这样的

[{'ProjectName': 'pr1', 'PMNumber': '119508-01'}, {'ProjectName': 'pr1', 'PMNumber': '119490-01'}]

However, I'm still missing some projects that don't have a PM related to them, I want all the projects in the queryset to be able to show them in a template, not just the ones that have a PM.但是,我仍然缺少一些没有与之相关的 PM 的项目,我希望查询集中的所有项目都能够在模板中显示它们,而不仅仅是具有 PM 的项目。 It should look something like this:它应该看起来像这样:

[{'ProjectName': 'pr2', 'PMNumber':'None'}, {'ProjectName':'pr3' , 'PMNumber':'None'}, {'ProjectName': 'pr1', 'PMNumber': '119508-01'}, {'ProjectName': 'pr1', 'PMNumber': '119490-01'}]

Is there a way to do this?有没有办法做到这一点? or is there another way to do this in the views?还是在视图中有另一种方法可以做到这一点?

Note: I know that setting an ID for each class in Django is not right, but it's kind of a standard in the place where I work at.注意:我知道在 Django 中为每个 class 设置一个 ID 是不对的,但这在我工作的地方是一种标准。 So I can't change it.所以我无法改变它。

You should then do this the opposite way:然后,您应该以相反的方式执行此操作:

result = list(Project.objects.values(
    'description',
    ProjectName=F('pm__PMNumber')
))

For the Project s for which no PM exists, None will be used for ProjectName .对于不存在PMProjectProjectName将使用None If there are multiple PM s for the same Project , all these PM s will be added.如果同一个Project有多个PM ,则将添加所有这些PM

That being said, I do not see why you set related_name to realted_name='+' .话虽如此,我不明白您为什么将 related_name 设置为related_name realted_name='+' This is the name of the relation in reverse, so likely it is better to set it to something like:这是反向关系的名称,因此最好将其设置为:

class PM(models.Model):
    PMid = models.AutoField(primary_key=True, db_column="Id", db_index=True)
    PMNumber = models.CharField(max_length=50, unique=True, db_column="PMNumber")
    description = models.CharField(max_length=600)
    projectId = models.ForeignKey(
        Project, on_delete=models.CASCADE,
        db_column="ProjectID",
        related_name='pm_set'
)

Then you query with:然后你查询:

result = list(Project.objects.values(
    'description',
    ProjectName=F('pm_set__PMNumber')
))

You can replace a missing ProjectName with the description of the project with:您可以将缺少的ProjectName替换为项目的description

from django.db.models.functions import Coalesce

result = list(Project.objects.values(
    'description',
    ProjectName=Coalesce('pm_set__PMNumber', 'description')
))

You can also post-process the list to a dictionary that contains dictionaries where the projectName (or perhaps better projectNames is a list , with:您还可以将列表后处理到包含字典的字典,其中projectName (或者更好的projectNameslist ,具有:

from itertools import groupby
from operator import itemgetter
from django.db.models.functions import Coalesce

result = list(Project.objects.values(
    'description',
    ProjectName=Coalesce('pm_set__PMNumber', 'description')
).order_by('description'))

result = [ 
    { 'description': k, 'projectNames': list(map(itemgetter('projectName'), vs)) }
    for k, vs in groupby(itemgetter('description'), result)
]

or we can make an empty list for Projects with no PM with:或者我们可以为没有PMProjects创建一个空列表:

from itertools import groupby
from operator import itemgetter

result = list(Project.objects.values(
    'description',
    ProjectName=F('pm_set__PMNumber')
).order_by('description'))

result = [ 
    { 'description': k, 'projectNames': list(filter(None, map(itemgetter('projectName'), vs))) }
    for k, vs in groupby(itemgetter('description'), result)
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM