Невозможно отобразить все результаты в отношении M2M - PullRequest
0 голосов
/ 22 марта 2020

В настоящее время у меня есть следующая модель отношений сущностей:

Связь таблиц

 ------------          -----------------           ------
| Objective | ------- | Objective_Task | ---------| Task |
 ------------          -----------------           ------

, и я пытаюсь отобразить результаты, как в следующей таблице

| id  |        Task        |   Task status |     Objective      |
----------------------------------------------------------------
|  1  |  Set up drivers    | In progress   | Set up my machine  |
|  2  |  Configure network | In progress   | Set up the network |
|  3  |  Test the network  | In progress   | Set up the network |

Но результат, который я получаю:

| id  |        Task        |   Task status |        Objective          |
-----------------------------------------------------------------------
|  1  |  Set up drivers    | In progress   | objective.Objective.None  |
|  2  |  Configure network | In progress   | objective.Objective.None  |
|  3  |  Test the network  | In progress   | objective.Objective.None  |

Ниже приведена настройка моих моделей классов для этого отношения сущности:

Объективная модель

class Objective(models.Model):
    id               = models.AutoField(primary_key=True)
    objective        = models.CharField(null=False, max_length=60)
    initial_date     = models.DateField(default=timezone.now(), null=False)
    expiration_date  = models.DateField()

    class Meta:
        ordering = ['initial_date']
        db_table = 'goal_objective'

Модель задачи

class Task(models.Model):
    ACTIVE = 'Active'
    FINALIZED = 'Finalized'

    STATUS = [(ACTIVE, ACTIVE), (FINALIZED, FINALIZED)]

    id           = models.AutoField(primary_key=True)
    objective    = models.ManyToManyField(Objective)
    task         = models.CharField(null=False, max_length=140)
    status       = models.CharField(max_length=24, choices=STATUS, default=ACTIVE)

    class Meta:
        db_table = 'task_table'

Это код, который я использовал для заполнения таблицы.

objective_ids = []
qs_current_objectives = Objective.objects.filter(initial_date__gte=date(2020,1,1), expiration_date__lte=date(2020,12,31)).values('id').values_list('id')

for value in qs_current_objectives:
    objective_ids.append(value)    

form = {'task_list': Task.objects.filter(objective__in=objective_ids)}

извлечение. html

{% for task in task_list %}
<table>
    <tbody>
        <tr>
         <td>{{task.id}}</td>
         <td>{{task.task}}</td>
         <td>{{task.status}}</td>
         <td>{{task.objective}}</td>
        </tr>
   </tbody>
</table>

Что мне не хватало в моих моделях, что я не могу достичь названия цели?

1 Ответ

1 голос
/ 23 марта 2020

Есть несколько вещей, которые вы должны изменить, чтобы избежать проблем в будущем.

class Objective(models.Model):
    initial_date = models.DateField(default=timezone.now, null=False)

Обратите внимание, что вы передаете функцию, а не результат вызова функции default. Если вы делаете то, что имеете, значение по умолчанию будет меняться при каждом перезапуске веб-сервера. Передача функции по умолчанию установит дату на текущую дату.

class Task(models.Model):
    objectives    = models.ManyToManyField(Objective, related_name='tasks')

При присвоении имени связи с множественной версией слова код становится более понятным. Теперь, когда вы получаете доступ к task.objectives, вы знаете, что это коллекция. task.objective создает впечатление, что он должен быть только один.

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

current_objectives = Objective.objects.filter(
    initial_date__gte=date(2020,1,1),
    expiration_date__lte=date(2020,12,31)
)
tasks = Task.objects.filter(objectives__in=current_objectives).distinct()
form = {'task_list': tasks}

Или вы можете просмотреть взаимосвязь в фильтре.

tasks = Task.objects.filter(
    objectives__initial_date__gte=date(2020,1,1),
    objectives__expiration_date__lte=date(2020,12,31),
).distinct()
form = {'task_list': tasks}

Тогда ваш шаблон должен выглядеть следующим образом:

{% for task in task_list %}
<table>
    <tbody>
        <tr>
         <td>{{task.id}}</td>
         <td>{{task.task}}</td>
         <td>{{task.status}}</td>
         <td>{{task.objectives.all}}</td>
        </tr>
   </tbody>
</table>
{% endfor %}

task.objectives (или task.objective в вашем текущем коде) - это просто ссылка на экземпляр Manager, а не на саму коллекцию. Вам необходимо получить доступ к .all, чтобы получить фактические данные.

...