具有两个 ForeignKey 关系的 CreateView 时出现 KeyError

KeyError while CreateView with two ForeignKey relationships

型号

我在 Journals 应用程序中创建了两个模型。一种模型用于日记 (to_journal),另一种用于日记条目 (to_journal_entry)。 to_journal 模型通过 "journal user" 与用户模型相关,to_journal_entry 模型通过 journal_name.

to_journal 相关

看起来像这样:

models.py

class to_journal(models.Model):
    journal_name = models.CharField(max_length = 40)
    slug = AutoSlugField(populate_from='journal_name')
    date_created = models.DateTimeField(auto_now_add=True)
    journal_user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)

    def __str__(self):
        return str(self.journal_user) + " " + self.name

    def get_absolute_url(self):
        return reverse('to-journals')


class to_journal_entry(models.Model):
    body = models.TextField()
    entry_date = models.DateTimeField(auto_now_add=True)
    journal_name = models.ForeignKey(to_journal, on_delete=models.CASCADE,)
    journal_user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)

    def __str__(self):
        return str(self.journal_name) + " " + str(self.entry_date)

    def get_absolute_url(self):
         return reverse('to_journals', args=[str(self.slug)])

观看次数

我已经成功地为 to_journal 设置了 CreateView。在相关页面上,我输入我想要给我的期刊的期刊名称,按 "Add" 按钮,页面更新,显示更新的期刊列表。这是通过下面的 CreateToJournal 视图实现的。

我想为日记条目实现同样的目标。一旦我 "inside" 任何给定的期刊,我希望能够输入文本并且我希望页面重新加载并仅更新该特定期刊的条目列表。

错误

我在此处按下添加按钮后,出现以下错误:

对于这一行:

我 运行 遇到了关于这一步的问题。当我写 form_valid:

def form_valid(self, form):
        current_journal_id = to_journal.objects.get(id=self.kwargs['id'])
        form.instance.journal_user = self.request.user
        form.instance.journal_name = current_journal_id.journal_name
        return super(ToJournalEntriesList, self).form_valid(form)

我通过说 form.instance.journal_user = self.request.user 来指定用户,通过说 form.instance.journal_name = to_journal.objects.get(id=self.kwargs['id']).journal_name 或类似的东西来指定当前期刊(下面是我尝试过的其他事情的列表)。

views.py

class CreateToJournal(LoginRequiredMixin, CreateView):
    model = to_journal
    template_name = 'to_journals/to_journal_list.html'
    fields = ('journal_name',)

    def form_valid(self, form):
        form.instance.journal_user = self.request.user
        return super(CreateToJournal, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(CreateToJournal, self).get_context_data(**kwargs)
        context['to_journals'] = to_journal.objects.filter(journal_user=self.request.user)
        return context


class ToJournalEntriesList(LoginRequiredMixin, CreateView):
    model = to_journal_entry
    template_name = 'to_journals/to_journal_entries_list.html'
    fields = ('body',)
    success_url = reverse_lazy('to-journal-entries')

def form_valid(self, form):
    # line below should get the current object (Parent Journal)
    current_journal_id = to_journal.objects.get(id=self.kwargs['id'])

    form.instance.journal_user = self.request.user

    # Line below should set the journal name for the form as the journal name of the object I got earlier.
    form.instance.journal_name = current_journal_id.journal_name
    return super(ToJournalEntriesList, self).form_valid(form)

def get_context_data(self, **kwargs):
    context = super(ToJournalEntriesList, self).get_context_data(**kwargs)
    context['to_journal_entries'] = to_journal.objects.filter(journal_user=self.request.user)
    context['to_journal_entries'] = to_journal_entry.objects.filter(pk=self.kwargs.get('pk'))
    return context

我试过了

这些给我 DoesNotExist 错误,这很奇怪,因为我位于它应该自动拾取的日志中。

数据库

只想展示我正在使用的数据库。它有一个 id 列,因此假设应该可以正常工作:

模板

<h1 class="green-button" onclick="inputJournal(); this.onclick=null;">Add Entry</h1>
  <div id="new-journal">
     <form class="" id="myForm" action="" method="post">
       {% csrf_token %}
       {{ form }}
       <button type="submit" id="add-button">Add</button>
     </form>
  </div>

抱歉久了post!如果需要任何额外信息,我将很乐意提供更多信息。非常感谢大家的观看。

最好的, 拉苏尔

编辑

网址

to_journals/urls.py

from django.urls import path
from .views import CreateToJournal, ToJournalEntriesList


urlpatterns = [
    path('', CreateToJournal.as_view(), name='to-journals'),
    path('<slug:slug>', ToJournalEntriesList.as_view(), name='to-journal-entries'),
]

root urls.py

urlpatterns = [
    path('admin/', admin.site.urls),

    path('users/', include('users.urls')),
    path('users/', include('django.contrib.auth.urls')),

    path('', include('pages.urls')),

    path('to-journals/', include('to_journals.urls')),

] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \
+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

编辑 2

在建议的答案之后,这是新的错误。

编辑 3 - 工作修复(感谢 Daniel Roseman)

def form_valid(self, form):
        current_journal = to_journal.objects.get(journal_user=self.request.user, slug=self.kwargs['slug'])
        form.instance.journal_user = self.request.user
        form.instance.journal_name = current_journal
        return super(ToJournalEntriesList, self).form_valid(form)

更改是在 kwargs 调用中(slug 而不是 id)和命名约定 current_journal 而不是 current_journal_id

self.kwargs 包含在该视图的 URL 中传递的命名参数。正如我们从模式中看到的那样,在 URL 中传递的唯一 kwarg 是 slug,它清楚地引用了日志的 slug 字段;在屏幕截图的情况下,sleep。这就是我们需要在方法中使用的值和要查找的字段:

current_journal_id = to_journal.objects.get(slug=self.kwargs['slug'])

但是请为您的对象命名以反映它们的实际含义。上面我们得到的是实际的日志,而不是 id;称之为 current_journal。同样,从入口指向到日志的外键,而不是日志名称;你应该将 FK 命名为 to_journal(虽然我也不明白为什么你的模型首先被称为那个,而不仅仅是 Journal)。

编辑

你的第二个问题直接是由你混乱的命名约定引起的。应该是:

form.instance.journal_name = current_journal_id

(不是 current_journal_id.journal_name)。如果您正确命名,它将是

form.instance.journal = current_journal

这样会更清晰,更不容易出错。