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%2522164398650116780271539703%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=164398650116780271539703&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-122736816.nonecase&utm_term=%E8%B7%A8%E5%9F%9F&spm=1018.2226.3001.4450c. element-ui+axios安装以及使用

element-ui+axios的使用https://blog.csdn.net/qq_52385631/article/details/122677133?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164398666516780265485172%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=164398666516780265485172&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-122677133.nonecase&utm_term=vue&spm=1018.2226.3001.4450

一. 前端配置

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字段的,这边来

序列化器中自定义外键返回值icon-default.png?t=M0H8https://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组件布局,子组件名用逗号分隔Stringsizesprevpagernextjumper->totalslot'prev, pager, next, jumper, ->, total'
page-sizes每页显示个数选择器的选项设置number[][10, 20, 30, 40, 50, 100]

Events(事件)

事件名称说明回调参数
size-changepageSize 改变时会触发每页条数
current-changecurrentPage 改变时会触发当前页

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>

效果截图

 

Logo

前往低代码交流专区

更多推荐