Django: Generic detail view must be called with either an object pk or a slug

You need to pass an object identifier (pk or slug) so your views know which object they're operating on.

Just to take an example from your 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'),

See how the second one has (?P<pk>\d+)/? That is passing a pk to the UpdateView so it knows which object to use. Thus if you go to facture/modifier/5/, then the UpdateView will modify object with pk of 5.

If you don't want to pass a pk or slug in your url, you'll need to override the get_object() method and get your object another way. Url here.


As Alex suggests: for default Django behaviour you have to use "pk" in your url pattern.

If you wish to change the object identifier for the primary key "pk" to a different name, you can define pk_url_kwarg. This is available since Django 1.4.


Hey all I used the new path() function and here is my working example that I'm sure will help:

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'),
]

templates/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>

Also note that in my settings.py, under TEMPLATES, I have 'APP_DIRS': True. More on path here.

Tags:

Python

Django