Django - 使用context_processor

时间:2011-06-27 09:42:13

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

我想在我的网页中随处放置一个登录表单,因此我添加了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尝试调用表单时尝试的差异htmls:

<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",
)

有什么想法吗?

6 个答案:

答案 0 :(得分:4)

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

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) 

答案 1 :(得分:4)

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

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

答案 2 :(得分: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),
        )

答案 3 :(得分:0)

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中明确声明它。

答案 4 :(得分:0)

不要试图把POST没有真正发布的东西放进去。如果您需要获取模板标签的一些信息,只需使用上下文。

答案 5 :(得分:0)

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

我跟着this question找到了解决方案。