Django queryset получает пустые значения в запросе - PullRequest
2 голосов
/ 23 апреля 2020

Поэтому я пытаюсь получить все значения, которые можно отобразить в моих шаблонах. Однако я столкнулся с этой проблемой:

У меня есть эти модели:

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='+')

И я пытаюсь получить все проекты с соответствующим PMNumber. Для чего я пытаюсь что-то вроде этого:

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

После этого результат выглядит следующим образом

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

Однако я все еще скучаю по некоторым проектам, которые не имеют PM, связанный с ними, я хочу, чтобы все проекты в наборе запросов могли отображать их в шаблоне, а не только те, которые имеют PM. Это должно выглядеть примерно так:

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

Есть ли способ сделать это? или есть другой способ сделать это в представлениях?

Примечание: я знаю, что установка идентификатора для каждого класса в Django неправильна, но это своего рода стандарт в месте, где я работаю , Поэтому я не могу это изменить.

1 Ответ

2 голосов
/ 23 апреля 2020

Затем вы должны сделать это противоположным способом:

result = list(Project.objects.values(
    'description',
    <b>ProjectName=F('pm__PMNumber')</b>
))

Для Project s, для которых не существует PM, None будет использоваться для ProjectName. Если есть несколько PM s для одного и того же Project, будут добавлены все эти PM s.

При этом я не понимаю, почему вы устанавливаете related_name в realted_name='+'. Это имя отношения в обратном порядке, поэтому, скорее всего, лучше установить его следующим образом:

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",
        <b>related_name='pm_set'</b>
)

Затем вы запросите:

result = list(Project.objects.values(
    'description',
    <b>ProjectName=F('pm_set__PMNumber')</b>
))

Вы можете заменить отсутствующее ProjectName с description проекта с:

from django.db.models.functions import Coalesce

result = list(Project.objects.values(
    'description',
    <b>ProjectName=Coalesce('pm_set__PMNumber', 'description')</b>
))

Вы также можете пост-обработать список в словарь, содержащий словари, где projectName (или, возможно, лучше projectNames является список , с:

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

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

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

или мы можем создать пустой список для Projects без PM с:

from itertools import groupby
from operator import itemgetter

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

result = [ 
    { 'description': k, 'projectNames': list(filter(None, map(itemgetter('projectName'), vs))) }
    for k, vs in groupby(itemgetter('description'), result)
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...