Crossin的编程教室

标题: Python 实战(4):搜一下 [打印本页]

作者: crossin先生    时间: 2015-5-3 15:54
标题: Python 实战(4):搜一下
someweb-04.png
一个内容型网站如果不能进行站内搜索,那是会令人抓狂的。都说知乎的搜索不好使,可人家好歹也是有的。所以我们的电影网站至少也得有个搜素框。

那么要如何做呢?HTML 里有一个 form 标签,它的作用是创建一个表单,用来提交一些数据。诸如搜索、登录、评论等操作,都可以通过 form 标签来解决。前面说过,我们直接在流量器里访问一个 url 地址是向服务器发送了一个 GET 请求。而用 form,就可以选择使用 POST 请求,从而更方便更安全地传递数据。

这件事情的大体思路是,在首页上通过 form 标签增加一个搜索框。当用户输入文字点击搜索后,会向服务器发送一个 POST 请求。服务器端的代码里拿到请求中的文字,在数据库里搜索标题中包含此文字的影片列表,返回给首页模板进行显示。

在首页模板 index.html 中添加搜索框:

<form action="/" method="post">
        <input type="text" name="title" />
         <input type="submit" value="搜索" />
</form>

action 是请求的地址,这里选择向首页请求,method 表示方法是 POST。input 是表单中的元素,type="text" 表示一个文本框,name="title" 在服务器端处理数据时会用到。type="submit" 表示一个提交按钮,value="搜索" 是按钮上显示的文字。

添加完之后刷新页面,可以看到已经有了一个搜索框。不过此时输入内容并点击“搜索”后,页面会显示 None。这是因为服务器端的 index 类中还没有对 POST 请求做相应的处理。所以,在 code.py 里,index 类中的 GET 方法下,增加一个类似的 POST 方法:

def POST(self):
   data = web.input()
   condition = r'title like "%' + data.title + r'%"'
   movies = db.select('movie', where=condition)
   return render.index(movies)

web.input() 拿到的是表单传入的数据,data.title 就是用户输入的文本。与 GET 方法中获取数据库中所有影片不同,这里额外增加一项搜索条件:

title like "%搜索内容%"

这里用r''是为了防止 python 默认对于字符串中 % 的转义。

like 是 SQL 的语法,% 表示匹配 0 到任意多个字符。这里对应完整的 SQL 查询语句是:

select * from movie where title like "%搜索内容%";

执行效果是查询出所有标题中包含(搜索内容)的影片数据。

此时再点击搜索,便可看见,首页上的影片列表只会列出符合搜索条件的影片标题。在之后数据量增加的情况下,这个小小的功能将会大有用处。


someweb-4-code.py (645 Bytes, 下载次数: 208)
someweb-4-index.html (303 Bytes, 下载次数: 180)



作者: Tig    时间: 2015-5-4 20:19
顶。。
作者: 喵小白    时间: 2015-5-5 20:52
如果我想在子页面放一个搜索框,但是子页面的地址是不确定的(由主页链接跳转而来),action要怎么写?
作者: crossin先生    时间: 2015-5-5 21:05
喵小白 发表于 2015-5-5 20:52
如果我想在子页面放一个搜索框,但是子页面的地址是不确定的(由主页链接跳转而来),action要怎么写? ...

action里写的是这个请求发送到的地址,所以在哪里不影响
这里‘/’表示把请求发到主页的url,而不是指当前页面
作者: 喵小白    时间: 2015-5-6 10:58
crossin先生 发表于 2015-5-5 21:05
action里写的是这个请求发送到的地址,所以在哪里不影响
这里‘/’表示把请求发到主页的url,而不是指当 ...

嗯。因为我想对子页面的数据进行搜索而不是主页的,所以我就把post方法写在了子页面类中,但是不能实现搜索。但是我把post方法写在主页里,子页面就可以实现搜索。所以我觉得应该是前者的action写的不对。。。。。。
作者: suckit    时间: 2015-5-7 09:46
博主快更,等好久了
作者: shallecker    时间: 2015-5-17 21:08
楼主大神
作者: chestnut    时间: 2015-6-5 22:22
先生,如果搜索的关键词不存在要怎样处理?
可以先判断搜索结果,存在则返回render.index(movies);如果判断db.select()返回None,则重新生成页面吗?
作者: crossin先生    时间: 2015-6-6 19:34
chestnut 发表于 2015-6-5 22:22
先生,如果搜索的关键词不存在要怎样处理?
可以先判断搜索结果,存在则返回render.index(movies);如果判断 ...

