web-dev-qa-db-ja.com

Flask self.errors.append()-AttributeError: 'Tuple'オブジェクトに属性がありません 'append'

送信されたデータをユーザーが検証し、入力された電子メールが存在するかどうかを確認しようとすると、小さな登録アプリでエラーが発生します。

これが私のファイルです:
フォーム:

from flask.ext.wtf import Form
from wtforms import TextField, BooleanField, PasswordField, TextAreaField, validators
from wtforms.validators import Required
from app import models

class RegisterForm(Form):
"""RegisterForm class needed for retrieving data from user"""
username = TextField('username', [validators.Length(min=3, max=50), validators.Required()])
email = TextField('email', [validators.Length(min=3, max=100), validators.Required()])
password = PasswordField('password', [validators.Required()])
age = TextField('age', [validators.Length(min=1, max=3), validators.Required()])
about_user = TextAreaField('about_user', [validators.Length(max=500)])
img_url = TextField('img_url')


def email_unique(self, email):
    if models.User.query.filter_by(email = email).first() != None:
        self.email.errors.append('This E-mail address is already in use. Please choose another one.') 
        return False

ビュー:

#!flask/bin/python
from app import app, db, lm
from flask import render_template, url_for, flash, g, redirect, session, request
from flask.ext.login import login_user, logout_user, current_user, login_required
from forms import LoginForm, RegisterForm, EditForm
from models import User

@app.route('/register', methods = ['GET', 'POST'])
def register():
    form = RegisterForm()
    #makes the username unique
    u_unique =  form.username.data
    u_unique = User.unique_username(u_unique)

    #validates email adress and checks if it already exists or not 
    form.email_unique(form.email.data)

    if form.validate_on_submit():
        user = User(
            u_unique,
            form.password.data, 
            form.email.data, 
            form.age.data, 
            form.about_user.data,
            form.img_url.data)
        db.session.add(user)
        db.session.commit()
        flash('Thank you for your registration')
        flash('Your username is: ' + str(u_unique))
        return redirect(url_for('login'))
    else:
        for error in form.errors:
            flash(error)

    return render_template('register.html',
        title = 'Registeration',
        form = form)

エラーは次のとおりです。

Traceback (most recent call last) File <br> "/home/maksad/Desktop/faskMonkey/flask/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__ return self.wsgi_app(environ, start_response) 
File "/home/maksad/Desktop/faskMonkey/flask/lib/python2.7/site-packages/flask/app.py", line 1689, in wsgi_app response = self.make_response(self.handle_exception(e)) 
File "/home/maksad/Desktop/faskMonkey/flask/lib/python2.7/site-packages/flask/app.py", line 1687, in wsgi_app response = self.full_dispatch_request() 
File "/home/maksad/Desktop/faskMonkey/flask/lib/python2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request rv = self.handle_user_exception(e) 
File "/home/maksad/Desktop/faskMonkey/flask/lib/python2.7/site-packages/flask/app.py", line 1358, in full_dispatch_request rv = self.dispatch_request() 
File "/home/maksad/Desktop/faskMonkey/flask/lib/python2.7/site-packages/flask/app.py", line 1344, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) 
File "/home/maksad/Desktop/faskMonkey/app/views.py", line 92, in register form.email_unique(form.email.data) 
File "/home/maksad/Desktop/faskMonkey/app/forms.py", line 26, in email_unique
 self.email.errors.append('This E-mail address is already in use. Please choose another one.')
 AttributeError: 'Tuple' object has no attribute 'append'
5
Max

Tupleオブジェクト 追加できません 。代わりに、list()を使用してリストに変換し、追加してから、次のように変換し直します。

>>> obj1 = (6, 1, 2, 6, 3)
>>> obj2 = list(obj1) #Convert to list
>>> obj2.append(8)
>>> print obj2
[6, 1, 2, 6, 3, 8]
>>> obj1 = Tuple(obj2) #Convert back to Tuple
>>> print obj1
(6, 1, 2, 6, 3, 8)

お役に立てれば!

12
A.J. Uppal

自分でこれに出くわした。あなたの質問に対するより良い答えは、要素にエラーを追加する前に要素を検証する必要があるということだと思います。検証プロセスでは、エラーフィールドがリストに設定され、フィールドを検証する前に変更すると、検証時に上書きされます。

したがって、フォームのvalidateメソッドをオーバーライドし、親のvalidateメソッドを呼び出してから、その中でemail_uniqueメソッドを実行します。

次に、validate_on_submitの一部になるため、ビューからemail_uniqueを削除できます。

4
24HourPhysicist

tuplesは不変の型であるため、スプライスして値を割り当てることはできません。値を追加および削除する必要があるデータ型を使用する場合は、代わりにリストを使用してください。

>>> a = (1,2,3)
>>> a.append(2)
AttributeError: 'Tuple' object has no attribute 'append'
>>> b = [1,2,3]
>>> b.append(2)
[1,2,3,2]
3
sshashank124

答えはもう少し深いです。 「エラー」は、Fieldクラスが作成されたときのタプルです。

class Field(object):
    """
    Field base class
    """
    errors = Tuple()

しかし、メソッドvalidateが呼び出されると、それはリストに変換されます

def validate(self, form, extra_validators=Tuple()):
    self.errors = list(self.process_errors)

したがって、必要なのは、validate_on_submitの直後にemail_unique関数を呼び出すだけです。これにより、フォームのvalidate関数が呼び出され、エラーがリストに変換されます。

@app.route('/register', methods = ['GET', 'POST'])
def register():
    form = RegisterForm()
    #makes the username unique
    u_unique =  form.username.data
    u_unique = User.unique_username(u_unique)

    #validates email adress and checks if it already exists or 

    if form.validate_on_submit():
        form.email_unique(form.email.data)
        user = User(
            u_unique,
            form.password.data, 
            form.email.data, 
            form.age.data, 
            form.about_user.data,
            form.img_url.data)
        db.session.add(user)
        db.session.commit()
        flash('Thank you for your registration')
        flash('Your username is: ' + str(u_unique))
        return redirect(url_for('login'))
    else:
        for error in form.errors:
            flash(error)

    return render_template('register.html',
        title = 'Registeration',
        form = form)
1
Zaytsev Dmitry