Django框架项目之搜索功能——搜索导航栏、搜索后台接口、搜索页面
文章目录
1-搜索导航栏
Header搜索组件:选择性CV
router/index.js
import SearchCourse from '../views/SearchCourse.vue'
const routes = [
// ...
{
path: '/course/search',
name: 'search-course',
component: SearchCourse,
},
];
Header.vue
<form class="search">
<div class="tips" v-if="is_search_tip">
<span @click="search_action('Python')">Python</span>
<span @click="search_action('Linux')">Linux</span>
</div>
<input type="text" :placeholder="search_placeholder" @focus="on_search" @blur="off_search" v-model="search_word">
<button type="button" class="glyphicon glyphicon-search" @click="search_action(search_word)"></button>
</form>
<script>
export default {
data() {
return {
is_search_tip: true,
search_placeholder: '',
search_word: ''
}
},
methods: {
search_action(search_word) {
if (!search_word) {
this.$message('请输入要搜索的内容');
return
}
if (search_word !== this.$route.query.word) {
this.$router.push(`/course/search?word=${search_word}`);
}
this.search_word = '';
},
on_search() {
this.search_placeholder = '请输入想搜索的课程';
this.is_search_tip = false;
},
off_search() {
this.search_placeholder = '';
this.is_search_tip = true;
},
},
}
</script>
<style scoped>
.search {
float: right;
position: relative;
margin-top: 22px;
margin-right: 10px;
}
.search input, .search button {
border: none;
outline: none;
background-color: white;
}
.search input {
border-bottom: 1px solid #eeeeee;
}
.search input:focus {
border-bottom-color: orange;
}
.search input:focus + button {
color: orange;
}
.search .tips {
position: absolute;
bottom: 3px;
left: 0;
}
.search .tips span {
border-radius: 11px;
background-color: #eee;
line-height: 22px;
display: inline-block;
padding: 0 7px;
margin-right: 3px;
cursor: pointer;
color: #aaa;
font-size: 14px;
}
.search .tips span:hover {
color: orange;
}
</style>
2-搜索后台接口
路由:course/urls.py
router.register('search', views.SearchCourseViewSet, 'search') # 搜索课程
视图:course/views.py
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from rest_framework.filters import SearchFilter
from . import models, serializers
# 搜索课程接口
class SearchCourseViewSet(GenericViewSet, ListModelMixin):
queryset = models.Course.objects.filter(is_delete=False, is_show=True).all()
serializer_class = serializers.CourseSerializer
pagination_class = pagination.PageNumberPagination
filter_backends = [SearchFilter]
search_fields = ['name']
3-搜索页面
SearchCourse搜索页面
<template>
<div class="search-course course">
<Header/>
<!-- 课程列表 -->
<div class="main">
<div v-if="course_list.length > 0" class="course-list">
<div class="course-item" v-for="course in course_list" :key="course.name">
<div class="course-image">
<img :src="course.course_img" alt="">
</div>
<div class="course-info">
<h3>
<router-link :to="'/free/detail/'+course.id">{{course.name}}</router-link>
<span><img src="@/assets/img/avatar1.svg" alt="">{{course.students}}人已加入学习</span></h3>
<p class="teather-info">
{{course.teacher.name}} {{course.teacher.title}} {{course.teacher.signature}}
<span v-if="course.sections>course.pub_sections">共{{course.sections}}课时/已更新{{course.pub_sections}}课时</span>
<span v-else>共{{course.sections}}课时/更新完成</span>
</p>
<ul class="section-list">
<li v-for="(section, key) in course.section_list" :key="section.name"><span
class="section-title">0{{key+1}} | {{section.name}}</span>
<span class="free" v-if="section.free_trail">免费</span></li>
</ul>
<div class="pay-box">
<div v-if="course.discount_type">
<span class="discount-type">{{course.discount_type}}</span>
<span class="discount-price">¥{{course.real_price}}元</span>
<span class="original-price">原价:{{course.price}}元</span>
</div>
<span v-else class="discount-price">¥{{course.price}}元</span>
<span class="buy-now">立即购买</span>
</div>
</div>
</div>
</div>
<div v-else style="text-align: center; line-height: 60px">
没有搜索结果
</div>
<div class="course_pagination block">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="filter.page"
:page-sizes="[2, 3, 5, 10]"
:page-size="filter.page_size"
layout="sizes, prev, pager, next"
:total="course_total">
</el-pagination>
</div>
</div>
</div>
</template>
<script>
import Header from '../components/Header'
export default {
name: "SearchCourse",
components: {
Header,
},
data() {
return {
course_list: [],
course_total: 0,
filter: {
page_size: 10,
page: 1,
search: '',
}
}
},
created() {
this.get_course()
},
watch: {
'$route.query' () {
this.get_course()
}
},
methods: {
handleSizeChange(val) {
// 每页数据量发生变化时执行的方法
this.filter.page = 1;
this.filter.page_size = val;
},
handleCurrentChange(val) {
// 页码发生变化时执行的方法
this.filter.page = val;
},
get_course() {
// 获取搜索的关键字
this.filter.search = this.$route.query.word || this.$route.query.wd;
// 获取课程列表信息
this.$axios.get(`${this.$settings.base_url}/course/search/`, {
params: this.filter
}).then(response => {
// 如果后台不分页,数据在response.data中;如果后台分页,数据在response.data.results中
this.course_list = response.data.results;
this.course_total = response.data.count;
}).catch(() => {
this.$message({
message: "获取课程信息有误,请联系客服工作人员"
})
})
}
}
}
</script>
<style scoped>
.course {
background: #f6f6f6;
}
.course .main {
width: 1100px;
margin: 35px auto 0;
}
.course .condition {
margin-bottom: 35px;
padding: 25px 30px 25px 20px;
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 4px 0 #f0f0f0;
}
.course .cate-list {
border-bottom: 1px solid #333;
border-bottom-color: rgba(51, 51, 51, .05);
padding-bottom: 18px;
margin-bottom: 17px;
}
.course .cate-list::after {
content: "";
display: block;
clear: both;
}
.course .cate-list li {
float: left;
font-size: 16px;
padding: 6px 15px;
line-height: 16px;
margin-left: 14px;
position: relative;
transition: all .3s ease;
cursor: pointer;
color: #4a4a4a;
border: 1px solid transparent; /* transparent 透明 */
}
.course .cate-list .title {
color: #888;
margin-left: 0;
letter-spacing: .36px;
padding: 0;
line-height: 28px;
}
.course .cate-list .this {
color: #ffc210;
border: 1px solid #ffc210 !important;
border-radius: 30px;
}
.course .ordering::after {
content: "";
display: block;
clear: both;
}
.course .ordering ul {
float: left;
}
.course .ordering ul::after {
content: "";
display: block;
clear: both;
}
.course .ordering .condition-result {
float: right;
font-size: 14px;
color: #9b9b9b;
line-height: 28px;
}
.course .ordering ul li {
float: left;
padding: 6px 15px;
line-height: 16px;
margin-left: 14px;
position: relative;
transition: all .3s ease;
cursor: pointer;
color: #4a4a4a;
}
.course .ordering .title {
font-size: 16px;
color: #888;
letter-spacing: .36px;
margin-left: 0;
padding: 0;
line-height: 28px;
}
.course .ordering .this {
color: #ffc210;
}
.course .ordering .price {
position: relative;
}
.course .ordering .price::before,
.course .ordering .price::after {
cursor: pointer;
content: "";
display: block;
width: 0px;
height: 0px;
border: 5px solid transparent;
position: absolute;
right: 0;
}
.course .ordering .price::before {
border-bottom: 5px solid #aaa;
margin-bottom: 2px;
top: 2px;
}
.course .ordering .price::after {
border-top: 5px solid #aaa;
bottom: 2px;
}
.course .ordering .price_up::before {
border-bottom-color: #ffc210;
}
.course .ordering .price_down::after {
border-top-color: #ffc210;
}
.course .course-item:hover {
box-shadow: 4px 6px 16px rgba(0, 0, 0, .5);
}
.course .course-item {
width: 1100px;
background: #fff;
padding: 20px 30px 20px 20px;
margin-bottom: 35px;
border-radius: 2px;
cursor: pointer;
box-shadow: 2px 3px 16px rgba(0, 0, 0, .1);
/* css3.0 过渡动画 hover 事件操作 */
transition: all .2s ease;
}
.course .course-item::after {
content: "";
display: block;
clear: both;
}
/* 顶级元素 父级元素 当前元素{} */
.course .course-item .course-image {
float: left;
width: 423px;
height: 210px;
margin-right: 30px;
}
.course .course-item .course-image img {
max-width: 100%;
max-height: 210px;
}
.course .course-item .course-info {
float: left;
width: 596px;
}
.course-item .course-info h3 a {
font-size: 26px;
color: #333;
font-weight: normal;
margin-bottom: 8px;
}
.course-item .course-info h3 span {
font-size: 14px;
color: #9b9b9b;
float: right;
margin-top: 14px;
}
.course-item .course-info h3 span img {
width: 11px;
height: auto;
margin-right: 7px;
}
.course-item .course-info .teather-info {
font-size: 14px;
color: #9b9b9b;
margin-bottom: 14px;
padding-bottom: 14px;
border-bottom: 1px solid #333;
border-bottom-color: rgba(51, 51, 51, .05);
}
.course-item .course-info .teather-info span {
float: right;
}
.course-item .section-list::after {
content: "";
display: block;
clear: both;
}
.course-item .section-list li {
float: left;
width: 44%;
font-size: 14px;
color: #666;
padding-left: 22px;
/* background: url("路径") 是否平铺 x轴位置 y轴位置 */
background: url("/src/assets/img/play-icon-gray.svg") no-repeat left 4px;
margin-bottom: 15px;
}
.course-item .section-list li .section-title {
/* 以下3句,文本内容过多,会自动隐藏,并显示省略符号 */
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
display: inline-block;
max-width: 200px;
}
.course-item .section-list li:hover {
background-image: url("/src/assets/img/play-icon-yellow.svg");
color: #ffc210;
}
.course-item .section-list li .free {
width: 34px;
height: 20px;
color: #fd7b4d;
vertical-align: super;
margin-left: 10px;
border: 1px solid #fd7b4d;
border-radius: 2px;
text-align: center;
font-size: 13px;
white-space: nowrap;
}
.course-item .section-list li:hover .free {
color: #ffc210;
border-color: #ffc210;
}
.course-item {
position: relative;
}
.course-item .pay-box {
position: absolute;
bottom: 20px;
width: 600px;
}
.course-item .pay-box::after {
content: "";
display: block;
clear: both;
}
.course-item .pay-box .discount-type {
padding: 6px 10px;
font-size: 16px;
color: #fff;
text-align: center;
margin-right: 8px;
background: #fa6240;
border: 1px solid #fa6240;
border-radius: 10px 0 10px 0;
float: left;
}
.course-item .pay-box .discount-price {
font-size: 24px;
color: #fa6240;
float: left;
}
.course-item .pay-box .original-price {
text-decoration: line-through;
font-size: 14px;
color: #9b9b9b;
margin-left: 10px;
float: left;
margin-top: 10px;
}
.course-item .pay-box .buy-now {
width: 120px;
height: 38px;
background: transparent;
color: #fa6240;
font-size: 16px;
border: 1px solid #fd7b4d;
border-radius: 3px;
transition: all .2s ease-in-out;
float: right;
text-align: center;
line-height: 38px;
position: absolute;
right: 0;
bottom: 5px;
}
.course-item .pay-box .buy-now:hover {
color: #fff;
background: #ffc210;
border: 1px solid #ffc210;
}
.course .course_pagination {
margin-bottom: 60px;
text-align: center;
}
</style>
Django框架项目之搜索功能——搜索导航栏、搜索后台接口、搜索页面的更多相关文章
- Vue 事件监听实现导航栏吸顶效果(页面滚动后定位)
Vue 事件监听实现导航栏吸顶效果(页面滚动后定位) Howie126313 关注 2017.11.19 15:05* 字数 100 阅读 3154评论 0喜欢 0 所说的吸顶效果就是在页面没有滑动之 ...
- Bootstrap框架(基础篇)之按钮,网格,导航栏,下拉菜单
一,按钮 注意:虽然在Bootstrap框架中使用任何标签元素都可以实现按钮风格,但个人并不建议这样使用,为了避免浏览器兼容性问题,个人强烈建议使用button或a标签来制作按钮. 框架中提供了基础按 ...
- Boostrap导航栏跳转到其他页面或外部链接
想要在boostrap下增加一个标签a,并设置其href属性来实现跳转功能(具体是想在导航栏中添加,点击某个导航栏部件时跳转至其他页面),但是发现事情并不是想象中的那么简单: “Bootstrap为这 ...
- Ios导航栏返回到指定的页面
在自己的项目实现中有这样的一个需求.一般情况下我们的导航栏返回按钮,是上个页面跳转过来,点击返回按钮返回到上来界面.但是在实际需求中有的并不是这么简单的.有的界面返回是只确定的界面.所以当时自己在实现 ...
- (GoRails)在导航栏增加自动的搜索功能(jquery插件:easyautocomplete)(gem 'ransack' 搜索对象4000✨)
Global Autocomplete Search 需要用到一个JQuery插件和一个搜索对象的gem EasyAutocomplete jQuery插件: https://github.com/p ...
- django框架项目 国际化和本地化的实现方法
转自 https://blog.csdn.net/scissors0707/article/details/79042458 Django国际化 所谓的国际化,是指使用不同语言的用户在访问同一个网站页 ...
- python实战项目练习-Django商城项目之注册功能实现
设计到的前端知识 项目的前端页面使用vue来实现局部刷新,通过数据的双向绑定实现与用户的交互,下面来看一下需求,在用户输入内容后,前端需要做一些简单的规则校验,我们希望在在用户输入后能够实时检测,如果 ...
- 使用Pycharm开发python下django框架项目生成的文件解释
目录MyDjangoProject下表示工程的全局配置,分别为setttings.py.urls.py和wsgi.py,1.其中setttings.py包括了系统的数据库配置.应用配置和其他配置,2. ...
- easyUI框架之学习2--添加左侧导航栏
<head> function addTab(title, url) { if ($('#tableContainer').tabs('exists', title)) { $('#tab ...
- 04 uni-app框架学习:禁用顶部原生导航栏
1.在pages.json中配置 比如要首页禁用 就在首页这个选项里 加上这几句代码 2.效果如下
随机推荐
- 2023-06-14:我们从二叉树的根节点 root 开始进行深度优先搜索。 在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度) 然后输出该节点的值。(如果节点的深度为 D,则其
2023-06-14:我们从二叉树的根节点 root 开始进行深度优先搜索. 在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度) 然后输出该节点的值.(如果节点的深度为 D,则其 ...
- [ARM 汇编]高级部分—ARM汇编编程实战—3.3.1 嵌入式系统的基本概念
嵌入式系统是一种特殊的计算机系统,通常用于执行特定的任务.它通常包含一个或多个微处理器.存储器和外围设备.与通用计算机系统相比,嵌入式系统具有体积小.功耗低.成本低和实时性强等特点.在这一部分,我们将 ...
- docker中的mysql中文乱码解决办法
博主最近在做谷粒商城,因为要使用docker安装mysql,但是由于安装的时候没有指定mysql的数据库的utf8格式,导致插入的时候就出现了中文是问号的情况,到处百度终于解决,于是打算记录一下自己的 ...
- PostgreSQL 12 文档: 部分 II. SQL 语言
部分 II. SQL 语言 这部份描述在PostgreSQL中SQL语言的使用.我们从描述SQL的一般语法开始,然后解释如何创建保存数据的结构.如何填充数据库以及如何查询它.中间的部分列出了在SQL命 ...
- 前端Vue自定义带历史记录的搜索框组件searchBar 支持搜索输入框清空 搜索历史存储记录清除
前端Vue自定义带历史记录的搜索框组件searchBar 支持搜索输入框清空 搜索历史存储记录清除,下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/p ...
- Unity UGUI的所有组件的介绍及使用
Unity UGUI的所有组件的介绍及使用 本文将介绍Unity UGUI中的各个组件,包括它们的具体介绍.用途 1. Text(文本) 介绍:Text组件用于在UI界面上显示文本内容. 用途:常用于 ...
- 基于AidLux的自动驾驶智能预警应用方案
### 1. 自动驾驶感知算法及AidLux相关方案介绍 #### 1.1自动驾驶 自动驾驶汽车,又称无人驾驶车.电脑驾驶车.无人车.自驾车,是一种需要驾驶员辅助驾驶或者完全不需要操控的车辆.作为自动 ...
- C语言基础--逻辑判断和循环
目录 一.储存标识符 1.auto 2.register 3.static 4.const 二.运算符 1.逻辑运算符 2.位运算符 3.运算符 4.三元运算符 三.选择结构 1.if判断 1.1 i ...
- .NET for Apache Spark 调试
.NET for Apache Spark 调试 官方文档:在 Windows 上部署 .NET for Apache Spark 应用程序 | Microsoft Learn 打开"新命令 ...
- css使用背景灵活展示雪碧图
雪碧图是把各种小图标集合在一起的png图片,通过background-position来展示雪碧图中不同位置的小图标,比如以下图片,在项目中要用到的小图标很多,如果每一个图标都作为一个png或者jpg ...