这个就看你想让他显示什么了。几种方法:

在模板里判断,如果movies为空,增加显示“没有符合的搜索结果”文字提示

在处理逻辑里判断,如果没搜到,返回其他模板,或者首页之类
作者: hipeter    时间: 2015-11-18 19:47
想问下先生那个condition的内容是怎么定义的? 我试着进行如下的断句:
condition = r'{title like "[%(' + data.title + r')%]"}'

其中title like "[%(' + data.title + r')%]"的双引号里面的部分%' + data.title + r' 不太明白。是%和r后面都需要加单引号的意思么?
作者: crossin先生    时间: 2015-11-19 13:20
hipeter 发表于 2015-11-18 19:47
想问下先生那个condition的内容是怎么定义的? 我试着进行如下的断句:
condition = r'{title like "[%(' + ...

不是加单引号,这个式子是
r'xxxxxx' + data.titile + r'xxxx'
为了拼出那个查询语句
作者: hipeter    时间: 2015-11-19 13:57
crossin先生 发表于 2015-11-19 13:20
不是加单引号,这个式子是
r'xxxxxx' + data.titile + r'xxxx'
为了拼出那个查询语句 ...

明白了,thx.
作者: A_Tling    时间: 2016-7-20 11:21
先生,我还是没有懂r'title like "%' + data.title + r'%"'这个式子。这样r'xxxxxx' + data.title + r'xxxx'是为了拼出查询语句,然后title like "%搜索内容%",可这样一来就变成title like "%' + data.title + r'%" 了啊。而且为了防止python转义的“为什么一个在%前,一个在%后呢
作者: crossin先生    时间: 2016-7-20 12:43
A_Tling 发表于 2016-7-20 11:21
先生,我还是没有懂r'title like "%' + data.title + r'%"'这个式子。这样r'xxxxxx' + data.title + r'xxxx ...

"%搜索内容%" 这个格式是给 sql 语句读的,不是python的防转义。
如果你觉得这边难理解,可以多分几个步骤来拼这个字符串,最终的目的就是你说的,拼出一个:
  1. title like "%搜索内容%"
复制代码
这样的字符串作为sql语句,然后交给数据库去执行
作者: A_Tling    时间: 2016-7-20 15:05
crossin先生 发表于 2016-7-20 12:43
"%搜索内容%" 这个格式是给 sql 语句读的,不是python的防转义。
如果你觉得这边难理解,可以多分几个步骤 ...

也就是说搜索内容是' + data.title + r'是吗,可是这儿的r又代表什么呢
麻烦先生了,原谅我比较笨。。。
作者: crossin先生    时间: 2016-7-20 16:23
A_Tling 发表于 2016-7-20 15:05
也就是说搜索内容是' + data.title + r'是吗,可是这儿的r又代表什么呢
麻烦先生了,原谅我比较笨。。。 ...

搜索内容是 condition:
  1. condition = r'title like "%' + data.title + r'%"'
复制代码
这个你看不明白的话,把他分解开来
  1. s1 = r'title like "%'        # title like "%
  2. s2 = data.title        # 搜索内容
  3. s3 = r'%"'        #  %"
  4. condition = s1 + s2 + s3
复制代码
最后 condition 就是
  1. title like "%标题%"
复制代码
这样一个字符串
作者: A_Tling    时间: 2016-7-20 17:17
crossin先生 发表于 2016-7-20 16:23
搜索内容是 condition:这个你看不明白的话,把他分解开来最后 condition 就是这样一个字符串 ...

啊,我明白了。跪谢~~~
作者: nekonekobox    时间: 2017-3-5 16:30
crossin先生 发表于 2016-7-20 16:23
搜索内容是 condition:这个你看不明白的话,把他分解开来最后 condition 就是这样一个字符串 ...

  我试了下这里可能不需要用r'转义内容'来转义吧
我是python3,用下面的语句一样可以生效
  def POST(self):
        data=web.input()
        condition='title like "%'+data.title+'%"'
        movies=db.select('movie',where=condition)
        return render.index(movies)
