【问题标题】:Django: Generic detail view must be called with either an object pk or a slugDjango:必须使用对象 pk 或 slug 调用通用详细视图
【发布时间】:2014-06-02 23:41:25
【问题描述】:

提交与此视图关联的表单时出现此错误。不确定到底是什么问题,考虑到我有一个结构非常相似的表单并且它工作正常。

#views.py
class Facture_Creer(SuccessMessageMixin, CreateView):
    model = Facture
    template_name = "facturation/nouvelle_facture.html"
    form_class= FormulaireFacture

    # permet de retourner a l'URL pointant vers le membre modifie
    def get_success_url(self):
        return reverse_lazy('facture_consulter',kwargs={'pk': self.get_object().id})

class Facture_Update(SuccessMessageMixin, UpdateView):
    model = Facture
    template_name = "facturation/nouvelle_facture.html"
    form_class= FormulaireFacture
    success_message = "Facture mise à jour avec succes"

    # permet de retourner a l'URL pointant vers le membre modifie
    def get_success_url(self):
        return reverse_lazy('facture_consulter',kwargs={'pk': self.get_object().id})

#urls.py
urlpatterns = patterns('',
    url(r'^$', TemplateView.as_view(template_name="facturation/index.html")),
    url(r'^facture/$', FactureView.as_view()),
    url(r'^facture/(?P<id>\d+)', FactureView.as_view(), name='facture_consulter'),
    url(r'^facture/ajouter/$', Facture_Creer.as_view(), name='facture_creer'),
    url(r'^facture/modifier/(?P<pk>\d+)/$', Facture_Update.as_view(), name='facture_update'),
    url(r'^membre/ajouter/$', Membre_Creer.as_view(), name='membre_creer'),
    url(r'^membre/modifier/(?P<pk>\d+)/$', Membre_Update.as_view(), name='membre_update'),
    #url(r'membre/(?P<pk>\d+)/supprimer/$', Membre_Supp.as_view(), name='membre_delete')
)

urlpatterns += staticfiles_urlpatterns()

【问题讨论】:

  • 只是附注:永远不要永远,永远,永远,如本例中所做的那样,使用非英语单词表示视图。 (Member、Facture、Creer 等)这使得你的代码库对于说其他语言的人(在这种情况下比法语)更难使用,而且看起来很丑。

标签: python django


【解决方案1】:

您需要传递一个对象标识符(pk 或 slug),以便您的视图知道它们正在操作哪个对象。

仅以您的urls.py 为例:

url(r'^facture/ajouter/$', Facture_Creer.as_view(), name='facture_creer'),
url(r'^facture/modifier/(?P<pk>\d+)/$', Facture_Update.as_view(), name='facture_update'),

看看第二个怎么有(?P&lt;pk&gt;\d+)/?那就是将 pk 传递给 UpdateView,以便它知道要使用哪个对象。因此,如果您转到facture/modifier/5/,则 UpdateView 将修改 pk 为 5 的对象。

如果您不想在 url 中传递 pk 或 slug,则需要覆盖 get_object() 方法并以另一种方式获取对象。网址here.

【讨论】:

  • 有道理。问题似乎出在 def get_success_url(self): return reverse_lazy('facture_consulter',kwargs={'pk': self.get_object().id}) 部分。你知道从 CreateView 中获取保存对象的方法吗?
  • 没关系,找到了。感谢您快速回答我的问题!
  • 它必须始终是“pk”还是也可以是不同的名称?
  • @user763410 可以,但您需要覆盖您正在使用的视图上的get_object() 方法。文档here
  • 请注意,我必须重新启动 Django 的开发网络服务器才能使其正常工作
【解决方案2】:

正如 Alex 建议的那样:对于默认 Django 行为,您必须在 url 模式中使用“pk”。

如果您希望将主键“pk”的对象标识符更改为不同的名称,您可以定义pk_url_kwarg。这从 Django 1.4 开始可用。

【讨论】:

  • 这是 Alex 的一个更好的答案。
