无法将表单数据传递给方法以验证表单

Cannot pass the form data to a method in order to validate form

我正在尝试为 AddSongForm 中的一个字段创建自定义验证器。我使用了内联验证器,它使用了我的歌曲 class 中的两种方法。当我尝试 运行 代码时,我得到以下回溯:

form = AddSongForm()
[2017-05-16 13:44:11,547] ERROR in app: Exception on /addsong [POST]
Traceback (most recent call last):
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Python36-32\lib\site-packages\flask\_compat.py", line 33, in reraise
raise value
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Python36-32\lib\site-packages\flask_login\utils.py", line 228, in decorated_view
return func(*args, **kwargs)
File "C:/Users/Pellissari/Desktop/files/projects/Musical 9gag/view.py", line 40, in addsong
if form.validate_on_submit():
File "C:\Python36-32\lib\site-packages\flask_wtf\form.py", line 101, in validate_on_submit
return self.is_submitted() and self.validate()
File "C:\Python36-32\lib\site-packages\wtforms\form.py", line 310, in validate
return super(Form, self).validate(extra)
File "C:\Python36-32\lib\site-packages\wtforms\form.py", line 152, in validate
if not field.validate(self, extra):
File "C:\Python36-32\lib\site-packages\wtforms\fields\core.py", line 204, in validate
stop_validation = self._run_validation_chain(form, chain)
File "C:\Python36-32\lib\site-packages\wtforms\fields\core.py", line 224, in _run_validation_chain
validator(form, self)
File "C:\Users\Pellissari\Desktop\files\projects\app\forms.py", line 20, in validate_song_link
if Songs.get_provider(url) in valid_providers:
TypeError: get_provider() missing 1 required positional argument: 'url'
127.0.0.1 - - [16/May/2017 13:44:11] "POST /addsong HTTP/1.1" 500 -

这是我的表格class

class AddSongForm(Form):
    song_title = StringField('song_title', validators=[DataRequired()])
    song_artist = StringField('song_artist', validators=[DataRequired()])
    song_genre = StringField('song_genre')
    song_link = StringField('song_link', validators=[DataRequired()])

    def validate_song_link(form, song_link):
    valid_providers = ['youtube.com', 'www.youtube.com', 'soundcloud.com', 'www.soundcloud.com']
    url = song_link.data
    if Songs.get_provider(url) in valid_providers:
        if Songs.get_embed_code(url) is not False:
            return True
        else:
            print("couldn't get your content")
            return False
    else:
        print("unsupported provider")
        return False

这里是class我使用的方法

class Songs(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    title = db.Column(db.String(50))
    artist = db.Column(db.String(30))
    genre = db.Column(db.String(40))
    author = db.Column(db.String(40))
    timestamp = db.Column(db.DateTime)
    likes_num = db.Column(db.Integer)
    song_link = db.Column(db.String(120))

    def get_provider(self, url):
        return urllib.parse.urlsplit(url)[1]

    def get_embed_code(self, url):
        code = None
        vars = {'url': url, 'format': 'json', 'iframe': 'true', 'maxwidth': '450', 'show_comments': 'false'}
        provider = self.get_provider(url)
        endpoint = "http://"+provider+"/oembed?"
        source = endpoint+urllib.parse.urlencode(vars)
        try:
            request = urlopen(source)
            code = json.load(request)['html']
            return code
        except:
            print("impossible to get your content. Check the link") 
            return False

我对 Python 很陌生,这是我第一次编写 OO 代码,所以我不知道这里会发生什么。除了这个问题,如果你也能给我一些关于代码的反馈,如果在某种意义上有改进的余地,我会很高兴。

我不相信这些应该是歌曲的方法。他们没有提到任何与歌曲有关的东西 class。

但是,如果您想将它们保留为方法,但仍想从 class 中调用它们,则它们需要是 class 方法,而不是实例方法。

@classmethod
def get_provider(cls, url):
    return urllib.parse.urlsplit(url)[1]

@classmethod
def get_embed_code(cls, url):
    ...
    provider = cls.get_provider(url)

首先纠正方法validate_song_link的缩进。应该是这样的:

def validate_song_link(form, song_link):
    valid_providers = ['youtube.com', 'www.youtube.com', 'soundcloud.com', 'www.soundcloud.com']
    url = song_link.data
    if Songs.get_provider(url) in valid_providers:
        if Songs.get_embed_code(url) is not False:
            return True
        else:
            print("couldn't get your content")
            return False
    else:
        print("unsupported provider")
        return False

要解决您的问题,您可以尝试将 get_provider 方法更改为 class 方法,如下所示:

@classmethod
def get_provider(cls, url):
    return urllib.parse.urlsplit(url)[1]

然后可以这样调用:

songs = Songs()

if Songs.get_provider(songs, url) in valid_providers:
    if Songs.get_embed_code(url) is not False:
        return True