drf----过滤组件&分页组件的快速使用,后端drf+前端vue
0. 准备a. django2.2+drf+vue+跨域+ide(pycharm/...)b. 跨域实现前后端跨域前后端实现跨域https://blog.csdn.net/qq_52385631/article/details/122736816?ops_request_misc=%257B%2522request%255Fid%2522%253A%252216439865011678027153
·
0. 准备
a. django2.2+drf+vue+跨域+ide(pycharm)
b. 跨域
实现前后端跨域
一. 前端配置
a. 根据上述文章,进行跨域的配置以及element-ui,axios的安装
b. 清除HelloWord和其相关的内容(为了节目效果,根路由是我们的界面)
c. 设置vue快捷启动
二. 后端接口(基础接口)
a. model.py
from django.db import models
# Create your models here.
class Category(models.Model):
category = models.CharField(verbose_name='标题', max_length=11)
uid = models.CharField(max_length=32, verbose_name='index', help_text='element-ui的index需要一个str')
def __str__(self):
return self.category
class Moves(models.Model):
title = models.CharField(verbose_name='标题', max_length=32)
category = models.ForeignKey(verbose_name='分类', to=Category, on_delete=models.DO_NOTHING)
b. urls.py
path('text/', views.FilterPageListAPIView.as_view()),
c. view.py
from django.shortcuts import render
from . import models
from . import serializer
from rest_framework.generics import ListAPIView
class FilterPageListAPIView(ListAPIView):
queryset = models.Category.objects.all()
serializer_class = serializer.FilterPageModelSerializer
d. serializer.py
from rest_framework import serializers
from .views import models
class FilterPageModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Category
fields = '__all__'
e. 测试接口(导航栏组件,index必须是str类型,id不能满足,使用我在数据库新增了一个uid,str类型)
<template>
<div style="width: 560px;margin: 0 auto">
<el-menu
:default-active="activeIndex2"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<el-menu-item :index="val.uid" v-for="(val,index) in category_data"
v-model="category_id"
:key="val.id">{{ val.category }}
</el-menu-item>
</el-menu>
</div>
</template>
<script>
export default {
name: "FilterPage",
data() {
return {
// 默认选中
activeIndex2: '1',
// 用来接受后端的数据
category_data: [],
// 参数
filter_dic: {},
};
},
created() {
// 一般在create里面进行异步请求
this.get_category_data();
},
methods: {
// 跳转路由
handleSelect(key, keyPath) {
// key:index,keyPath:路径
console.log(key, keyPath);
},
// 定义获取分类的函数
get_category_data() {
// 发送请求
this.$axios.get(`${this.$settings.host}/text/`, {
params: {} // 此参数必须是字典,第二种传参方式,类似于直接在路由上?username='xx'
})
.then((res) => {
// 成功之后执行
this.category_data = res.data
}).catch((errors) => {
})
},
}
}
</script>
<style scoped>
</style>
f. 测试截图
三. 过滤
1. 在当前项目中安装 字段过滤排序
pip install django-filter
2. 在settings.py配置文件中增加过滤后端的设置:
INSTALLED_APPS = [
...
'django_filters', # 需要注册应用,
]
3. 视图中使用
from django.shortcuts import render
from . import models
from . import serializer
from rest_framework.generics import ListAPIView
# 1. 导包过滤组件
from django_filters.rest_framework import DjangoFilterBackend
class MovesListAPIView(ListAPIView):
"""电影视图"""
queryset = models.Moves.objects.all()
serializer_class = serializer.MovesModelSerializer
# 2. 配置顾虑使用的范围
filter_backends = [DjangoFilterBackend, ]
# 3. 配置过滤字段(以什么字段过滤)
filter_fields = ('category',)
4.sealizer.py
class MovesModelSerializer(serializers.ModelSerializer):
# 利用source字段
category_name = serializers.CharField(source='category.category')
category_uid = serializers.CharField(source='category.uid')
class Meta:
model = models.Moves
fields = ['id', 'title', 'category_name', 'category_uid']
5.url
path('filter_text/', views.MovesListAPIView.as_view()),
ps:不清楚source字段的,这边来
序列化器中自定义外键返回值https://blog.csdn.net/qq_52385631/article/details/122786527?spm=1001.2014.3001.55016. 前端发送请求获取数据
<template>
<div style="width: 560px;margin: 0 auto">
<!--分类-->
<el-menu
:default-active="activeIndex2"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<el-menu-item
:index="val.uid" v-for="(val,index) in category_data"
:key="val.id">{{ val.category }}
</el-menu-item>
</el-menu>
<!-- moves列表页 -->
<el-card class="box-card" shadow="hover" v-for="(m_val,m_index) in moves_data" :key="m_val.id">
<div class="text item">
<div>序号:{{ m_val.category_uid }}</div>
<div>名称:{{ m_val.title }}</div>
<div>分类:{{ m_val.category_name }}</div>
</div>
</el-card>
</div>
</template>
<script>
export default {
name: "FilterPage",
data() {
return {
// 默认选中
activeIndex2: '1',
// 用来接受后端的数据
category_data: [],
moves_data: [],
// 参数
filter_dic: {},
};
},
created() {
// 一般在create里面进行异步请求
this.get_category_data();
this.get_moves();
},
methods: {
// 跳转路由
handleSelect(key, keyPath) {
// key:index,keyPath:路径
if (key === '1') {
// uid===1为全部
delete this.filter_dic['category']
this.get_moves();
} else {
// 在字典中的封装数据
this.filter_dic.category = key
this.get_moves();
}
},
// 定义获取分类的函数
get_category_data() {
// 发送请求
this.$axios.get(`${this.$settings.host}/text/`, {
params: {} // 此参数必须是字典,第二种传参方式,类似于直接在路由上?username='xx'
})
.then((res) => {
// 成功之后执行
this.category_data = res.data
}).catch((errors) => {
})
},
// 获取moves
get_moves() {
// 发送请求
this.$axios.get(`${this.$settings.host}/filter_text/`, {
params: this.filter_dic // 此参数必须是字典,第二种传参方式,类似于直接在路由上?username='xx'
})
.then((res) => {
// 成功之后执行
this.moves_data = res.data
}).catch((errors) => {
})
},
}
}
</script>
<style scoped>
.text {
font-size: 14px;
}
.item {
padding: 18px 0;
}
.box-card {
width: 480px;
}
</style>
四:过滤+分页
1. element-ui分页属性介绍
Attributes(属性)
total | 总条目数 | number | — | — |
layout | 组件布局,子组件名用逗号分隔 | String | sizes , prev , pager , next , jumper , -> , total , slot | 'prev, pager, next, jumper, ->, total' |
page-sizes | 每页显示个数选择器的选项设置 | number[] | — | [10, 20, 30, 40, 50, 100] |
Events(事件)
事件名称 | 说明 | 回调参数 |
---|---|---|
size-change | pageSize 改变时会触发 | 每页条数 |
current-change | currentPage 改变时会触发 | 当前页 |
2.后端接口
url
path('filter_text/', views.MovesListAPIView.as_view()),
view
from django.shortcuts import render
from . import models
from . import serializer
from rest_framework.generics import ListAPIView
# 1. 导包过滤组件
from django_filters.rest_framework import DjangoFilterBackend
# 导入分页组件(restframework自带的)
from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
page_size = 5 # 每页显示的个数
page_query_param = 'page' # 查询参数 ?page=3
page_size_query_param = 'size' # 前端自定义查询的数量,?size=10
max_page_size = 100 # 前端自定义显示的字段条数的最大限制
class MovesListAPIView(ListAPIView):
"""电影视图"""
queryset = models.Moves.objects.all()
serializer_class = serializer.MovesModelSerializer
# 2. 配置顾虑使用的范围
filter_backends = [DjangoFilterBackend, ]
# 3. 配置过滤字段(以什么字段过滤)
filter_fields = ('category',)
# 分页配置
pagination_class = MyPageNumberPagination
serializer
from rest_framework import serializers
from .views import models
class MovesModelSerializer(serializers.ModelSerializer):
# 利用source字段
category_name = serializers.CharField(source='category.category')
category_uid = serializers.CharField(source='category.uid')
class Meta:
model = models.Moves
fields = ['id', 'title', 'category_name', 'category_uid']
前端
<template>
<div style="width: 560px;margin: 0 auto">
<!--分类-->
<el-menu
:default-active="activeIndex2"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<el-menu-item
:index="val.uid" v-for="(val,index) in category_data"
:key="val.id">{{ val.category }}
</el-menu-item>
</el-menu>
<!-- 分页-->
<div>
<el-pagination
@size-change="handleSizeChange"
:page-sizes="[5, 8, 10, 20]"
@current-change="handleCurrentChange"
background
layout="total, sizes, prev, pager, next, jumper"
:page-size="5"
:total="totals">
</el-pagination>
</div>
<!-- moves列表页 -->
<el-card class="box-card" shadow="hover" v-for="(m_val,m_index) in moves_data" :key="m_val.id">
<div class="text item">
<div>序号:{{ m_val.category_uid }}</div>
<div>名称:{{ m_val.title }}</div>
<div>分类:{{ m_val.category_name }}</div>
</div>
</el-card>
</div>
</template>
<script>
export default {
name: "FilterPage",
data() {
return {
// 默认选中
activeIndex2: '1',
// 用来接受后端的数据
category_data: [],
moves_data: [],
// 参数
filter_dic: {},
totals: 0,
};
},
created() {
// 一般在create里面进行异步请求
this.get_category_data();
this.get_moves();
},
methods: {
// 跳转路由
handleSelect(key, keyPath) {
// key:index,keyPath:路径
if (key === '1') {
// uid===1为全部
delete this.filter_dic['category']
this.get_moves();
} else {
// 在字典中的封装数据
this.filter_dic.category = key
this.get_moves();
}
},
// 定义获取分类的函数
get_category_data() {
// 发送请求
this.$axios.get(`${this.$settings.host}/text/`, {
params: {} // 此参数必须是字典,第二种传参方式,类似于直接在路由上?username='xx'
})
.then((res) => {
// 成功之后执行
this.category_data = res.data
}).catch((errors) => {
})
},
// 获取moves
get_moves() {
// 发送请求
this.$axios.get(`${this.$settings.host}/filter_text/`, {
params: this.filter_dic // 此参数必须是字典,第二种传参方式,类似于直接在路由上?username='xx'
})
.then((res) => {
// 成功之后执行
// this.moves_data = res.data
// 现在的数据在data.results里面,必须进行修改,不然会报name...这个错
this.moves_data = res.data.results
// 总页码数
this.totals = res.data.count
}).catch((errors) => {
})
},
// 点击页码触发函数
handleCurrentChange(cpage) {
// cpage:当前页码数
this.filter_dic.page = cpage
this.get_moves();
},
// 自定义展示数据
handleSizeChange(size) {
this.filter_dic.size = size
this.get_moves();
}
}
}
</script>
<style scoped>
.text {
font-size: 14px;
}
.item {
padding: 18px 0;
}
.box-card {
width: 480px;
}
</style>
效果截图
更多推荐
已为社区贡献22条内容
所有评论(0)