【发布时间】:2022-06-14 01:23:03
【问题描述】:
我目前正在通过阅读《Head First Python 2nd Edition》这本书来学习 Python,它确实很有帮助并且写得很好,但我认为它有点不合时宜(因为它于 2016 年 12 月 16 日发布,我认为从那时起各种事情发生了变化)。
问题是:我刚刚写完(到目前为止我必须做的)webapp vsearch4web.py,它看起来像这样:
from flask import Flask, render_template, request, escape
from vsearch import search4letters
from DBcm import UseDatabase
app = Flask(__name__)
app.config['dbconfig'] = {'host': '127.0.0.1',
'user': 'vsearch',
'password': 'vsearchpasswd',
'database': 'vsearchlogDB', }
def log_request(req: 'flask_request', res: str) -> None:
"""Log details of the web request and the results"""
with UseDatabase(app.config['dbconfig']) as cursor:
_SQL = """insert into log
(phrase, letters, ip, browser_string, results)
values
(%s, %s, %s, %s, %s)"""
cursor.execute(_SQL, (req.form['phrase'],
req.form['letters'],
req.remote_addr,
req.user_agent.browser,
res, ))
@app.route('/search4', methods=['POST'])
def do_search() -> 'html':
phrase = request.form['phrase']
letters = request.form['letters']
title = 'Here are your results:'
results = ''.join(search4letters(phrase, letters))
log_request(request, results)
return render_template('results.html',
the_title=title,
the_phrase=phrase,
the_letters=letters,
the_results=results,)
@app.route('/')
@app.route('/entry')
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
@app.route('/viewlog')
def view_the_log() -> 'html':
with UseDatabase(app.config['dbconfig']) as cursor:
_SQL = """Select phrase, letters, ip, browser_string, results
from log"""
cursor.execute(_SQL)
contents = cursor.fetchall()
titles = ('Phrase', 'Letters', 'Remote_addr', 'User_agent', 'Results')
return render_template('viewlog.html',
the_title='View Log',
the_row_titles=titles,
the_data=contents,)
if __name__ == '__main__':
app.run(debug=True)
这是我在代码中使用的类:
import mysql.connector
class UseDatabase:
def __init__(self, config: dict) -> None:
self.configuration = config
def __enter__(self) -> 'cursor':
self.conn = mysql.connector.connect(**self.configuration)
self.cursor = self.conn.cursor()
return self.cursor
def __exit__(self, exc_type, exc_value, exc_trace) -> None:
self.conn.commit()
self.cursor.close()
self.conn.close()
然后我在 MySQL 控制台中创建了数据库 "vsearchlogDB",然后(以用户 "vsearch" 的身份登录),我创建了表 “log”(准确输入书上写的内容,即使结果表略有不同,这也是我之前说这本书可能有点不合时宜的原因):
(这是书中显示的表格):
现在,当我在本地运行我的 webapp 并尝试时,会出现此错误:
mysql.connector.errors.IntegrityError: 1048 (23000): 列'browser_string'不能为空
谁能解释一下为什么代码无法提取 browser_string 的值?
我尝试从头开始重新创建表并将 browser_string 列设置为空,实际上在 browser_string 列中(在 /viewlog 页面中)它总是显示 None(即使我认为这是一个无用的测试,因为我不知道如何使用 MySQL),但它不应该是这样的,有人可以解释一下吗?
这里我还添加了webapp的(所有)页面的HTML和CSS代码(对不起所有代码,但我真的不知道问题出在哪里):
base.html:
<!doctype html>
<html>
<head>
<title>{{ the_title }}</title>
<link rel="stylesheet" href="static/hf.css" />
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
entry.html:
{% extends 'base.html' %}
{% block body %}
<h2>{{ the_title }}</h2>
<form method='POST' action='/search4'>
<table>
<p>Use this form to submit a search request:</p>
<tr><td>Phrase:</td><td><input name='phrase' type='TEXT' width='60'></td></tr>
<tr><td>Letters:</td><td><input name='letters' type='TEXT' value='aeiou'></td></tr>
</table>
<p>When you're ready, click this button:</p>
<p><input value="Do it!" type="submit"></p>
</form>
{% endblock %}
结果.html:
{% extends 'base.html' %}
{% block body %}
<h2>{{ the_title }}</h2>
<p>You submitted the following data:</p>
<table>
<tr><td>Phrase:</td><td>{{ the_phrase }}</td></tr>
<tr><td>Letters:</td><td>{{ the_letters }}</td></tr>
</table>
<p>When "{{ the_phrase }}" is searched for "{{ the_letters }}", the following
results are returned:</p>
<h3>{{ the_results }}</h3>
{% endblock %}
viewlog.html:
{% extends 'base.html' %}
{% block body %}
<h2>{{ the_title }}</h2>
<table>
<tr>
{% for row_title in the_row_titles %}
<th>{{row_title}}</th>
{% endfor %}
</tr>
{% for log_row in the_data %}
<tr>
{% for item in log_row %}
<td>{{item}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endblock %}
hf.css:
body {
font-family: Verdana, Geneva, Arial, sans-serif;
font-size: medium;
background-color: tan;
margin-top: 5%;
margin-bottom: 5%;
margin-left: 10%;
margin-right: 10%;
border: 1px dotted gray;
padding: 10px 10px 10px 10px;
}
a {
text-decoration: none;
font-weight: 600;
}
a:hover {
text-decoration: underline;
}
a img {
border: 0;
}
h2 {
font-size: 150%;
}
table {
margin-left: 20px;
margin-right: 20px;
caption-side: bottom;
border-collapse: collapse;
}
td, th {
padding: 5px;
text-align: left;
}
.copyright {
font-size: 75%;
font-style: italic;
}
.slogan {
font-size: 75%;
font-style: italic;
}
.confirmentry {
font-weight: 600;
}
/*** Tables ***/
table {
font-size: 1em;
background-color: #fafcff;
border: 1px solid #909090;
color: #2a2a2a;
padding: 5px 5px 2px;
border-collapse: collapse;
}
td, th {
border: thin dotted gray;
}
/*** Inputs ***/
input[type=text] {
font-size: 115%;
width: 30em;
}
input[type=submit] {
font-size: 125%;
}
select {
font-size: 125%;
}
【问题讨论】:
-
对我来说看起来是正确的。它试图从烧瓶请求的 user_agent 中获取浏览器,这是查看的正确位置。您可以执行
req.user_agent.browser if req.user_agent.browser is not None else 'Unknown'之类的操作或一些此类技巧,以确保将值传递到 INSERT 语句中。或者您可以修改表以允许该列中的 NULL 值,以便您可以完成您的教程。 -
是的,我可以这样做,但我仍然无法弄清楚为什么程序不采用浏览器名称的值(我尝试了不同的浏览器,但结果是相同),这很奇怪,因为当我之前在 .txt 文件中打印值(整个 req.user_agent 而不是 req.user_agent.browser)时,一切正常,然后我尝试更改(在当前程序上你在这个网站上看到)从req.user_agent.browser到req.user_agent,但是MySQL显示这个消息错误:_mysql_connector.MySQLInterfaceError: Python type UserAgent cannot be convert,so Idk
-
(我为字符限制写了另一条评论)那么,您认为这可能是数据库问题(因为它略有不同,即使字段browser_string的记录相同)或其他?
-
当您打印出
req.user_agent时,它是否显示一个以browser作为键之一的对象?我真的不确定它为什么会失败。你的蟒蛇是正确的。问题不是数据库问题。这只是一个整体问题,当前的代码 + 表不是以允许None浏览器之类的方式构建的。代码是正确的。表是正确的。它只是没有超级硬化,因为它不会优雅地预测和处理这样的边缘情况。 -
当我打印出“req.user_agent”(在 .txt 文件中)时,它显示(这里是一个示例):Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3。 9 (KHTML, 像 Gecko) 版本/9.0.2 Safari/601.3.9
标签: mysql python-3.x database flask mysql-python