• 前台主页搭建、后台主页轮播图接口设计、跨域问题详解、前后端互通、后端自定义配置、git软件的初步介绍


    今日内容概要

    • 前台主页
    • 后台主页轮播图接口
    • 跨域问题详解
    • 前后端打通
    • 后端自定义配置
    • 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="https://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="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>
    

    新建:\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>
    

    image

    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管理页面:
    	增加四条轮播图数据
    

    image

    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')),  # http://127.0.0.1:8000/api/v1/home/banner/
    ]
    

    image

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

    # 在前端项目中写:
    	用 pycharm打开前端项目 luffycity
        
    # 现在写好了后端接口,前端加载数据---》加载不过来,报错,--》报跨域的错误
    
    #  同源策略 ---》浏览器的规定
    	请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同,否则,加载回来的数据就会禁止
        
    	前端:http://127.0.0.1:8080
    	后端:http://127.0.0.1:8000
    	这俩属于不同源,协议,地址一样,但是端口不一样,所以请求成功,但是到了浏览器被禁止掉了,因为浏览器的同源策略
    	前后端分离,就会遇到这个问题,现在解决这个问题
        
        
        
    # jsonp 解决:出现了跨域问题---》有的东西不出跨域问题---》img,script,link--》回调
    	https://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: "http://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')),  # http://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 *
    

    image

    6、git介绍和安装

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

    image
    image

    image

  • 相关阅读:
    Docker 常用命令总结
    Springboot接收http参数总结(最简单易懂)
    Cy3菁染料标记海藻酸钠;CY3-Alginate;Alginate-CY3
    一切为了喵喵 | 攻防世界 x Nepnep x CATCTF邀你一战!
    手把手教你玩转 Gitea|使用 Docker 安装 Gitea
    计算机网络 - 应用层
    翻译QT使用手册:将库添加到项目
    企业舆情监测的意义是什么?为什么要做舆情监测?
    大数据精准营销一站式解决你的获客难题
    9/4 经典dp+线性筛求质数+混合背包
  • 原文地址:https://www.cnblogs.com/jgx0/p/16172208.html