【问题标题】:Django - Using context_processorDjango - 使用 context_processor
【发布时间】:2011-09-23 09:05:42
【问题描述】:

我想在我的网页中随处放置一个登录表单,所以我添加了一个context_processor 并将其包含在 base.html 文件中。现在的问题是我看不到表格。

这是我的 context_processors.py:

def global_login_form(request):
    if request.method == 'POST':
        formLogin = LoginForm(data=request.POST)
        if formLogin.is_valid():
            from django.contrib.auth import login
            login(request, formLogin.get_user())
            ...
    else:
        formLogin = LoginForm()

    return {'formLogin': formLogin}

这是我在 base.html 中尝试调用表单的不同 html:

<form action="/myapp/login/" method="post">
{% csrf_token %}
{{global_login_form}}
</form>

<form action="/myapp/login/" method="post">
{% csrf_token %}
{{global_login_form.as_p}}
</form>

<form action="/myapp/login/" method="post">
{% csrf_token %}
{{request.formLogin}}
</form>

我第一次加载页面时,context_process 返回{'formLogin': formLogin}(因为formLoginLoginForm())但是在检查 html 时我看不到表单。它不存在...但我可以看到 csrf_token 所以我认为我没有正确调用上下文。

只是大小写(可能顺序不对),这里是settings.py:

TEMPLATE_CONTEXT_PROCESSORS = (
    "myapp.context_processors.global_login_form",
    "django.core.context_processors.request",
    "django.contrib.auth.context_processors.auth",
)

有什么想法吗?

【问题讨论】:

  • 当您说“我的页面上的任何地方”时,您实际上是指“我的网站上的任何地方”,因为您希望登录表单出现在任何地方,以便用户可以在每个页面上登录?
  • 没错,对不起我的英语
  • 您可以发布处理帖子的视图吗?如果我正确理解了这个问题,那么问题是模板没有 POST 上下文,因此您无法在失败时预填表单?

标签: django forms login django-views django-templates


【解决方案1】:

我认为 OP 错误地假设模板上下文变量将匹配上下文处理器的函数名称。

OP 的上下文处理器global_login_form()formLogin 注入到模板上下文中。因此,在模板中,应将表单引用为,例如,{{ formLogin.as_p }}

【讨论】:

    【解决方案2】:

    你必须在每个视图中都有表单变量,或者你应该实现一个模板标签。示例:

    https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags

    from django import template
    from django.contrib.auth.forms import AuthenticationForm
    
    register = template.Library()
    
    @register.inclusion_tag('registration/login.html', takes_context=True)
    def login(context):
        """
        the login form 
        {% load login %}{% login %}
        """
        request = context.get('request', None)
        if not request:
            return 
        if request.user.is_authenticated():
            return dict(formLogin=AuthenticationForm())
        return dict(user=request.user) 
    

    【讨论】:

    • 如果您在 firebug 中可视化表单,您应该会看到 {{ form.username }} 为空。这不是 CSS 问题,但“表单”对象是空的。
    【解决方案3】:

    我想在我的网站上随处使用 表明您可能需要模板上下文处理器。

    def global_login_form(request):
        next = request.GET.get('next', '/')
        login_form = AuthenticationForm(initial={'next': next})
        return {'login_form': login_form}
    

    拥有这个并将这个上下文处理器添加到设置中的 TEMPLATE_CONTEXT_PROCESSORS 部分,您可以在模板中使用{{global_login_form}}

    可能你或多或少会有这样的东西

    ....
    <form action="{% url login_view_name %}" method="POST">
    {{global_login_form.as_p}}
    </form>
    ....
    

    我在我的一个项目中使用了这种模式,并且效果很好。仅在此处注意,如果未验证表单,最好在单独的页面上显示错误的表单。这是视图的示例:

    def login(request):
        if request.method == "POST":
            login_form =LoginForm(data=request.POST)
            if login_form.is_valid():
                next = login_form.cleaned_data.get('next', '/')
                login(request, login_form.get_user())
                return HttpResponseRedirect(next)
    
        return render_to_response(
            'users/login/login_page.html', 
            {'form': login_form},
            context_instance=RequestContext(request),
            )
    

    【讨论】:

    • 但是,如果表单无法验证,我希望消息错误替换登录表单,而不是打开不同的页面。这可能吗?另一方面,你需要使用下一个变量吗?
    • 您不需要使用下一个变量,这是一个有用的附加功能。可以在发布的同一页面上显示表单。我想最好使用 ajax 来响应错误。你需要这样的例子吗?
    • 你的上下文处理器看起来像: {'formLogin': formLogin} 所以在模板中你可以使用变量 {{ formLogin }}。
    • 也请不要完全修改问题,这会使大多数答案无用和不清楚。
    • 还有一个问题:没有login_page.html,因为登录表单在base.html中,所以用户到处都可以看到。如何在登录视图中获取 render_to_response 的第一个参数的值??
    【解决方案4】:
    class MyForm(forms.Form):
        username = forms.CharField(widget=forms.TextInput(attrs={'class':'login_text'}))
        password = forms.CharField(widget=forms.TextInput(attrs={'class':'password_text'}))
    

    这可能是您的解决方案。 Css 作为表单字段的属性传递,因此您无需在 html 中显式声明它。

    【讨论】:

      【解决方案5】:

      不要尝试在 POST 中放入未真正发布过的内容。如果您需要获取模板标签的一些信息,只需使用上下文即可。

      【讨论】:

      • 我做到了,我改变了问题,现在表格不见了!
      【解决方案6】:

      最后我使用了一个中间件来处理请求,而不是使用 context_processor。另外,我删除了我的登录视图,并将表单操作更改为“。”所以登录功能在中间件中。

      我关注this question寻找解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-07
        • 2012-07-11
        • 2014-10-26
        • 2020-10-27
        • 1970-01-01
        • 1970-01-01
        • 2015-06-30
        • 2014-11-03
        相关资源
        最近更新 更多