表单在 Django 中没有绑定

Posted

技术标签:

【中文标题】表单在 Django 中没有绑定【英文标题】:Form not binding in Django 【发布时间】:2016-08-10 19:38:24 【问题描述】:

在我发布数据的 Django 视图之一中,表单由于未绑定而无效,尽管表单肯定与数据绑定。我不完全确定为什么会这样。我正在开发的应用程序使用 Angular 作为前端,所以我没有在我的 html 中使用 Django 的表单类,但它应该没关系,因为 Django 的表单类只是创建 HTML 小部件?

login.html

<div class="account-login" id="login-view">
  <div class="card card-half">
    <h2 class="text-center">Welcome back!</h2>
    <h4 class="text-center">Sign in to your account.</h4>

    <div class="alert alert-danger" ng-if="vm.errorMessage">
       vm.errorMessage 
    </div>

    <form class="form-horizontal" name="form" ng-submit="vm.login(vm.auth)">
        % csrf_token %
      <div class="form-group">
        <label for="email" class="col-sm-3 control-label">Email</label>

        <div class="col-sm-9 col-md-7">
          <input type="email" id="email"
              class="form-control"
              placeholder="name@example.com"
              ng-model="vm.auth.email"
              required
              hl-focus>
        </div>
      </div>

      <div class="form-group">
        <label for="password" class="col-sm-3 control-label">Password</label>

        <div class="col-sm-9 col-md-7">
          <input type="password" id="password" name="password"
              class="form-control"
              placeholder="******"
              ng-model="vm.auth.password"
              required minlength="6">

          <div class="has-warning" ng-if="form.password.$dirty">
            <div class="help-block" ng-messages="form.password.$error">
              <div ng-message="minlength">Please enter at least six characters.
              </div>
            </div>
          </div>

        </div>
      </div>

      <div class="form-group">
        <div class="col-sm-3"></div>
        <div class="col-sm-9 col-md-7">
          <button type="submit" class="btn btn-block btn-secondary"
              ng-disabled="!form.$valid || vm.submitBusy">
            Sign in
            <span ng-if="vm.submitBusy"><i class="fa fa-circle-o-notch fa-spin"></i></span>
          </button>
        </div>
      </div>

    </form>

  </div>
</div>

<div class="col-sm-6 col-sm-offset-3">
  <p>Forgot your password? Reset it
      <a ui-sref="auth.reset">here</a>.</p>
  <p>Trying to create a team?
      <a ui-sref="auth.join.personal">Sign up</a> to get started.</p>
</div>

表格

class LoginForm(forms.Form):
    email = forms.EmailField(max_length=100)
    password = forms.CharField(max_length=20)
    token = forms.CharField(max_length=20)

    def __init__(self, request=None, *args, **kwargs):
        self.cached_user = None
        self.request = request
        kwargs.setdefault('label_suffix', '')
        super(LoginForm, self).__init__(*args, **kwargs)

    def clean(self):
        cleaned_data = self.cleaned_data

        if len(self._errors) > 0:
            return cleaned_data
        else:
            email = cleaned_data.get('email')
            password = cleaned_data.get('password')

            if email is None or password is None:
                messages.error(self.request, 'Please enter an email and password.')
                return forms.ValidationError("Error")
            else:
                self.cached_user = authenticate(username=email, password=password)

                if self.cached_user is None:
                    self._errors["password"] = self.error_class(["Password incorrect. Passwords are case sensitive."])
                elif not self.cached_user.is_active:
                    messages.error(self.request,
                                   'This account is inactive. Please check your inbox for our confirmation email, and '
                                   'click the link within to activate your account.')
                    raise forms.ValidationError("Error")

        if not cleaned_data.get('remember_me'):
            self.request.session.set_expiry(0)

        return cleaned_data

    def get_user(self):
        return self.cached_user

查看

def login(request):
    # """ -Log in the user if credentials are valid """
    if request.method == "POST":
        form = LoginForm(request.POST)

        if form.is_valid():
            cleaned_data = form.clean()

            account = Account.objects.get(email=cleaned_data['email'], password=cleaned_data['password'])

            if cleaned_data['token']:

                token = cleaned_data['token']
                invite = OrgInvite.objects.get(token=token)
                org = Org.objects.get(id=invite.org_id)
                if not invite:
                    raise Exception("Invitation token is invalid.")
                if invite.used == True:
                    raise Exception("Invitation token has already been used.")

                org_member = OrgMember.objects.get(account_id=account.id)
                if org_member:
                    raise Exception("Account is already in team.")
                else:
                    org.add_members(account.id, False, invite.is_admin)
                    invite.used = False

                    # add_to_welcome(org_id=org.id, account_id=account.id, inviter_id=invite.token)

            else:
                pass

        context = 
            'message': 'ok',
            'next': '/app/'
        

        return composeJsonResponse(200, "", context)

【问题讨论】:

form.is_valid() 将调用 form.clean() 所以你不应该明确地调用它。要在清理后获取表单数据,请执行cleaned_data = form.cleaned_data 是什么让您认为表单未绑定,或者这就是验证失败的原因? 当我在视图中调试并设置断点时,表单绑定属性显示为 false。我将它包含在图像中。它的末端有一个很小的滑行,所以有点难以看到。 【参考方案1】:

这是一个常见的错误:您更改了表单类的初始化函数的签名,因此第一个参数是请求。因此,当您执行LoginForm(request.POST) 时,POST 数据将转到request 参数,而不是data

可以通过确保始终传递请求来解决此问题 - LoginForm(request, request.POST) - 但更好的方法是不更改签名,并将请求作为 kwarg 传递并获取它来自**kwargs 字典。

【讨论】:

啊,我明白了,这很有道理。我刚刚更改了表单初始化函数的参数,现在它已经绑定了,谢谢 Daniel。 您能写更多细节吗?目前尚不清楚如何解决此问题。

以上是关于表单在 Django 中没有绑定的主要内容,如果未能解决你的问题,请参考以下文章

Django表单API详解

Django 表单API详解

Django:无法将上传的图像绑定到表单 ImageField()

Django的表单类

如何在 Django 管理员中为模型字段使用自定义表单字段?

纯Django表格绑定用户提交表格和视图