如何实现前台主页搭建、后台轮播图接口设计及跨域问题解决,确保前后端互通与后端自主开发?

2026-05-05 21:332阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计3490个文字,预计阅读时间需要14分钟。

如何实现前台主页搭建、后台轮播图接口设计及跨域问题解决,确保前后端互通与后端自主开发?

今日内容概要:- 前台主页- 后台主页轮播图接口- 跨域问题详解- 前后端打通- 后端自定义配置- Git介绍和安装- 内容详细: 1. 前台主页:Home.vue - template - div class=home - Header/Header - Banner/Banner - 推荐课程

今日内容概要
  • 前台主页
  • 后台主页轮播图接口
  • 跨域问题详解
  • 前后端打通
  • 后端自定义配置
  • git介绍和安装
内容详细 1、前台主页 Homeviwe.vue

<template> <div class="home"> <Header></Header> <Banner></Banner> <!-- 推荐课程--> <div class="course"> <el-row> <el-col :span="6" v-for="(o, index) in 8" :key="o"> <el-card :body-style="{ padding: '0px' }" class="course_card"> <img src="tva1.sinaimg.cn/large/e6c9d24egy1h1g0zd133mj20l20a875i.jpg" class="image"> <div style="padding: 14px;"> <span>推荐的课程</span> <div class="bottom clearfix"> <time class="time">价格:100元</time> <el-button type="text" class="button">查看详情</el-button> </div> </div> </el-card> </el-col> </el-row> </div> <img src="tva1.sinaimg.cn/large/e6c9d24egy1h1g112oiclj224l0u0jxl.jpg" alt="" height="500px" width="100%"> <Footer></Footer> </div> </template> <script> import Footer from "@/components/Footer"; import Header from "@/components/Header"; import Banner from "@/components/Banner"; export default { name: 'HomeView', data() { return {} }, components: { Footer, Header, Banner } } </script> <style scoped> .time { font-size: 13px; color: #999; } .bottom { margin-top: 13px; line-height: 12px; } .button { padding: 0; float: right; } .image { width: 100%; display: block; } .clearfix:before, .clearfix:after { display: table; content: ""; } .clearfix:after { clear: both } .course { margin-left: 20px; margin-right: 20px; } .course_card { margin: 50px; } </style> 新建:\src\components\Footer.vue

<template> <div class="footer"> <ul> <li>关于我们</li> <li>联系我们</li> <li>商务合作</li> <li>帮助中心</li> <li>意见反馈</li> <li>新手指南</li> </ul> <p>Copyright © luffycity.com版权所有 | 京ICP备17072161号-1</p> </div> </template> <script> export default { name: "Footer" } </script> <style scoped> .footer { width: 100%; height: 128px; background: #25292e; color: #fff; } .footer ul { margin: 0 auto 16px; padding-top: 38px; width: 810px; } .footer ul li { float: left; width: 112px; margin: 0 10px; text-align: center; font-size: 14px; } .footer ul::after { content: ""; display: block; clear: both; } .footer p { text-align: center; font-size: 12px; } </style> 新建:\src\components\Banner.vue

<template> <div class="banner"> <el-carousel :interval="5000" arrow="always" height="400px"> <el-carousel-item v-for="item in 4" :key="item"> <img src="../assets/img/banner1.png" alt=""> </el-carousel-item> </el-carousel> </div> </template> <script> export default { name: "Banner" } </script> <style scoped> el-carousel-item { height: 400px; min-width: 1200px; } .el-carousel__item img { height: 400px; margin-left: calc(50% - 1920px / 2); } </style> 新建:\src\components\Header.vue

<template> <div class="header"> <div class="slogan"> <p>老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</p> </div> <div class="nav"> <ul class="left-part"> <li class="logo"> <router-link to="/"> <img src="../assets/img/head-logo.svg" alt=""> </router-link> </li> <li class="ele"> <span @click="goPage('/free-course')" :class="{active: url_path === '/free-course'}">免费课</span> </li> <li class="ele"> <span @click="goPage('/actual-course')" :class="{active: url_path === '/actual-course'}">实战课</span> </li> <li class="ele"> <span @click="goPage('/light-course')" :class="{active: url_path === '/light-course'}">轻课</span> </li> </ul> <div class="right-part"> <div> <span>登录</span> <span class="line">|</span> <span>注册</span> </div> </div> </div> </div> </template> <script> export default { name: "Header", data() { return { url_path: sessionStorage.url_path || '/', } }, methods: { goPage(url_path) { // 已经是当前路由就没有必要重新跳转 if (this.url_path !== url_path) { this.$router.push(url_path); } sessionStorage.url_path = url_path; }, }, created() { sessionStorage.url_path = this.$route.path; this.url_path = this.$route.path; } } </script> <style scoped> .header { background-color: white; box-shadow: 0 0 5px 0 #aaa; } .header:after { content: ""; display: block; clear: both; } .slogan { background-color: #eee; height: 40px; } .slogan p { width: 1200px; margin: 0 auto; color: #aaa; font-size: 13px; line-height: 40px; } .nav { background-color: white; user-select: none; width: 1200px; margin: 0 auto; } .nav ul { padding: 15px 0; float: left; } .nav ul:after { clear: both; content: ''; display: block; } .nav ul li { float: left; } .logo { margin-right: 20px; } .ele { margin: 0 20px; } .ele span { display: block; font: 15px/36px '微软雅黑'; border-bottom: 2px solid transparent; cursor: pointer; } .ele span:hover { border-bottom-color: orange; } .ele span.active { color: orange; border-bottom-color: orange; } .right-part { float: right; } .right-part .line { margin: 0 10px; } .right-part span { line-height: 68px; cursor: pointer; } </style>

2、后台主页轮播图接口(luffy_api)

# 轮播图接口 # 导航条写死的---》如果想动态变化---》也要写成接口 # 首页推荐的8个课程---》接口---》按销量排序取前8个课程 ### 在pycharm打开后台项目 luffy_api: # cmd窗口 注册app: home cd到apps目录下 python ../../manage.py startapp home 到配置文件注册: INSTALLED_APPS = [ 'home', ] 2.1 表设计 新建 utils/model.py:

from django.db import models # 5个公共字段 class BaseModel(models.Model): created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') updated_time = models.DateTimeField(auto_now=True, verbose_name='最后更新时间') is_delete = models.BooleanField(default=False, verbose_name='是否删除') is_show = models.BooleanField(default=True, verbose_name='是否上架') orders = models.IntegerField(verbose_name='优先级') class Meta: abstract = True # 表示它是虚拟的,不在数据库中生成表,它只用来做继承 apps/home/models.py :

from django.db import models from utils.model import BaseModel # 轮播图接口---》轮播图表 class Banner(BaseModel): # 顺序,插入时间, 是否显示,是否删除。。。----》后期写课程的表也会用到这些字段--->仿AbstractUser,写一个基表,以后继承这个表 # 继承过来,只需要写自有字段即可:title,image,info,link title = models.CharField(max_length=16, unique=True, verbose_name='名称') image = models.ImageField(upload_to='banner', verbose_name='图片') # 写接口---》app---》前端配合一个接口---》实现打开app,就有广告图片---》点击广告图片调整到app内部或者使用浏览器打开 # 一打开app,先打开的页面是什么,写app的人写的---》整一张大图充满全屏即可--》配合一个接口,返回一张大图 # app打开广告接口---》{code:100,msg:成功,img:{img:127.0.0.1/img/1.png,link:'www.baidu.com',type:2}} link = models.CharField(max_length=64, verbose_name='跳转链接') # 在前端点击图片,会跳转到某个地址 info = models.TextField(verbose_name='详情') # 也可以用详情表,宽高出处 class Meta: db_table = 'luffy_banner' verbose_name_plural = '轮播图表' def __str__(self): return self.title

# 表设计完之后 迁移数据 并创建超级用户 python manage.py makemigrations ---》如果没有变化,是app没注册 python manage.py migrate python manage.py createsuperuser --->创建个用户 2.2 引入simpleui

# 下载 pip install django-simpleui # 注册app(写在最顶上) INSTALLED_APPS = [ 'simpleui', ... ] # 在admin.py中写: from django.contrib import admin from .models import Banner @admin.register(Banner) class BannerAdmin(admin.ModelAdmin): list_display = ('id', 'title', 'link', 'is_show', 'is_delete') # 增加自定义按钮 actions = ['make_copy'] def make_copy(self, request, queryset): # 选中一些数据,点击 触发方法执行,传入你选中 queryset # 保存,删除 print(queryset) make_copy.short_description = '自定义按钮' # 进入后台admin管理页面: 增加四条轮播图数据

2.3 轮播图接口

# 返回数据格式 {code:100, msg:成功,result:[{img:地址,link:跳转地址,orders:顺序,title:名字},{img:地址,link:跳转地址,orders:顺序,title:名字}]} 视图类 home/views.py中写:

from django.shortcuts import render from .models import Banner from .serializer import BannerSerializer from utils.response import APIResponse from rest_framework.viewsets import GenericViewSet from rest_framework.mixins import ListModelMixin class BannerView(GenericViewSet, ListModelMixin): # class BannerView(GenericViewSet,ListModelMixin): # 获取所有接口-list,自动生成路由 # qs对象可以像列表一样,切片 queryset = Banner.objects.filter(is_delete=False, is_show=True).order_by('orders') serializer_class = BannerSerializer def list(self, request, *args, **kwargs): # 重写list res = super().list(request, *args, **kwargs) return APIResponse(result=res.data) 新建序列化类 home/serializer.py:

from rest_framework import serializers from .models import Banner class BannerSerializer(serializers.ModelSerializer): class Meta: model = Banner fields = ['title', 'image', 'link', 'orders'] 新建分路由 home/urls.py:

from django.urls import path, include from rest_framework.routers import SimpleRouter from .views import BannerView router = SimpleRouter() router.register('banner', BannerView, 'banner') urlpatterns = [ path('', include(router.urls)), ] 总路由 urls.py:

from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/home/', include('home.urls')), # 127.0.0.1:8000/api/v1/home/banner/ ]

3、跨域问题详解(回到前端书写 luffycity:)

# 在前端项目中写: 用 pycharm打开前端项目 luffycity # 现在写好了后端接口,前端加载数据---》加载不过来,报错,--》报跨域的错误 # 同源策略 ---》浏览器的规定 请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同,否则,加载回来的数据就会禁止 前端:127.0.0.1:8080 后端:127.0.0.1:8000 这俩属于不同源,协议,地址一样,但是端口不一样,所以请求成功,但是到了浏览器被禁止掉了,因为浏览器的同源策略 前后端分离,就会遇到这个问题,现在解决这个问题 # jsonp 解决:出现了跨域问题---》有的东西不出跨域问题---》img,script,link--》回调 www.zhihu.com/question/19966531 但是目前已经不用了 所以不再介绍 # 通过CORS(跨域资源共享)解决: CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能 实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信 只需要在响应头中指定,允许跨域即可 # cors有两类请求 浏览器将CORS请求分成两类:简单请求(simple request)和 非简单请求(not-so-simple request) # 只要同时满足以下两大条件,就属于简单请求,否则就是非简单请求 1-请求方法是以下三种方法之一: HEAD GET POST 2-HTTP的头信息不超出以下几种字段: Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain 问:post,josn格式是什么请求? 非简单请求 # 简单请求和非简单请求的区别 简单请求:一次请求,直接发真正的请求,如果允许,数据拿回来,如果不允许,浏览器拦截 非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。 非简单请求发两次,第一次是OPTIONS请求,如果允许跨域,再发真正的请求 # 解决跨域-->分成简单和非简单请求处理 简单请求再响应头中加入:"Access-Control-Allow-Origin":"*" 非简单,咱们要加判断,如果是OPTIONS请求,在响应头中加入允许 # 自行解决跨域---》django中写个中间件,处理跨域--->配置到配置文件中 from django.utils.deprecation import MiddlewareMixin class CorsMiddleWare(MiddlewareMixin): def process_response(self,request,response): if request.method=="OPTIONS": #可以加* response["Access-Control-Allow-Headers"]="Content-Type" response["Access-Control-Allow-Origin"] = "*" return response # 经常遇到的东西,一定会有第三方解决方案---》我们使用第三方解决 第一步:下载(打开后台项目操作 luffy_api): pip install django-cors-headers 第二步:app中注册 dev.py: INSTALLED_APPS = ( ... 'corsheaders', ... ) 第三步:中间件注册 MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10 ... 'corsheaders.middleware.CorsMiddleware', ] 第四步:配置文件配置 ### 跨域问题处理 # 允许简单请求,所有地址 相当于CORS_ORIGIN_ALLOW_ALL="*" CORS_ALLOW_ALL_ORIGINS = True # 允许的请求方式 CORS_ALLOW_METHODS = ( 'DELETE', 'GET', 'OPTIONS', 'POST', 'PUT', ) # 允许的请求头 CORS_ALLOW_HEADERS = ( 'accept-encoding', 'authorization', # jwt 'content-type', # json 'origin', 'user-agent', 'Pragma', ) 修改 src/assets/js/settings.js:

export default { base_url: "127.0.0.1:8000/api/v1/" } 修改 Banner.vue:

<template> <div class="banner"> <el-carousel :interval="5000" arrow="always" height="400px"> <el-carousel-item v-for="item in banner_list"> <img :src="item.image" alt=""> </el-carousel-item> </el-carousel> </div> </template> <script> export default { name: "Banner", data() { return { banner_list: [] } }, created() { this.$axios.get(this.$settings.base_url + 'home/banner/').then(res => { if (res.data.status == 100) { this.banner_list = res.data.result console.log(this.banner_list) } }) } } </script> <style scoped> el-carousel-item { height: 400px; min-width: 1200px; } .el-carousel__item img { height: 400px; margin-left: calc(50% - 1920px / 2); } </style> 4、前后端打通 修改后台总路由:

from django.contrib import admin from django.urls import path, include, re_path from django.views.static import serve from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/home/', include('home.urls')), # 127.0.0.1:8000/api/v1/home/banner/ # 开启media的访问 path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT}) ] 修改banner.py:

<template> <div class="banner"> <el-carousel :interval="5000" arrow="always" height="400px"> <el-carousel-item v-for="item in banner_list"> <img :src="item.image" alt=""> </el-carousel-item> </el-carousel> </div> </template> <script> export default { name: "Banner", data(){ return { banner_list:[] } }, created() { this.$axios.get(this.$settings.base_url+'home/banner/').then(res=>{ if(res.data.status==100){ this.banner_list=res.data.result console.log(this.banner_list) } }) } } </script> <style scoped> el-carousel-item { height: 400px; min-width: 1200px; } .el-carousel__item img { height: 400px; margin-left: calc(50% - 1920px / 2); } </style> 5、后端自定义配置

# 在setting文件夹下新建 user_settings.py: # 用户自己的配置,单独放到一个py文件中 BANNER_COUNT = 3 # 在dev.py中导入 # 导入用户自定义的配置 from .user_settings import *

6、git介绍和安装

# 公司里是协同开发,多人开发同一个项目 # 代码已经写到v3版本了,忽然想看一下v1版本什么样 # git: 代码版本管理工具/软件,同类型的是 svn--但是用得少 帮助开发者合并开发的代码 如果出现冲突代码的合并,会提示后提交合并代码的开发者,让其解决冲突 做代码版本管理,可以快速回到某个版本上 # win:下载 git-scm.com/download # mac下载: github.com/timcharper/git_osx_installer/releases/download/2.2.1/git-2.2.1-intel-universal-mavericks.dmg # 一路下一步,其他都不用选 安装完成后 鼠标在桌面右键 会显示两个功能出来 代表安装成功


如何实现前台主页搭建、后台轮播图接口设计及跨域问题解决,确保前后端互通与后端自主开发?

本文共计3490个文字,预计阅读时间需要14分钟。

如何实现前台主页搭建、后台轮播图接口设计及跨域问题解决,确保前后端互通与后端自主开发?

今日内容概要:- 前台主页- 后台主页轮播图接口- 跨域问题详解- 前后端打通- 后端自定义配置- Git介绍和安装- 内容详细: 1. 前台主页:Home.vue - template - div class=home - Header/Header - Banner/Banner - 推荐课程

今日内容概要
  • 前台主页
  • 后台主页轮播图接口
  • 跨域问题详解
  • 前后端打通
  • 后端自定义配置
  • git介绍和安装
内容详细 1、前台主页 Homeviwe.vue

<template> <div class="home"> <Header></Header> <Banner></Banner> <!-- 推荐课程--> <div class="course"> <el-row> <el-col :span="6" v-for="(o, index) in 8" :key="o"> <el-card :body-style="{ padding: '0px' }" class="course_card"> <img src="tva1.sinaimg.cn/large/e6c9d24egy1h1g0zd133mj20l20a875i.jpg" class="image"> <div style="padding: 14px;"> <span>推荐的课程</span> <div class="bottom clearfix"> <time class="time">价格:100元</time> <el-button type="text" class="button">查看详情</el-button> </div> </div> </el-card> </el-col> </el-row> </div> <img src="tva1.sinaimg.cn/large/e6c9d24egy1h1g112oiclj224l0u0jxl.jpg" alt="" height="500px" width="100%"> <Footer></Footer> </div> </template> <script> import Footer from "@/components/Footer"; import Header from "@/components/Header"; import Banner from "@/components/Banner"; export default { name: 'HomeView', data() { return {} }, components: { Footer, Header, Banner } } </script> <style scoped> .time { font-size: 13px; color: #999; } .bottom { margin-top: 13px; line-height: 12px; } .button { padding: 0; float: right; } .image { width: 100%; display: block; } .clearfix:before, .clearfix:after { display: table; content: ""; } .clearfix:after { clear: both } .course { margin-left: 20px; margin-right: 20px; } .course_card { margin: 50px; } </style> 新建:\src\components\Footer.vue

<template> <div class="footer"> <ul> <li>关于我们</li> <li>联系我们</li> <li>商务合作</li> <li>帮助中心</li> <li>意见反馈</li> <li>新手指南</li> </ul> <p>Copyright © luffycity.com版权所有 | 京ICP备17072161号-1</p> </div> </template> <script> export default { name: "Footer" } </script> <style scoped> .footer { width: 100%; height: 128px; background: #25292e; color: #fff; } .footer ul { margin: 0 auto 16px; padding-top: 38px; width: 810px; } .footer ul li { float: left; width: 112px; margin: 0 10px; text-align: center; font-size: 14px; } .footer ul::after { content: ""; display: block; clear: both; } .footer p { text-align: center; font-size: 12px; } </style> 新建:\src\components\Banner.vue

<template> <div class="banner"> <el-carousel :interval="5000" arrow="always" height="400px"> <el-carousel-item v-for="item in 4" :key="item"> <img src="../assets/img/banner1.png" alt=""> </el-carousel-item> </el-carousel> </div> </template> <script> export default { name: "Banner" } </script> <style scoped> el-carousel-item { height: 400px; min-width: 1200px; } .el-carousel__item img { height: 400px; margin-left: calc(50% - 1920px / 2); } </style> 新建:\src\components\Header.vue

<template> <div class="header"> <div class="slogan"> <p>老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</p> </div> <div class="nav"> <ul class="left-part"> <li class="logo"> <router-link to="/"> <img src="../assets/img/head-logo.svg" alt=""> </router-link> </li> <li class="ele"> <span @click="goPage('/free-course')" :class="{active: url_path === '/free-course'}">免费课</span> </li> <li class="ele"> <span @click="goPage('/actual-course')" :class="{active: url_path === '/actual-course'}">实战课</span> </li> <li class="ele"> <span @click="goPage('/light-course')" :class="{active: url_path === '/light-course'}">轻课</span> </li> </ul> <div class="right-part"> <div> <span>登录</span> <span class="line">|</span> <span>注册</span> </div> </div> </div> </div> </template> <script> export default { name: "Header", data() { return { url_path: sessionStorage.url_path || '/', } }, methods: { goPage(url_path) { // 已经是当前路由就没有必要重新跳转 if (this.url_path !== url_path) { this.$router.push(url_path); } sessionStorage.url_path = url_path; }, }, created() { sessionStorage.url_path = this.$route.path; this.url_path = this.$route.path; } } </script> <style scoped> .header { background-color: white; box-shadow: 0 0 5px 0 #aaa; } .header:after { content: ""; display: block; clear: both; } .slogan { background-color: #eee; height: 40px; } .slogan p { width: 1200px; margin: 0 auto; color: #aaa; font-size: 13px; line-height: 40px; } .nav { background-color: white; user-select: none; width: 1200px; margin: 0 auto; } .nav ul { padding: 15px 0; float: left; } .nav ul:after { clear: both; content: ''; display: block; } .nav ul li { float: left; } .logo { margin-right: 20px; } .ele { margin: 0 20px; } .ele span { display: block; font: 15px/36px '微软雅黑'; border-bottom: 2px solid transparent; cursor: pointer; } .ele span:hover { border-bottom-color: orange; } .ele span.active { color: orange; border-bottom-color: orange; } .right-part { float: right; } .right-part .line { margin: 0 10px; } .right-part span { line-height: 68px; cursor: pointer; } </style>

2、后台主页轮播图接口(luffy_api)

# 轮播图接口 # 导航条写死的---》如果想动态变化---》也要写成接口 # 首页推荐的8个课程---》接口---》按销量排序取前8个课程 ### 在pycharm打开后台项目 luffy_api: # cmd窗口 注册app: home cd到apps目录下 python ../../manage.py startapp home 到配置文件注册: INSTALLED_APPS = [ 'home', ] 2.1 表设计 新建 utils/model.py:

from django.db import models # 5个公共字段 class BaseModel(models.Model): created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') updated_time = models.DateTimeField(auto_now=True, verbose_name='最后更新时间') is_delete = models.BooleanField(default=False, verbose_name='是否删除') is_show = models.BooleanField(default=True, verbose_name='是否上架') orders = models.IntegerField(verbose_name='优先级') class Meta: abstract = True # 表示它是虚拟的,不在数据库中生成表,它只用来做继承 apps/home/models.py :

from django.db import models from utils.model import BaseModel # 轮播图接口---》轮播图表 class Banner(BaseModel): # 顺序,插入时间, 是否显示,是否删除。。。----》后期写课程的表也会用到这些字段--->仿AbstractUser,写一个基表,以后继承这个表 # 继承过来,只需要写自有字段即可:title,image,info,link title = models.CharField(max_length=16, unique=True, verbose_name='名称') image = models.ImageField(upload_to='banner', verbose_name='图片') # 写接口---》app---》前端配合一个接口---》实现打开app,就有广告图片---》点击广告图片调整到app内部或者使用浏览器打开 # 一打开app,先打开的页面是什么,写app的人写的---》整一张大图充满全屏即可--》配合一个接口,返回一张大图 # app打开广告接口---》{code:100,msg:成功,img:{img:127.0.0.1/img/1.png,link:'www.baidu.com',type:2}} link = models.CharField(max_length=64, verbose_name='跳转链接') # 在前端点击图片,会跳转到某个地址 info = models.TextField(verbose_name='详情') # 也可以用详情表,宽高出处 class Meta: db_table = 'luffy_banner' verbose_name_plural = '轮播图表' def __str__(self): return self.title

# 表设计完之后 迁移数据 并创建超级用户 python manage.py makemigrations ---》如果没有变化,是app没注册 python manage.py migrate python manage.py createsuperuser --->创建个用户 2.2 引入simpleui

# 下载 pip install django-simpleui # 注册app(写在最顶上) INSTALLED_APPS = [ 'simpleui', ... ] # 在admin.py中写: from django.contrib import admin from .models import Banner @admin.register(Banner) class BannerAdmin(admin.ModelAdmin): list_display = ('id', 'title', 'link', 'is_show', 'is_delete') # 增加自定义按钮 actions = ['make_copy'] def make_copy(self, request, queryset): # 选中一些数据,点击 触发方法执行,传入你选中 queryset # 保存,删除 print(queryset) make_copy.short_description = '自定义按钮' # 进入后台admin管理页面: 增加四条轮播图数据

2.3 轮播图接口

# 返回数据格式 {code:100, msg:成功,result:[{img:地址,link:跳转地址,orders:顺序,title:名字},{img:地址,link:跳转地址,orders:顺序,title:名字}]} 视图类 home/views.py中写:

from django.shortcuts import render from .models import Banner from .serializer import BannerSerializer from utils.response import APIResponse from rest_framework.viewsets import GenericViewSet from rest_framework.mixins import ListModelMixin class BannerView(GenericViewSet, ListModelMixin): # class BannerView(GenericViewSet,ListModelMixin): # 获取所有接口-list,自动生成路由 # qs对象可以像列表一样,切片 queryset = Banner.objects.filter(is_delete=False, is_show=True).order_by('orders') serializer_class = BannerSerializer def list(self, request, *args, **kwargs): # 重写list res = super().list(request, *args, **kwargs) return APIResponse(result=res.data) 新建序列化类 home/serializer.py:

from rest_framework import serializers from .models import Banner class BannerSerializer(serializers.ModelSerializer): class Meta: model = Banner fields = ['title', 'image', 'link', 'orders'] 新建分路由 home/urls.py:

from django.urls import path, include from rest_framework.routers import SimpleRouter from .views import BannerView router = SimpleRouter() router.register('banner', BannerView, 'banner') urlpatterns = [ path('', include(router.urls)), ] 总路由 urls.py:

from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/home/', include('home.urls')), # 127.0.0.1:8000/api/v1/home/banner/ ]

3、跨域问题详解(回到前端书写 luffycity:)

# 在前端项目中写: 用 pycharm打开前端项目 luffycity # 现在写好了后端接口,前端加载数据---》加载不过来,报错,--》报跨域的错误 # 同源策略 ---》浏览器的规定 请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同,否则,加载回来的数据就会禁止 前端:127.0.0.1:8080 后端:127.0.0.1:8000 这俩属于不同源,协议,地址一样,但是端口不一样,所以请求成功,但是到了浏览器被禁止掉了,因为浏览器的同源策略 前后端分离,就会遇到这个问题,现在解决这个问题 # jsonp 解决:出现了跨域问题---》有的东西不出跨域问题---》img,script,link--》回调 www.zhihu.com/question/19966531 但是目前已经不用了 所以不再介绍 # 通过CORS(跨域资源共享)解决: CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能 实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信 只需要在响应头中指定,允许跨域即可 # cors有两类请求 浏览器将CORS请求分成两类:简单请求(simple request)和 非简单请求(not-so-simple request) # 只要同时满足以下两大条件,就属于简单请求,否则就是非简单请求 1-请求方法是以下三种方法之一: HEAD GET POST 2-HTTP的头信息不超出以下几种字段: Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain 问:post,josn格式是什么请求? 非简单请求 # 简单请求和非简单请求的区别 简单请求:一次请求,直接发真正的请求,如果允许,数据拿回来,如果不允许,浏览器拦截 非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。 非简单请求发两次,第一次是OPTIONS请求,如果允许跨域,再发真正的请求 # 解决跨域-->分成简单和非简单请求处理 简单请求再响应头中加入:"Access-Control-Allow-Origin":"*" 非简单,咱们要加判断,如果是OPTIONS请求,在响应头中加入允许 # 自行解决跨域---》django中写个中间件,处理跨域--->配置到配置文件中 from django.utils.deprecation import MiddlewareMixin class CorsMiddleWare(MiddlewareMixin): def process_response(self,request,response): if request.method=="OPTIONS": #可以加* response["Access-Control-Allow-Headers"]="Content-Type" response["Access-Control-Allow-Origin"] = "*" return response # 经常遇到的东西,一定会有第三方解决方案---》我们使用第三方解决 第一步:下载(打开后台项目操作 luffy_api): pip install django-cors-headers 第二步:app中注册 dev.py: INSTALLED_APPS = ( ... 'corsheaders', ... ) 第三步:中间件注册 MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10 ... 'corsheaders.middleware.CorsMiddleware', ] 第四步:配置文件配置 ### 跨域问题处理 # 允许简单请求,所有地址 相当于CORS_ORIGIN_ALLOW_ALL="*" CORS_ALLOW_ALL_ORIGINS = True # 允许的请求方式 CORS_ALLOW_METHODS = ( 'DELETE', 'GET', 'OPTIONS', 'POST', 'PUT', ) # 允许的请求头 CORS_ALLOW_HEADERS = ( 'accept-encoding', 'authorization', # jwt 'content-type', # json 'origin', 'user-agent', 'Pragma', ) 修改 src/assets/js/settings.js:

export default { base_url: "127.0.0.1:8000/api/v1/" } 修改 Banner.vue:

<template> <div class="banner"> <el-carousel :interval="5000" arrow="always" height="400px"> <el-carousel-item v-for="item in banner_list"> <img :src="item.image" alt=""> </el-carousel-item> </el-carousel> </div> </template> <script> export default { name: "Banner", data() { return { banner_list: [] } }, created() { this.$axios.get(this.$settings.base_url + 'home/banner/').then(res => { if (res.data.status == 100) { this.banner_list = res.data.result console.log(this.banner_list) } }) } } </script> <style scoped> el-carousel-item { height: 400px; min-width: 1200px; } .el-carousel__item img { height: 400px; margin-left: calc(50% - 1920px / 2); } </style> 4、前后端打通 修改后台总路由:

from django.contrib import admin from django.urls import path, include, re_path from django.views.static import serve from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/home/', include('home.urls')), # 127.0.0.1:8000/api/v1/home/banner/ # 开启media的访问 path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT}) ] 修改banner.py:

<template> <div class="banner"> <el-carousel :interval="5000" arrow="always" height="400px"> <el-carousel-item v-for="item in banner_list"> <img :src="item.image" alt=""> </el-carousel-item> </el-carousel> </div> </template> <script> export default { name: "Banner", data(){ return { banner_list:[] } }, created() { this.$axios.get(this.$settings.base_url+'home/banner/').then(res=>{ if(res.data.status==100){ this.banner_list=res.data.result console.log(this.banner_list) } }) } } </script> <style scoped> el-carousel-item { height: 400px; min-width: 1200px; } .el-carousel__item img { height: 400px; margin-left: calc(50% - 1920px / 2); } </style> 5、后端自定义配置

# 在setting文件夹下新建 user_settings.py: # 用户自己的配置,单独放到一个py文件中 BANNER_COUNT = 3 # 在dev.py中导入 # 导入用户自定义的配置 from .user_settings import *

6、git介绍和安装

# 公司里是协同开发,多人开发同一个项目 # 代码已经写到v3版本了,忽然想看一下v1版本什么样 # git: 代码版本管理工具/软件,同类型的是 svn--但是用得少 帮助开发者合并开发的代码 如果出现冲突代码的合并,会提示后提交合并代码的开发者,让其解决冲突 做代码版本管理,可以快速回到某个版本上 # win:下载 git-scm.com/download # mac下载: github.com/timcharper/git_osx_installer/releases/download/2.2.1/git-2.2.1-intel-universal-mavericks.dmg # 一路下一步,其他都不用选 安装完成后 鼠标在桌面右键 会显示两个功能出来 代表安装成功


如何实现前台主页搭建、后台轮播图接口设计及跨域问题解决,确保前后端互通与后端自主开发?