Django DetailView без перенаправления 404 - PullRequest
0 голосов
/ 10 марта 2020

У меня есть небольшое новостное приложение с классом DetailView, например:

class DetailView(LoginRequiredMixin,generic.DetailView):
    model = NewsItem
    template_name = 'news/detail.html'

    def get_object(self):
        obj = super().get_object()

        if self.request.user.is_superuser or obj.published:
            return obj

и конфиг urls.py, например:

urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:itemId>/publish', views.publish, name='publish'),
]

Теперь, когда я передаю недействительный Идентификатор подробного представления, который он автоматически перенаправляет на 404. Я хотел знать, возможно ли вместо этого просто передать пустой объект в DetailView. Затем шаблон будет обрабатывать 404. Сам по себе.

Кроме того: Даже несмотря на то, что он работает до сих пор, я чувствую, что способ обработки требований к разрешениям (переопределение метода get_object) не является правильным способом / Django способ делать вещи

Решение: я изменил переопределение get_object следующим образом:

class DetailView(LoginRequiredMixin,generic.DetailView):
    model = NewsItem
    template_name = 'news/detail.html'

    def get_object(self):
        queryset = self.get_queryset()
        pk = self.kwargs.get(self.pk_url_kwarg)

        if pk is not None:
            queryset = queryset.filter(pk=pk)
        else:
            raise AttributeError("No article id provided")

        try:
            return queryset.get()
        except queryset.model.DoesNotExist:
            return None

это в основном тот же метод get_object, что и оригинал, только без проверьте значение slug, и если вызов queryset.get() перехватывает исключение queryset.model.DoesNotExist, он возвращает None

1 Ответ

1 голос
/ 10 марта 2020

Классические CBV, , как обычно, проясняют все.

Если вам не нравится 404 для плохого идентификатора, вам нужно переопределить get_object в большей степени, чем вы сделали, потому что это вызывает исключение Http404 для плохого идентификатора. Код, о котором идет речь:

 try:
    # Get the single item from the filtered queryset
    obj = queryset.get()
 except queryset.model.DoesNotExist:
    raise Http404(_("No %(verbose_name)s found matching the query") %
                  {'verbose_name': queryset.model._meta.verbose_name})
 return obj

Вы можете поймать исключение, когда позвоните obj = super().get_object()

try:
    obj = super().get_object()
except Http404:
    obj = NewsItem( ... ) # a dummy empty NewsItem

Или вы можете просто вообще не вызывать super () и предоставить свой собственный код для возврата соответствующего объекта. Пустой объект может существовать в базе данных как особый объект (лучше всего созданный путем переноса данных), или он может (как здесь) создаваться на лету и никогда не сохраняться. В любом случае он будет иметь некоторые отличительные характеристики c, которые шаблон может легко проверить.

...