Luffy/3/前台主页搭建&轮播图接口

博客 动态
0 291
优雅殿下
优雅殿下 2022-04-21 01:58:15
悬赏:0 积分 收藏

Luffy /3/ 前台主页搭建&轮播图接口

Luffy /3/ 前台主页搭建&轮播图接口 前台主页搭建、轮播图接口、DRF处理跨域、

目录
  • 前台主页搭建
    • components/Homeviwe.vue
    • components/Banner.vue
    • components/Header.vue
    • components/Footer.vue
  • 后台主页轮播图接口
    • 创建home应用
    • 表设计
      • utils/model.py/BaseModel
    • 迁移数据,创建超级用户
    • 引入simpleui,录入数据
    • 轮播图接口格式
    • 轮播图接口实现
  • 处理跨域请求
    • 同源策略
    • CORS(跨域资源共享)简介
    • CORS分类
      • 如何区分这两种?
    • 简单请求和非简单请求的区别
    • 解决跨域
      • 方式一:
      • 方式二
      • 方式三
    • 轮播图前后端数据互通
  • 后端自定义配置

前台主页搭建

vue前端组件开发

components/Homeviwe.vue

<template>    <div >        <Header></Header>        <Banner></Banner>        <!--        推荐课程-->        <div >            <el-row>                <el-col :span="6" v-for="(o, index) in 8" :key="o">                    <el-card :body- >                        <img src="https://tva1.sinaimg.cn/large/e6c9d24egy1h1g0zd133mj20l20a875i.jpg" >                        <div >                            <span>推荐的课程</span>                            <div >                                <time >价格:100元</time>                                <el-button type="text" >查看详情</el-button>                            </div>                        </div>                    </el-card>                </el-col>            </el-row>        </div>        <img src="https://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>

components/Banner.vue

<template>    <div >        <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>

components/Header.vue

<template>    <div >        <div >            <p>路飞学城 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</p>        </div>        <div >            <ul >                <li >                    <router-link to="/">                        <img src="../assets/img/head-logo.svg" alt="">                    </router-link>                </li>                <li >                    <span @click="goPage('/free-course')" :>免费课</span>                </li>                <li >                    <span @click="goPage('/actual-course')" :>实战课</span>                </li>                <li >                    <span @click="goPage('/light-course')" :>轻课</span>                </li>            </ul>            <div >                <div>                    <span>登录</span>                    <span >|</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>

components/Footer.vue

<template>    <div >        <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>

image-20220420222337241

后台主页轮播图接口

创建home应用

startapp home

表设计

utils/model.py/BaseModel

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  # 表示它是虚拟的,不在数据库中生成表,它只用来做继承

迁移数据,创建超级用户

命令

# python manage.py makemigrations  ---》如果没有变化,是app没注册# python manage.py migrate# python manage.py createsuperuser  --->创建个用户

pycharm快捷

image-20220420222958214

引入simpleui,录入数据

# 下载    pip install django-simpleui    # dev.py注册appINSTALLED_APPS = [      'simpleui',      ...  ]# 在home/admin中写from django.contrib import adminfrom .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 = '自定义按钮'

轮播图接口格式

格式如下,可以使用自定制的APIResponse

{code:100,msg:成功,result:[{img:地址,link:跳转地址,orders:顺序,title:名字},{img:地址,link:跳转地址,orders:顺序,title:名字}]}

轮播图接口实现

总路由:urls.py

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

home路由:urls.py

from django.urls import path, includefrom rest_framework.routers import SimpleRouterfrom .views import BannerViewrouter = SimpleRouter()router.register('banner', BannerView, 'banner')urlpatterns = [    path('', include(router.urls)),]

视图类

from .models import Bannerfrom .serializer import BannerSerializerfrom utils.response import APIResponsefrom rest_framework.viewsets import GenericViewSetfrom rest_framework.mixins import ListModelMixinclass BannerView(GenericViewSet,ListModelMixin):    # 获取所有接口-list,自动生成路由    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)

序列化类

from rest_framework import serializersfrom .models import Bannerclass BannerSerializer(serializers.ModelSerializer):    class Meta:        model = Banner        fields = ['title', 'image', 'link', 'orders']

image-20220420223917615


处理跨域请求

image-20220420230040685

同源策略

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现

请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同,否则,加载回来的数据就会禁止,比如:前端Vue项目是http://127.0.0.1:8080,后端项目地址http://127.0.0.1:8000,那么这俩就属于不同源,前后端分离,就会遇到这个问题。

浏览器上就会报错,这个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险

image-20220420230430971

但是注意,项目2中的访问已经发生了,说明是浏览器对非同源请求返回的结果做了拦截

CORS(跨域资源共享)简介

CORS需要浏览器和服务器同时支持。目前,大部分浏览器都支持该功能。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信,只需要在响应头中指定,允许跨域即可

比较老的技术比如:jsonp技术,如果出现了跨域问题它可以通过img,script,link标签的连接功能,利用js的漏洞执行回调函数解决

jsonp

CORS分类

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)

如何区分这两种?

只要同时满足以下两大条件,就属于简单请求,否则就是非简单请求

1-请求方法是以下三种方法之一:HEADGETPOST2-HTTP的头信息不超出以下几种字段:AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

比如,post请求,josn格式是什么请求? 非简单请求

简单请求和非简单请求的区别

  • 简单请求:一次请求,直接发真正的请求,如果允许,数据拿回来,如果不允许,浏览器拦截
  • 非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。非简单请求发两次,第一次是OPTIONS请求,如果允许跨域,再发真正的请求

解决跨域

方式一:

  1. 简单请求再响应头中加入:"Access-Control-Allow-Origin":"*"

  2. 非简单,咱们要加判断,如果是OPTIONS请求,在响应头中加入允许

    # DRF中使用Response(result=res.data,headers={"Access-Control-Allow-Origin":"*"})

方式二

django中写个中间件,处理跨域,配置到配置文件

from django.utils.deprecation import MiddlewareMixinclass 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

方式三

使用第三方模块django-cors-headers

  1. 下载:pip install django-cors-headers

  2. app注册

 INSTALLED_APPS = (    ...    'corsheaders',    ...  )
  1. 中间件注册
  MIDDLEWARE = [        # Or MIDDLEWARE_CLASSES on Django < 1.10    ...    'corsheaders.middleware.CorsMiddleware',    ...  ]
  1. 配置文件配置
CORS_ALLOW_CREDENTIALS = TrueCORS_ORIGIN_ALLOW_ALL = TrueCORS_ORIGIN_WHITELIST = (	'*')CORS_ALLOW_METHODS = (	'DELETE',	'GET',	'OPTIONS',	'PATCH',	'POST',	'PUT',	'VIEW',)CORS_ALLOW_HEADERS = (	'XMLHttpRequest',	'X_FILENAME',	'accept-encoding',	'authorization',	'content-type',	'dnt',	'origin',	'user-agent',	'x-csrftoken',	'x-requested-with',	'Pragma',)

轮播图前后端数据互通

settings.js

export default {    base_url: "http://127.0.0.1:8000/api/vi/"}

banner.vue

<template>    <div >        <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>

后端自定义配置

在setting文件夹下新建 user_settings.py,我们可以把用户自己的配置放在这个配置文件中

BANNER_COUNT=3

可以继续在主配置文件导入继续使用

# 在dev.py中导入# 导入用户自定义的配置from .user_settings import *
posted @ 2022-04-21 01:04 HammerZe 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    优雅殿下

    优雅殿下 (王者 段位)

    2018 积分 (2)粉丝 (47)源码

    小小码农,大大世界

     

    温馨提示

    亦奇源码

    最新会员