【问题标题】:python Django 403 forbidden when changing email更改电子邮件时禁止python Django 403
【发布时间】:2015-01-12 07:53:43
【问题描述】:

我想使用标准 Django 方法更改用户电子邮件,但在更改电子邮件之前,表单和数据库中的密码必须匹配。我得到 403 错误CSRF token missing or incorrect. 这是我的form

class ChangeMailForm(forms.Form):
    password = forms.CharField(label = (u'Podaj hasło'), widget=forms.PasswordInput(render_value=False))
    email = forms.EmailField(label = (u'Podaj nowy adres email'))

    def clean_email(self):
        mail = self.cleaned_data['email']
        if User.objects.filter(email=email).exists():
            raise ValidationError("Taki email jest w bazie")
        return mail

我的view:

def ChangeEmail(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/')
    if request.method == 'POST':
        form = ChangeMailForm(request.POST)
        if form.is_valid():
            usr = request.user
            u = User.objects.filter(username=usr)
            if not User.objects.filter(username=usr).check_password(form.cleaned_data['password']):
                return HttpResponseRedirect('/')
            mail = form.cleaned_data['email']
            u.new_email(mail)
            u.save()
        else:
            return render_to_response('changeemail.html', {'form':form},context_instance=RequestContext(request))
    else:
        form = ChangeMailForm()
        return render_to_response('changeemail.html', {'form':form}, context_instance=RequestContext(request))

和我的template的一部分:

<form action="" method="post">
    {% csrf_token %}
    {% if form.errors %}<p id="correct">Popraw następujące pola:</p>{% endif %}
    <table id="change">
        <tr>
            <td {% if form.password.errors %} class="error" {% endif %}>Podaj hasło:</td>
            <td>{{ form.password }}</td>
        </tr>
        <tr>
            <td {% if form.email.errors %} class="error" {% endif %}>Podaj nowy adres:</td>
            <td>{{ form.email }}</td>
        </tr>
    </table>
    <div id="sub">
    <input type="submit"  value="Wykonaj" alt="login" id="submit" />

任何帮助将不胜感激。

编辑:添加@csrf_exempt 装饰器后的回溯

Request Method: POST
Request URL: http://127.0.0.1:8000/changeemail/

Django Version: 1.7.1
Python Version: 2.7.8
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'dailyresults',
 'trainingresults',
 'athlete',
 'easy_pdf')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware')


Traceback:
File "D:\Programy\Python27\lib\site-packages\django-1.7.1-py2.7.egg\django\core\handlers\base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "D:\Programy\Python27\lib\site-packages\django-1.7.1-py2.7.egg\django\views\decorators\csrf.py" in wrapped_view
  57.         return view_func(*args, **kwargs)
File "D:\Inz\trening\athlete\views.py" in ChangeEmail
  93.             if not User    .objects.filter(username=usr).check_password(form.cleaned_data['password']):

异常类型:/changeemail/ 处的 AttributeError 异常值:“QuerySet”对象没有属性“check_password”

【问题讨论】:

  • 当前代码发生了什么?一个快速的假设 - 您可能不想将您的 clean_email 方法中的行更改为 if not User.objects.filter(email=email).exists()
  • @IanPrice,我添加了发布的原因(第二行),我无法更改您建议的行 - 如果电子邮件在数据库中,它将返回 ValidationError "This email在数据库中”
  • @AdamP,这一行是错误的:User.objects.filter(username=usr).check_password(...)u 是一个本身没有 check_password 方法的查询集。您需要更改为queryset().first()u[0] 之类的东西才能访问User 对象(当然您需要验证它是否存在,否则它将是[])。
  • 虽然我上面提到的是真的,CSRF is missing 提示你代码中其他地方的错误,没有正确传递/验证它。
  • @AdamP,您能否尝试在您的视图中放置一个@csrf_exempt 装饰器,以检查其他部分是否有效?请发布您的完整堆栈跟踪

标签: python django csrf


【解决方案1】:

您需要将此行更改为:

u = User.objects.filter(username=usr)
if not User.objects.filter(username=usr).check_password(...):

到这里:

u = User.objects.filter(username=usr).first()
if u and u.check_password(...):
    ...

为什么它会在第一种方法中抛出错误是因为 ulist 中的一个查询集,它本身没有 check_password 方法。但是您可以使用queryset().first() 访问User Object 或将其切片u[0] 并获取User 对象(当然您需要验证它是否存在,否则它将是[])。

请确保csrf_token确实存在于您的请求中,您可以使用logging并检查如下:

import logging
...
#your view
logging.info('request MEAT for csrf: %s', request.META.get('CSRF_COOKIE'))

看看它是否存在。

您也可以尝试清除浏览器缓存,或使用其他浏览器(新会话或私人会话)进行测试,看看是否仍然出现错误。

更新

当您需要更新email字段时,只需使用普通模型的save方法即可:

# above code... and being verified ...
u.email = form.cleaned_data['email']
u.save()

就是这样。

【讨论】:

  • 好的,但请告诉我如何实际更新email 字段?我尝试过使用u.update(email=request.POST['email'])u.update(email=mail),但它返回给我的是用户没有update 属性。与u.email(mail) 我得到unicode not callable。我已经登录到我的视图,但我没有看到任何信息。
  • @AdamP,这只是普通的 django 模型 save() 方法??好的,我会为你更新答案
  • 哇,比我想象的要容易。感谢您的帮助。
  • @AdamP,没问题 ;) 是的,修改/更新模型实际上比我们想象的要容易。
猜你喜欢
  • 2015-11-03
  • 1970-01-01
  • 2020-07-29
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多