作者: crossin先生    时间: 2017-3-5 17:10
nekonekobox 发表于 2017-3-5 16:30
我试了下这里可能不需要用r'转义内容'来转义吧
我是python3,用下面的语句一样可以生效
  def POST(sel ...

r不是转义,只是为了防止转义。当没有转义字符的时候,加不加都一样
作者: Rune    时间: 2017-6-22 17:25
本帖最后由 Rune 于 2017-6-22 17:33 编辑

先生 我按照教程里写了代码结果搜索结果是none,我直接copy了你留在帖子里的代码只是改了数据库和模板的名字,用的是我自己的,其他都没动,结果搜索还是现实none。 请问该如何解决啊?

1.png (39.75 KB, 下载次数: 432)

1.png


作者: crossin先生    时间: 2017-6-22 23:42
Rune 发表于 2017-6-22 17:25
先生 我按照教程里写了代码结果搜索结果是none,我直接copy了你留在帖子里的代码只是改了数据库和模板的名 ...

帖子下面的代码有问题。你参考教程中的代码,要根据condition搜出movie,然后再rander后return返回。
你没有return,默认就返回none
作者: Rune    时间: 2017-6-23 11:36
本帖最后由 Rune 于 2017-6-23 11:43 编辑
crossin先生 发表于 2017-6-22 23:42
帖子下面的代码有问题。你参考教程中的代码,要根据condition搜出movie,然后再rander后return返回。
你 ...

先生 非常感谢你的回复,其实我昨天也试过按照教程写代码,但是还是显示none。今天我又找到第八课,参考里面搜索的部分写,结果还是none。我看到cmd上面说"http/1.1 POST"405 method not allowed,也搜索了相关解决办法,不知道是不是和别的设置有关而不是代码的问题?下面是我修改后的代码
class index:
    def GET(self):
        movies=db.select('movie')
        return render.b(movies)
        def POST(self):
             data = web.input()
        condition = r'title like "%' + data.title + r'%"'
        movies = db.select('movie', where=condition)
        return render.b(movies)
作者: crossin先生    时间: 2017-6-23 21:01
Rune 发表于 2017-6-23 11:36
先生 非常感谢你的回复,其实我昨天也试过按照教程写代码,但是还是显示none。今天我又找到第八课,参考里 ...

你这个缩进都完全不对啊
405就是说你没有定义post方法,如果你缩进是你发上来的这样,那肯定不对。
作者: crossin先生    时间: 2017-6-23 21:01
Rune 发表于 2017-6-23 11:36
先生 非常感谢你的回复,其实我昨天也试过按照教程写代码,但是还是显示none。今天我又找到第八课,参考里 ...

你这个缩进都完全不对啊
405就是说你没有定义post方法,如果你缩进是你发上来的这样,那肯定不对。
作者: Rune    时间: 2017-6-24 22:57
crossin先生 发表于 2017-6-23 21:01
你这个缩进都完全不对啊
405就是说你没有定义post方法,如果你缩进是你发上来的这样,那肯定不对。 ...

先生 感谢你的回复。我粘贴上来之后缩进变了,图贴在下面 第20行我也觉得缩进应该往后一格,但是往后一格就会说unexpected indent,在图里那个位置才没有问题。我已经在搜索功能这一块卡了两天了,也试过自己查别的方法解决,实在解决不了了。感谢你耐心的回复。

1.png (14.47 KB, 下载次数: 420)

1.png


作者: crossin先生    时间: 2017-6-25 14:40
Rune 发表于 2017-6-24 22:57
先生 感谢你的回复。我粘贴上来之后缩进变了,图贴在下面 第20行我也觉得缩进应该往后一格,但是往后一格 ...

你这缩进还是混乱的。不知道你之前基础课程里的内容是否有都看过,包括缩进的含义、函数的定义、面向对象等。如果不熟悉,不建议直接做这个,不然也只是照抄代码,不知道什么意思。

这里index类里面要定义两个函数 GET 和 POST,如果你缩进不对,会直接影响程序的逻辑。有可能你是复制了网上的代码,又手动添加了代码,空格和tab混用了。请重新打或者换一个编辑器。

这里有示例代码,你仔细再对照一下 https://github.com/crossin/MovieSite
作者: Rune    时间: 2017-6-26 21:24
crossin先生 发表于 2017-6-25 14:40
你这缩进还是混乱的。不知道你之前基础课程里的内容是否有都看过,包括缩进的含义、函数的定义、面向对象 ...

感谢先生耐心的解答,我确实是从您的python基础教程一节课一节课看过来的,课后习题包括足球游戏都写了,我再仔细检查一下我的代码吧。 谢谢!
作者: 不会飞的hjh    时间: 2017-9-12 11:52
请问先生,为什么condition = r'title like "%'+data.title+r'%"' 中,用户输入的data 要写成data.tltle呢?换成data会显示格式错误,在数据库中的操作也是直接select * from movie where title like "%输入数据%"就可以了,求解
作者: crossin先生    时间: 2017-9-12 12:14
不会飞的hjh 发表于 2017-9-12 11:52
请问先生,为什么condition = r'title like "%'+data.title+r'%"' 中,用户输入的data 要写成data.tltle呢 ...

<input type="text" name="title" />

title是对应你的文本框
作者: 不会飞的hjh    时间: 2017-9-12 12:27
crossin先生 发表于 2017-9-12 12:14
title是对应你的文本框

原来是这样,谢谢先生
作者: fubixingwzy    时间: 2018-2-9 16:14
先生,这个问题弄得我头好疼,麻烦帮帮我,非常感谢!
跟着您的教程做完了这个电影网站,但是搜索这里还是有问题,我输入单个字搜索总是会出错,多个字就可以;点演员名子搜索的时候有的可以,有的却报错
演员探索 单字搜索
作者: crossin先生    时间: 2018-2-9 16:23
fubixingwzy 发表于 2018-2-9 16:14
先生,这个问题弄得我头好疼,麻烦帮帮我,非常感谢!
跟着您的教程做完了这个电影网站,但是搜索这里还是有问题 ...

这个不清楚,从你报错也没看出什么问题。你把拿到的参数输出一下看看吧,可能是文本编码的问题
作者: 2894386560    时间: 2018-5-9 21:06
按照教程做到这课,也是碰到了405 Method Not Allowed 的问题,百度之后也没能解决掉这个问题,在网页搜索之后得不到结果只能得到None。有点头疼不太懂为什么出现这个问题。
把代码图片发上来,希望先生可以帮忙看看。

2.png (22.25 KB, 下载次数: 521)

2.png

1.png (13.02 KB, 下载次数: 529)

1.png

3.png (43.36 KB, 下载次数: 527)

3.png


作者: 2894386560    时间: 2018-5-9 21:10
2894386560 发表于 2018-5-9 21:06
按照教程做到这课,也是碰到了405 Method Not Allowed 的问题,百度之后也没能解决掉这个问题,在网页搜索 ...

我试过在数据库里搜   title like "%阿甘正传%"    是可以得到结果的。。

4.png (51.64 KB, 下载次数: 535)

4.png


作者: crossin先生    时间: 2018-5-10 14:42
2894386560 发表于 2018-5-9 21:06
按照教程做到这课,也是碰到了405 Method Not Allowed 的问题,百度之后也没能解决掉这个问题,在网页搜索 ...

报405是没有找到POST方法
没看出代码问题

唯一可能的是,你把你代码里 空格和Tab 统一了之后再重新试下
作者: 2894386560    时间: 2018-5-10 15:40
crossin先生 发表于 2018-5-10 14:42
报405是没有找到POST方法
没看出代码问题

额,按照先生说的统一了空格和Tab之后果然就可以搜索了……没想到会出现这种问题……
十分感谢先生!
作者: boat    时间: 2019-8-17 08:33
这一课最大的问题是编码的问题,出现中文都会报错。
首先是pycharm里,要确认是utf8编码
可以参考文章https://segmentfault.com/q/1010000007395685/检查一下自己的默认编码格式
然后是两个html文档,记事本的默认编码格式不是utf8,可以用其他的来修改。我用了notepad++
最后是MySQL的默认编码格式。这个真的费了我很长时间,一直报错,最后终于找到了下面的文章,成功解决问题。
参考文章https://blog.csdn.net/qq_31683121/article/details/73371697
作者: crossin先生    时间: 2019-8-20 22:23
boat 发表于 2019-8-17 08:33
这一课最大的问题是编码的问题,出现中文都会报错。
首先是pycharm里,要确认是utf8编码
可以参考文章https ...

webpy的坑确实有点多




欢迎光临 Crossin的编程教室 (https://bbs.crossincode.com/) Powered by Discuz! X2.5