1.搜索界面开发
1.1 模糊查询
文件地址:pycharm-
class SightListView(ListView):
    paginate_by = 5
    def 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=objects
        totalItem.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.isHot
    isTop.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.obj
        return {
            #...
            '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.city
    if(sightDetail.value.area){
        area += sightDetail.value.area
    }
    if(sightDetail.value.town){
        area += sightDetail.value.town
    }
    return area
})2.7 更改静态地址为动态
景点大图:

景点介绍:

地址信息:

门票列表:














![[ 内网渗透实战篇-2 ] 父域子域架构的搭建与安装域环境判断域控定位组策略域森林架构配置信任关系](https://i-blog.csdnimg.cn/direct/fdcc9a90c40f450f9925b9729debe379.png)





