Chcę przekierować do adresu URL, jeśli obiekt członka grupy nie istnieje, ale pokazuje ten błąd:

TypeError: kontekst musi być dyktą, a nie str.

Oto mój pogląd:

class GroupDetail(DetailView):

template_name = "group_detail.html"
model = Group

def get_context_data(self, **kwargs):
    context = super(GroupDetail, self).get_context_data(**kwargs)
    # Code
    try:
        group_member = GroupMember.objects.get(member=volunteer, group=group)
        context['group_member'] = group_member
        # Code
        return context
    except:
        return reverse('users:home')

Staram się przekierować i odwrócić_lazy, ale pokazuje ten sam błąd i próbowałem

reverse('users:home', {}), reverse('users:home', kwargs={}) 

I

reverse('users:home', kwargs=None)
1
Vinsmoke Mau 27 czerwiec 2017, 01:06

3 odpowiedzi

Najlepsza odpowiedź

Po pierwsze, zawsze jest nie tak, ponieważ nie ma członka ani ochotnika w lokalnych danych.

Po drugie, właściwy sposób na zrobienie tego jest zwrócenie żadnego ani pustego dict i nadpisania render_to_response:

from django.views.generic import DetailView
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.contrib.messages import warning

class GroupDetail(DetailView):
    def get_context_data(self, **kwargs):
        volunteer = self.get_volunteer()  # Or something like that
        group = self.get_group()  # Or something like that
        try:
            group_member = GroupMember.objects.get(
                member=volunteer, group=group
            )
            return super(GroupDetail, self).get_context_data(
                group_member=group_member, **kwargs
            )
        except GroupMember.DoesNotExist:
            return None
            # All other exceptions should really be raised as they are
            # actual application errors.

    def render_to_response(self, context, **response_kwargs):
        if context is None:
            warning(self.request, 'You are groupless! Peer pressure incoming.')
            return HttpResponseRedirect(reverse("users:home"))
        return super(GroupDetail, self).render_to_response(
            context, **response_kwargs
        )

W ten sposób w pełni wykorzystujesz interfejs API i może rozciągać się i zastąpić potrzebną potrzebę, dlatego zaprojektowano widoki na klasie.

2
Melvyn 26 czerwiec 2017, 23:02

get_context_data() Metoda musi zwrócić słownik reprezentujący kontekst szablonu, a nie łańcuchy URL. Aby przekierować wyjątek, możesz zastąpić metodę get() zamiast tego:

from django.http HttpResponseRedirect

class GroupDetail(DetailView):
    template_name = "group_detail.html"
    model = Group

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        try:                
            # your code            
            return self.render_to_response(context)
        except:
            return HttpResponseRedirect(reverse("users:home"))

Możesz sprawdzić kod źródłowy DetailView i jego przodków Oto.

0
Eugene Yarmash 27 czerwiec 2017, 14:13

Jeśli kod zgłasza wyjątek, uruchomi return reverse('users:home'), który daje typ danych str.

Jednak DJANCO Docs stwierdza wyraźnie:

get_context_data(**kwargs)

Zwraca słownik reprezentujący kontekst szablonu.

Musisz zrobić coś takiego:

def get_context_data(self, **kwargs):
  context = super(GroupDetail, self).get_context_data(**kwargs)
  # Code
  try:
      group_member = GroupMember.objects.get(member=volunteer,group=group)
      context['group_member'] = group_member
      # Code
  finally:
      return context

Albo możesz to zrobić, jeśli chcesz przekierować:

def get_context_data(self, **kwargs):
  context = super(GroupDetail, self).get_context_data(**kwargs)
  # Code
  try:
      group_member = GroupMember.objects.get(member=volunteer,group=group)
      context['group_member'] = group_member
      # Code
  except:
      return HttpResponseRedirect(reverse('users:home'))
0
an0o0nym 26 czerwiec 2017, 22:24