开发者

Django: return several views from a single URL without redirection

开发者 https://www.devze.com 2023-03-08 01:10 出处:网络
With function based Django view it was simple to switch between several different views based on a condition, e.g. something like:

With function based Django view it was simple to switch between several different views based on a condition, e.g. something like:

def base_view(request):
    if some_condition():
        return 开发者_如何学运维foo_view(request)
    else:
        return bar_view(request)

I can't find a simple way to do the same with the new class-based generic views. The only way I can think of is to redisrect, which I would like to avoid for various reasons:

def base_view(request):
    if some_condition():
        return redirect(reverse("name_of_url_to_class-based_view_foo"))
    else:
        return redirect("/url_to_class-based_view_bar/")

Any suggestions?


This is equivalent to your example with class based views.

class FooView(View):
    pass

class BarView(View):
    pass

class BaseView(View):
    # staticmethod to avoid adding 'self' to the arguments
    foo_view = staticmethod(FooView.as_view())
    bar_view = staticmethod(BarView.as_view())

    def dispatch(self, request, *args, **kwargs):
        if some_condition():
            return self.foo_view(request, *args, **kwargs)
        else:
            return self.bar_view(request, *args, **kwargs)


Even though the Django docs do say that the function based generic views are now deprecated I think the only reason to switch would be if you're writing less code.

If you're still set on switching, you'll want to first identify which class based views or mixins are most appropriate (single object, multiple objects, date based, forms, etc.). If the conditional was used to select a function that returns different context data / template to provide to the view, you can push the conditional down into an overridden get_queryset|get_context_data|get_object|get_template_names depending on your use case.

For example,

def get_context_data(self, **kwargs):
    # Call the base implementation first to get a context
    context = super(BaseView, self).get_context_data(**kwargs)
    # Add in the publisher
    if some_condition():
        context['some_data'] = ...
    else:
        context['other_data'] = ...
    return context

If all else fails and you're still determined to have class based views, you could probably also override get(self, request, *args, **kwargs) and do the switching there to the appropriate method. The detailed docs are getting better but I've still found myself poking through the source code to figure out how to accomplish what I want.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号