【解决方案3】:

大家好,我使用了新的 path() 函数,这是我的工作示例,我相信它会有所帮助:

views.py:

from django.views.generic.detail import DetailView

class ContentAmpView(DetailView):

    model = Content
    template_name = 'content_amp.html'  # Defaults to content_detail.html

urls.py:

from django.urls import path

from .views import ContentAmpView

# My pk is a string so using a slug converter here intead of int
urlpatterns = [
    path('<slug:pk>/amp', ContentAmpView.as_view(), name='content-amp'),
]

模板/content_amp.html

<!doctype html>
<html amp lang="en">
<head>
    <meta charset="utf-8">
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <title>Hello, AMPs</title>
    <link rel="canonical" href="http://example.ampproject.org/article-metadata.html">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <script type="application/ld+json">
      {
        "@context": "http://schema.org",
        "@type": "NewsArticle",
        "headline": "Open-source framework for publishing content",
        "datePublished": "2015-10-07T12:02:41Z",
        "image": [
          "logo.jpg"
        ]
      }

    </script>
    <style amp-boilerplate>
        body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}
    </style>
    <noscript>
        <style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}
        </style>
    </noscript>
</head>
<body>
<h1>Welcome to AMP - {{ object.pk }}</h1>
<p>{{ object.titles.main }}</p>
<p>Reporter: {{ object.reporter }}</p>
<p>Date: {{ object.created_at|date }}</p>
</body>
</html>

还要注意,在我的settings.py 中,在TEMPLATES 下,我有'APP_DIRS': True。更多关于路径here。

【讨论】:

    【解决方案4】:

    就像 Robin 所说,如果您想要自定义 pk 名称,可以使用 pk_url_kwarg。

    但另外,问题必须使用对象 pk 或 slug 调用通用详细视图也会在 slug 中引发。

    因此,如果您想创建 自定义 slug 字段(无需使用 pk 或 slug 名称)。您可以在 DetailView 类中覆盖 slug_field 和 slug_url_kwarg。

    如果您希望 url 作为 Slug 字段,这只是另一个示例。

    models.py

    class Post(models.Model):
        title = models.CharField(max_length=255)
        url = models.SlugField()
        body = models.TextField()
        image = models.ImageField(upload_to='blog/', blank=True, null=True)
    

    views.py

    class ListPost(ListView):
        model = Post
        template_name = 'blog/list.html'
        paginate_by = 2
        context_object_name = 'posts'
    
    class DetailPost(DetailView):
        model = Post
        template_name = 'blog/detail.html'
        slug_field = 'url'
        slug_url_kwarg = 'url'
    

    urls.py

    urlpatterns = [
        path('', ListPost.as_view()),
        path('<slug:url>/', DetailPost.as_view()),
    ]
    

    【讨论】:

      【解决方案5】:

      我使用的是 Django 版本 2.2.12,

      这只是另一个对我来说很好用的例子:

      models.py

      from django.db import models
      
      class Book(models.Model):
          title = models.CharField(max_length=256)
          author = models.CharField(max_length=256)
          pages = models.IntegerField()
          price = models.FloatField()
      

      views.py

      from django.views.generic import ListView,DetailView
      from testapp.models import Book
      
      class BookListView(ListView):
          model=Book
      
      class BookDetailView(DetailView):
          model=Book
      

      urls.py

      from django.contrib import admin
      from django.urls import path
      from testapp import views
      
      urlpatterns = [
          path('admin/', admin.site.urls),
          path('', views.BookListView.as_view()),
          path('<slug:pk>/', views.BookDetailView.as_view()),
      ]
      

      【讨论】:

        【解决方案6】:

        更新:在 django 2.0.2 中,将其更改为:

        url(r'^facture/modifier/<int:pk>/$', Facture_Update.as_view(), name='facture_update'),
        

        【讨论】:

        • 这行不通。 url() 函数的行为在 Django 2.x 中没有改变,并且仍然像以前一样工作。您可能正在考虑新的path() 函数。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多