我应该如何在函数视图中调用基于类的通用视图

Posted

技术标签:

【中文标题】我应该如何在函数视图中调用基于类的通用视图【英文标题】:How should i call class based generic view in function view 【发布时间】:2017-12-31 16:55:13 【问题描述】:

我想在函数视图中调用基于类的索引视图 我在登录函数视图中渲染索引模板,但是当我在索引模板中添加一个额外的上下文时,我从函数视图'它只渲染了额外的上下文,而不是已经由基于类的索引视图渲染的上下文。

所以我想我是否可以从函数中调用基于类的索引视图,以便我向基于类的视图添加额外的上下文并同时渲染它。

简而言之,我想从函数视图中添加额外的上下文并渲染它。

这是我的基于类的通用视图,用于在索引模板中列出对象。

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    title = 'hello'
    num_visit = 'a'
    context_object_name = 'question_list'

    def get_queryset(self):
        """Return the last five published questions."""
           return Question.objects.filter(pub_date__lte=timezone.now()).order_by('-pub_date')[:5]

这是我的登录视图,它与基于类的索引视图所呈现的模板相同

def login_view(request):
    user = authenticate(request,username=request.POST['username'],password=request.POST['password'])
    if user is not None:
        login(request, user)
        return redirect('polls:index')
    return render_to_response('polls/index.html', 'error_message': 'wrong credentials')

.................................................. ..

现在我可以登录索引模板,但查看添加的代码上下文不起作用,也许它起作用了,但我认为它确实与默认对象列表上下文混淆了。

class IndexView(generic.ListView):
template_name = 'polls/index.html'
title = 'sdasd'
num_visit = 'a'
context_object_name = 'question_list'
error_message = None

def get_queryset(self):
    """Return the last five published questions."""
    return Question.objects.filter(pub_date__lte=timezone.now()).order_by('-pub_date')[:5]

def post(self, request, **kwargs):
    user = authenticate(request, username=request.POST['username'], password=request.POST['password'])
    if user is not None:
        login(request, user)
        return redirect('polls:index')
    error_message = 'i love jesus'
    context = self.get_context_data(request, error_message, **kwargs)
    return render(request, 'polls:index', context)



def get_context_data(self, *args, **kwargs):
    context = super(IndexView, self).get_context_data(**kwargs)
    context['error_message'] = self.args
    return context

模板代码....... 无法添加模板代码'这很复杂我在这里添加 https://codeshare.io/5zXYJb

引用错误https://ibb.co/jdA7Ek

【问题讨论】:

能发一些代码吗? 你永远不应该从另一个视图调用一个视图。如果您在两个视图中有公共代码,请将其移至视图之外的实用程序方法(创建 utils.py 文件)或将其移至模型中。您应该尝试将尽可能多的逻辑向下移动到您的模型中。 @IanKirkpatrick 我认为没有其他方法,因为我想在使用列表视图的同一索引页面中添加登录页面......我不想使用登录查看不同模板中的不同网址'我希望你明白这就是我想要挑战自我的方式。 @IanKirkpatrick 您的意思是作为模型登录以便我可以在任何视图中使用? 所以您想要在您的索引页面上有一个登录部分,而不是一个专门用于登录的单独页面?有点像亚马逊在每个页面顶部的快速登录? 【参考方案1】:

您不应该将逻辑从一个视图调用到另一个视图。创建登录逻辑。你没有发布任何代码,所以我不太确定你的程序是如何工作的,但你可以这样做:

在forms.py中

class MyLoginForm(Form):
    username = forms.TextField(...)
    password = forms.PasswordField(...)

在 utils.py 中

def login(request, user_name, password):
    user = authenticate(request, username=user_name, password=password)
    if user is not None:
        login(request, user)
        return True
    return False

def index_context(...):
    context = 
    # do context stuff here
    return context

在views.py中

class Index(View):
    def post(self, request, *args, **kwargs):
        # The logging_in part is optional but it's used to know when a post request is a login post or for something else. Just add a hidden field in your login form that has this name and a value of True.
        if request.POST.get("logging_in", False):
            authenticated = utils.login(request, request.POST.get("username", ""), request.POST.get("password", ""))

            if authenticated:
                # refresh the page
            else:
                # refresh the page with error
        else:
            # do other POST actions.

    def get(self, request, *args, **kwargs):
        # add a username and password form to context along with whatever other context you need.
        context = utils.index_context(...)
        context["login_form"] = MyLoginForm
        return render(request, "index.html", context)

def login_view(request):
    # Used if you also want a separate login page too.
    if request.method == "POST":
        loggedin = utils.login(request, request.POST.get("username", ""), request.POST.get("password", ""))
        if loggedin:
            return redirect('polls:login')
        return render_to_response('polls/login.html', 'error_message': 'wrong credentials')
    else:
        # render template with username and password field
        context = 
        context["login_form"] = MyLoginForm
        return render(request, "login.html", context)

您也可以只拥有一个 API 视图,该视图仅用于登录内容并让 ajax 调用此视图。无论哪种方式,登录的实际逻辑都应该在一个单独的全局函数中。

【讨论】:

即使我使用你的代码,它看起来就像我的代码做同样的事情............它假设如何从索引视图呈现数据,这是对象的列表.......我想要的是从我的简单登录视图添加额外的上下文到通用列表视图并从登录视图渲染两者,以便两个上下文同时在索引模板中呈现。 我刚刚编辑了答案。注意 utils.py 中的新方法 我在基于类的列表视图中使用了 post 方法'它工作正常,但我想做的第二件事是.....在我的基于类的列表视图中'有一些对象列表是由 django 自动呈现,添加额外上下文的唯一方法是使用 get_context_method。我所做的是我在 post 方法中使用了 get context 方法并添加了一个新变量然后我渲染,我得到的错误是 'IndexView' 对象没有属性 'object_list' 看起来就像我在 post 方法中添加额外的上下文和渲染上下文时一样抛出错误。 我可以看到你的整个视图吗?两种观点? 如何在此处添加代码?它不会让我添加超过 15 个字符的

以上是关于我应该如何在函数视图中调用基于类的通用视图的主要内容,如果未能解决你的问题,请参考以下文章

手动调用基于类的通用视图

如何在基于类的通用视图中访问 RequestContext?

Django:渲染视图后如何更新模型?

Django 基于类的通用视图和身份验证

基于 Django 类的通用视图和 ModelForms

如何在基于类的视图中编写自己的方法并在 url 中调用方法