Создайте строку, содержащую значения из связанных объектов для отображения в представлении - PullRequest
Купить гитару в Москве
0 голосов
/ 23 декабря

Я новичок в Джанго, поэтому, пожалуйста, потерпите меня. Я пытаюсь создать представление, в котором перечислены JournalEntries, которые имеют тип = BP. Список должен включать выбранные значения из LineItems, которые связаны с каждым JournalEntry. Каждый объект JournalEntry с типом = BP всегда имеет только два связанных LineItems.

models.py

class JournalEntry(models.Model):
    date = models.DateField(null=True, blank=False)
    TYPE = (
        ('BP', 'Bank Payment'),
        ('YE', 'Year End'),
    )
    type = models.CharField(
        max_length=2,
        choices=TYPE,
        blank=True,
        default='0'
        )

class LineItem(models.Model):
    journal_entry = models.ForeignKey(JournalEntry, on_delete=models.PROTECT)
    ledger = models.ForeignKey(Ledger, on_delete=models.PROTECT)
    description = models.CharField(max_length=255, null=True, blank=True)
    cr = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
    dr = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)

class Ledger(models.Model):
    name = models.CharField(max_length=255)

views.py

def journalentries_show_all(request):
    journal_entries = JournalEntry.objects.filter(type="BP")

    context = {
        'journal_entries': journal_entries,
    }
    return render(request, 'journal/journalentries_show_all.html', context)

Мой шаблон journalentries_show_all.html

<ul>
 {% for journal_entry in journal_entries %}
  <li>{{ journal_entry.date }}</li>
  <li>{{ ledger name from first line item in this journal_entry }}</li>
  <li>{{ ledger name from second line item in this journal_entry }}</li>
  <li>{{ description from first line item in this journal_entry }}</li>
  <li>{{ description from second line item in this journal_entry }}</li>
 {% endfor %}
</ul>

В этом конкретном представлении меня интересует только отображение JournalEntries с типом = BP, у всех из которых только две позиции. Другие типы JournalEntries имеют больше LineItems, но они рассматриваются в другом представлении.

Ответы [ 4 ]

0 голосов
/ 23 декабря

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

<td>{{ journal_entry.date }}</td>
<td>{{ journal_entry.lineitem_set.all.1.ledger }}</td>
<td>{{ journal_entry.lineitem_set.all.0.ledger }}</td>
<td>{{ journal_entry.lineitem_set.all.1.description|truncatechars:15 }}</td>
<td>{{ journal_entry.lineitem_set.all.0.description|truncatechars:15 }}</td>
0 голосов
/ 23 декабря

Почему вы хотите передать информацию в виде строки? Это дополнительный шаг, который ничего не добавляет. Вы можете передавать целые словари как переменную context, поэтому я рекомендую вам это сделать. По вашему мнению, можно запросить строки на основе фильтра, как показано в документах здесь . Затем вы можете передать данные из запроса в шаблон в виде словаря.

Кроме того, почему ваша JournalEntry модель имеет только одно поле? Можем ли мы просто объединить JournalEntry и LineItem во что-то вроде этого:

class LineItem(models.Model):
    date = models.DateField(null=True, blank=False)
    # journal_entry = models.ForeignKey(JournalEntry, on_delete=models.PROTECT)
    # this journal_entry fk wouldn't work so you'd have to replace it with something else
    ledger = models.ForeignKey(Ledger, on_delete=models.PROTECT)
    description = models.CharField(max_length=255, null=True, blank=True)
    cr = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
    dr = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)

Тогда для представления я напишу что-то вроде этого:

views.py

from .models import LineItem

def journalentries_show_all(request):
    context = LineItem.objects.filter(arbitrary_criteria = True) # choose your own criteria here

    return render(request, 'journal/journalentries_show_all.html', context)

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

0 голосов
/ 23 декабря

Возможно, я вас неправильно понял, но почему бы вам просто не отправить свой квест JournalEntry в свой шаблон?

def journalentries_show_all(request):
    context['journal_entries'] = JournalEntry.objects.all()
    ....

Затем вы можете отобразить то, что вы хотите в своем шаблоне

{% for entry in journal_entries %}
{{ entry.id }} {{ entry.date }}
{% for item in entry.lineitem_set.all|slice:"2" %}
{{ item.ledger.name }}
{% endfor %}
{% endfor %}
0 голосов
/ 23 декабря

Базовых итераций Python достаточно для того, что вам нужно

results = []
for entry in journal_entries:
    results.append(entry.lineitem_set.all()[2]

Просто этот список results должен сделать это в context. .all()[2] отправит запрос с лимитом на первые 2 элемента. Вы получите все предметы. Выберите то, что вам нужно отображать в шаблоне, а не в представлениях. Чтобы сделать вашу жизнь проще, вы также можете определить атрибут related_name для внешних ключей и использовать желаемое имя вместо сгенерированного *_set

...