質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

Django(Python)にて関連テーブルの追加用テンプレートに親要素の引数を渡せない

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 181

RyoheiM

score 14

Djangoにて出版業務の入稿システムを作っています。

問題の概要

本のタイトル、部、章、節、項という親要素(model:Bunch)があり、その子要素(model:Bunchrelate)としてページとページタイトルが紐づきます。子要素である、ページ、ページタイトルを追加するテンプレートをレンダーする部分で"NoReverseMatch"エラーが起きており、それを解決したいというのが主題です。おそらく原因は子要素を追加する画面で親要素のpkが引数としてテンプレートに渡っていないことだと予想しています。

エラーの内容

bunchrelatelistにて一覧表示する画面でbunchrelateaddをレンダーしようとすると以下のようなエラーが発生します。
イメージ説明

関連情報

models.py

Bunch=書目、部、章、節、項といった親要素
Bunchrelate=Bunchに紐づく、ページ番号、ページタイトルといった子要素

from django.db import models
from django.utils import timezone


class Bunch(models.Model):
    categoryname = models.CharField(max_length=50, blank=False, null=False)
    chaptername = models.CharField(max_length=50, blank=False, null=False)
    sectionname = models.CharField(max_length=50, blank=False, null=False)
    termname = models.CharField(max_length=50, blank=False, null=False)
    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.categoryname


class Bunchrelate(models.Model):
    relatepages = models.CharField(
        max_length=7, unique=True, blank=False, null=False)
    slideheader = models.CharField(max_length=50, blank=False, null=False)
    bunch = models.ForeignKey(Bunch, on_delete=models.PROTECT)
    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.relatepages

urls.py

from django.urls import path
from . import views

app_name = 'factors'

urlpatterns = [
    path('bunchlist/', views.bunchlist, name='bunchlist'),
    path('bunchlist/bunchadd/', views.bunchadd, name='bunchadd'),
    path('bunchlist/<int:pk>/bunchedit/', views.bunchedit, name='bunchedit'),
    path('bunchlist/<int:pk>/', views.bunchdelete, name='bunchdelete'),
    path('bunchlist/<int:pk>/bunchrelateadd/',
         views.bunchrelateadd, name='bunchrelateadd'),
    path('bunchlist/<int:pk>/bunchrelatelist/',
         views.bunchrelatelist, name='bunchrelatelist'),
]

views.py

from django.shortcuts import render, redirect, get_list_or_404, get_object_or_404
from django.http import HttpResponse
from .models import Bunch, Bunchrelate, Details
from .forms import BunchForm, BunchrelateForm
from django.utils import timezone
from django.forms import inlineformset_factory
from django.db.models import ProtectedError
from django.contrib import messages


def bunchlist(request):
    ctx = {
        'bunches': Bunch.objects.all(),
    }
    return render(request, 'factors/bunchlist.html', ctx)


def bunchadd(request):
    if request.method == "POST":
        form = BunchForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.save()
            return redirect('factors:bunchlist')
    else:
        form = BunchForm()
    return render(request, 'factors/bunchadd.html', {'form': form})

    # Create your views here.


def bunchdelete(request, pk):
    bunch = get_object_or_404(Bunch, pk=pk)

    if request.method == 'POST':

        try:
            bunch.delete()
        except ProtectedError:
            messages.error(request, '紐付いている見開きページ情報等を削除してからでないと消せません')

    return redirect('factors:bunchlist')


def bunchedit(request, pk):
    bunch = get_object_or_404(Bunch, pk=pk)
    if request.method == "POST":
        form = BunchForm(request.POST, instance=bunch)
        if form.is_valid():
            bunch = form.save(commit=False)
            bunch.save()
            return redirect('factors:bunchlist')
    else:
        form = BunchForm(instance=bunch)
    return render(request, 'factors/bunchedit.html', {'form': form})


def bunchrelateadd(request, pk):
    if request.method == "POST":
        form = BunchrelateForm(request.POST)
        if form.is_valid():
            bunchrelate = form.save(commit=False)
            bunchid = Bunch.objects.get(id=pk)
            bunchrelate.bunch = bunchid
            bunchrelate.save()
            return redirect('factors:bunchrelatelist', pk=bunchrelate.bunch.pk)
    else:
        form = BunchrelateForm()
    return render(request, 'factors/bunchrelateadd.html', {'form': form})


def bunchrelatelist(request, pk):
    ctx = {
        'bunchrelates': Bunchrelate.objects.filter(bunch_id=pk),
    }
    return render(request, 'factors/bunchrelatelist.html', ctx)

bunchrelatelist.html

{% extends 'factors/base.html' %} {% block content %}
<h2>紙面情報(部・章・節・項タイトル)</h2>
<table class="table">
  <thead class="thead-dark">
    <tr>
      <th scope="col">見開きページ</th>
      <th scope="col">スライドタイトル</th>
    </tr>
  </thead>
  <tbody>
    {% for bunchrelate in bunchrelates %}
    <tr>
      <td>{{ bunchrelate.relatepages }}</td>
      <td>{{ bunchrelate.slideheader }}</td>
    </tr>
    <a href="{% url 'factors:bunchrelateadd' pk=bunchrelate.bunch.pk%}"
      >項目の追加</a
    >
    {% endfor %}
  </tbody>
</table>
<a href="{% url 'factors:bunchlist'%}">一覧へ戻る</a>
{% endblock %}

bunchrelateadd.html

{% extends 'factors/base.html' %} {% block content %}
<h2>見開きページ、タイトル</h2>

<form method="POST" action="">
  <table border="1">
    {% csrf_token %} {{ form.as_table }}
  </table>
  <button type="submit" class="save btn btn-default">登録</button>
</form>

</form>
<a href="{% url 'factors:bunchrelatelist'%}">見開き一覧へ戻る</a>
{% endblock %}

3日程悩んでいますが解決にいたりません。
もしかしたら私の仮設が間違っているのかもしれないです。
アドバイスいただけるととても嬉しいです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

下記で、bunchrelateというオブジェクトが存在しないからだと思います。
下記の前のforbunchrelateはスコープを外れています。

<a href="{% url 'factors:bunchrelateadd' pk=bunchrelate.bunch.pk%}">項目の追加</a>

当該ビューはBunchに関連するBunchrelateモデルインスタンスのリストを表示するビューであるため、
Bunchrelateに親のBunchモデルインスタンスをコンテキストで渡して、下記のようにするのはどうでしょうか。

from django.shortcuts get_object_or_404
from .models. import Bunch, Bunchrelate
def bunchrelatelist(request, pk):
    ctx = {
        'bunch': get_object_or_404(Bunch, pk=pk)
        'bunchrelates': Bunchrelate.objects.filter(bunch_id=pk),
    }
    return render(request, 'factors/bunchrelatelist.html', ctx)
<a href="{% url 'factors:bunchrelateadd' pk=bunch.pk%}">項目の追加</a>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る