今日内容概要

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

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

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 *

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 # 一路下一步,其他都不用选
安装完成后 鼠标在桌面右键 会显示两个功能出来 代表安装成功



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

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

    目录 前台主页搭建 components/Homeviwe.vue components/Banner.vue components/Header.vue components/Footer.vue ...

  2. 【VIP视频网站项目一】搭建视频网站的前台页面(导航栏+轮播图+电影列表+底部友情链接)

    首先来直接看一下最终的效果吧: 项目地址:https://github.com/xiugangzhang/vip.github.io 在线预览地址:https://xiugangzhang.githu ...

  3. 原生js实现轮播图

    原生js实现轮播图 很多网站上都有轮播图,但找到一个系统讲解的却很难,因此这里做一个简单的介绍,希望大家都能有所收获,如果有哪些不正确的地方,希望大家可以指出. 原理: 将一些图片在一行中平铺,然后计 ...

  4. Flutter学习五之网络请求和轮播图的实现

    上期讲到了,怎样实现一个下拉刷新和加载更多的列表,数据更新,需要使用到网络请求,在flutter中,怎样实现一个网络请求呢?官方使用的是dart io中的HttpClient发起的请求,但HttpCl ...

  5. 潭州课堂25班:Ph201805201 django 项目 第二十二课 文章主页 新闻列表页面滚动加载,轮播图后台实现 (课堂笔记)

    新建static/js/news/index.js文件 ,主要用于向后台发送请求, // 新建static/js/news/index.js文件 $(function () { // 新闻列表功能 l ...

  6. 仿百度壁纸客户端(二)——主页自定义ViewPager广告定时轮播图

    仿百度壁纸客户端(二)--主页自定义ViewPager广告定时轮播图 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度壁纸客户端( ...

  7. 潭州课堂25班:Ph201805201 django 项目 第二十三课 文章主页 轮播图前端实现 热门新闻推荐实现 详情页实现 (课堂笔记)

    前台代码 // 在static/js/news/index.js文件中 $(function () { // 新闻列表功能 let $newsLi = $(".news-nav ul li& ...

  8. 从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文

    一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...

  9. 潭州课堂25班:Ph201805201 django 项目 第四十一课 后台 轮播图管理功能讲解,文档管理功能 实现 (课堂笔记)

    在进入轮播图管理页面时,要把轮播图显示在页面上,所以后台要向前台返回: 图片路由,:image_url 优先级: priority def get(self, request): # priority ...

随机推荐

  1. S7-1200在博途V16中新建数据块(DB)

    硬件环境: S7-1200 CPU V4.4(6ES7 212-1AE40-0XB0) 软件环境: (1)Windows 10 Professional SP1 64位 (2)STEP7 V16 SP ...

  2. 🍛 餐厅吃饭版理解 IO 模型:阻塞 / 非阻塞 / IO 复用 / 信号驱动 / 异步

    IO 概念 一个基本的 IO,它会涉及到两个系统对象,一个是调用这个 IO 的进程对象,另一个就是系统内核 (kernel).当一个 read 操作发生时,它会经历两个阶段: 通过 read 系统调用 ...

  3. 文字图片在wps中清晰化方法

    在wps中双击图片出属性,然后再选择文字增强.选择对比增加即可.

  4. MAVEN setting文件

    <?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://mav ...

  5. kafka producer的batch.size和linger.ms

    1.问题 batch.size和linger.ms是对kafka producer性能影响比较大的两个参数.batch.size是producer批量发送的基本单位,默认是16384Bytes,即16 ...

  6. String s = new String(“xyz”);创建了几个字符串对象?

    两个对象,一个是静态区的"xyz",一个是用 new 创建在堆上的对象.

  7. 学习GlusterFS(二)

    环境准备 3台机器,每个机器双网卡,每个机器还需要额外添加1个10GB的磁盘用于测试 机器系统版本是centos6.6 1 2 3 4 5 [root@gluster-1-1 ~]# uname -r ...

  8. Python - Datetime库简介

  9. [性能测试] locust学习-基础篇

    在本文中,我将介绍一个名为Locust的性能测试工具.我将从Locust的功能特性出发,结合实例对Locust的使用方法进行介绍. 概述 Locust主要有以下的功能特性: 在Locust测试框架中, ...

  10. 一步步搭建物联网系统——无处不在的CSS

    无处不在的CSS 或许你觉得CSS一点儿也不重要,而事实上,如果说HTML是建筑的框架,CSS就是房子的装修.那么Javascript呢,我听到的最有趣的说法是小三--还是先让我们回到代码上来吧. C ...