1.搜索界面开发
1.1 模糊查询
文件地址:pycharm-
class SightListView(ListView):paginate_by = 5def get_queryset(self):#is_valid=True:表中is_valid列,有值则被查询出来query = Q(is_valid=True)#1.获得热门景点is_hot = self.request.GET.get('is_hot',None)if is_hot:query = query & Q(is_hot=True)#2.获得精选景点is_top = self.request.GET.get('is_top',None)if is_top:query = query & Q(is_top=True)#3.景点名称搜索👇#获取前端传来的 用于搜索的景点关键字name = self.request.GET.get('name',None)if name:query = query & Q(name__icontains=name) #名字列模糊查询👆queryset = Sight.objects.filter(query)return queryset#用于分页函数def get_paginate_by(self, queryset):#用于控制 从前端传递过来的每一页显示条数的函数page_size = self.request.GET.get('limit',None)return page_size or self.paginate_by #对分页做一个重写
1.2 访问服务端接口【获取数据】
<script setup>
import { ajax } from '@/utils/ajax';
import { SightApis } from '@/utils/apis';
//访问服务端接口,获取数据
const getDataList=()=>{ajax.get(SightApis.sightListUrl,{params:{name:sightName.value,page:currentPage.value,limit:perPage.value}}).then(({data:{meta,objects}})=>{dataList.value=objectstotalItem.value = meta.total_count})
}
onMounted(()=>{getDataList()
})
</script>
1.3 搜索函数
if语句,判断搜索框中是否输入数据,如果没有数据则提示"说话!"
<script setup>
import { showToast } from 'vant';//提示框组件
//搜索函数
const onSearch = ()=>{// console.log('onSearch')if(!sightName.value){showToast('请输入搜索词')return}//重置数据dataList.value=[]currentPage.value=1//执行查询getDataList()
}
</script>
1.4 清空并换新列表函数
<script setup>
//清空列表函数
const clear =()=>{//重置数据dataList.value=[]currentPage.value=1//执行查询getDataList()
}
const pageChange=()=>{getDataList()
}
</script>
<template><div class="page-search"><!-- 分页 --><van-pagination v-model="currentPage":total-items="totalItem":items-per-page="perPage"@change="pageChange"></van-pagination></div>
</template>
1.5 调整搜索界面布局
<style lang="less">.page-search{padding-bottom: 60px;.sight-list{padding: 10px;background-color: aliceblue;margin-bottom: 10px;}}
</style>
1.6 分类显示
点击不同的按钮进入不同的搜索界面【热门/推荐景点】
<script setup>
import { useRoute,useRouter } from 'vue-router';
const route = useRoute()
const router = useRouter()
//热门景点和精选景点
const isHot = ref('')
const isTop = ref('')
onMounted(()=>{isHot.value = route.query.isHotisTop.value = route.query.isTop
})
</script>
<template><div class="page-search"><!-- 判断显示热门景点还是精选景点 --><h2 v-if="isHot">热门推荐</h2><h2 v-if="isTop">精选推荐</h2><!-- 底部导航 --><TripFooter v-if="!(isHot||isTop)"/></div>
</template>
1.7 返回主界面
<script setup>
const goBack = ()=>{router.go(-1)
}
</script>
<template><div class="page-search"><!-- 标题 --><van-nav-bar title="搜索景点" left-text="返回" @click="goBack" v-if="isHot||isTop"/><van-nav-bar title="搜索景点" v-else/></div>
</template>
1.8 “更多”按键功能跳转
1.8.1 Fine.vue推荐景点
1.8.2 Hot.vue热门景点
2.景点接口数据联调
1.阅读接口文档 2.配置接口地址 3.使用axios获取数据 4.将数据至到模型层
2.1 服务端获取评论信息
数据模型文件
该文件用于统一服务端与数据库端的数据格式
“抗拒不匹配”,数据库端以表的方式表示数据,服务端以对象等方式表示数据
为了使两者数据统一,因此需要数据模型做规范
class Sight(CommonModel):#....@property#获得评论总数def comment_count(self):return self.comments.filter(is_valid=True).count()@property#获得景点图片总数def image_count(self):return self.images.filter(is_valid=True).count()
重构响应对象
重构原因:服务端提供了众多接口用于响应数据,
为了便于前端能够统一处理这些数据,需要将响应的数据统一格式。
以上,成为重构响应对象(序列化)
文件地址:sight/serializers.py
class SightDetailSerializers(BaseSerializer):#景点详情def to_dict(self):obj = self.objreturn {#...'comment_count': obj.comment_count,#获得景点评论数量'image_count': obj.image_count#获得景点图片数量}
2.2 配置接口
文件地址:src\utils\apis.js
//景点相关的接口
const SightApis = {//访问服务端的接口地址//访问景点列表sightListUrl:apiHost+"/sight/sight/list/",//访问景点详情sightDetailUrl:apiHost+"/sight/sight/detail/#{id}/",//门票列表sightTicketUrl:apiHost+"/sight/ticket/list/#{id}/",
}
再调整一下路由:
{path:'/sight/comment/:id',name:'SightComment',component:SightComment},
2.3 控制跳转
import useroute/userouter:用于控制页面跳转工具,传值工具;
goBack:返回前一页。
<script setup>
import {useRoute, useRouter} from 'vue-router'
import { ajax } from '@/utils/ajax';
import { SightApis } from '@/utils/apis';const router = useRouter()
const route = useRoute()const goBack = ()=>{router.go(-1)
}
</script>
2.4 获取景点详情信息
{}:用于表示对象,类似于python字段,由于服务端响应的数据是对象的格式,因此使用{}承载
replace:替换api/sight/sight/detail/#{id}中的id值
route.params.id: 获取地址栏携带id值
const sightDetail = ref({})
const getSightDetail = ()=>{const url = SightApis.sightDetailUrl.replace('#{id}',route.params.id)ajax.get(url).then(({data})=>{sightDetail.value = data})
}onMounted(()=>{getSightDetail()
})
2.5 获取景点门票信息
const ticketList = ref([])
const getTicketList = ()=>{const url = SightApis.sightTicketUrl.replace('#{id}',route.params.id)ajax.get(url).then(({data:{objects}})=>{ticketList.value = objects})
}
onMounted(()=>{getTicketList()
})
2.6 获取景点地址
computed计算属性,用于数据处理的函数,如何返回数据进行格式化
const fullArea = computed(()=>{let area = sightDetail.value.province+sightDetail.value.cityif(sightDetail.value.area){area += sightDetail.value.area}if(sightDetail.value.town){area += sightDetail.value.town}return area
})
2.7 更改静态地址为动态
景点大图:
景点介绍:
地址信息:
门票列表: