- 前端页面
- 主页
- 后台home设计
- 表设计
- 前后台跨域交互
-曾老湿, 江湖人称曾老大。
-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。
前端页面
主页
我们把主页分成三部分: 1.导航栏 2.轮播图 3.页脚
图片 |
---|
先把图片放入img目录中

全局做一个CSS reset |
---|
assets/css/global.css
代码语言:javascript复制/* 声明全局样式和项目的初始化样式 */
body, h1, h2, h3, h4, p, table, tr, td, ul, li, a, form, input, select, option, textarea {
margin: 0;
padding: 0;
font-size: 15px;
}
a {
text-decoration: none;
color: #333;
}
ul {
list-style: none;
}
table {
border-collapse: collapse; /* 合并边框 */
}
导航栏 |
---|
创建Header组件
Header也就是我们的导航栏
componets/Header.vue
代码语言:javascript复制<template>
<div class="header-box">
<div class="header">
<div class="content">
<div class="logo full-left">
<router-link to="/"><img @click="jump('/')" src="@/assets/img/logo.svg" alt=""></router-link>
</div>
<ul class="nav full-left">
<li><span @click="jump('/course')" :class="this_nav=='/course'?'this':''">免费课</span></li>
<li><span @click="jump('/light-course')" :class="this_nav=='/light-course'?'this':''">轻课</span></li>
<li><span>学位课</span></li>
<li><span>题库</span></li>
<li><span>老男孩教育</span></li>
</ul>
<div class="login-bar full-right">
<div class="shop-cart full-left">
<img src="@/assets/img/cart.svg" alt="">
<span><router-link to="/cart">购物车</router-link></span>
</div>
<div class="login-box full-left">
<span>登录</span>
|
<span>注册</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Header",
data() {
return {
this_nav: "",
}
},
created() {
this.this_nav = localStorage.this_nav;
},
methods: {
jump(location) {
localStorage.this_nav = location;
// vue-router除了提供router-link标签跳转页面以外,还提供了js跳转的方式
this.$router.push(location);
}
}
}
</script>
<style scoped>
.header-box {
height: 80px;
}
.header {
width: 100%;
height: 80px;
box-shadow: 0 0.5px 0.5px 0 #c9c9c9;
position: fixed;
top: 0;
left: 0;
right: 0;
margin: auto;
z-index: 99;
background: #fff;
}
.header .content {
max-width: 1200px;
width: 100%;
margin: 0 auto;
}
.header .content .logo {
height: 80px;
line-height: 80px;
margin-right: 50px;
cursor: pointer;
}
.header .content .logo img {
vertical-align: middle;
}
.header .nav li {
float: left;
height: 80px;
line-height: 80px;
margin-right: 30px;
font-size: 16px;
color: #4a4a4a;
cursor: pointer;
}
.header .nav li span {
padding-bottom: 16px;
padding-left: 5px;
padding-right: 5px;
}
.header .nav li span a {
display: inline-block;
}
.header .nav li .this {
color: #4a4a4a;
border-bottom: 4px solid #ffc210;
}
.header .nav li:hover span {
color: #000;
}
.header .login-bar {
height: 80px;
}
.header .login-bar .shop-cart {
margin-right: 20px;
border-radius: 17px;
background: #f7f7f7;
cursor: pointer;
font-size: 14px;
height: 28px;
width: 88px;
margin-top: 30px;
line-height: 32px;
text-align: center;
}
.header .login-bar .shop-cart:hover {
background: #f0f0f0;
}
.header .login-bar .shop-cart img {
width: 15px;
margin-right: 4px;
margin-left: 6px;
}
.header .login-bar .shop-cart span {
margin-right: 6px;
}
.header .login-bar .login-box {
margin-top: 33px;
}
.header .login-bar .login-box span {
color: #4a4a4a;
cursor: pointer;
}
.header .login-bar .login-box span:hover {
color: #000000;
}
.full-left {
float: left !important;
}
.full-right {
float: right !important;
}
.el-carousel__arrow {
width: 120px;
height: 120px;
}
.el-checkbox__input.is-checked .el-checkbox__inner,
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
background: #ffc210;
border-color: #ffc210;
border: none;
}
.el-checkbox__inner:hover {
border-color: #9b9b9b;
}
.el-checkbox__inner {
width: 16px;
height: 16px;
border: 1px solid #9b9b9b;
border-radius: 0;
}
.el-checkbox__inner::after {
height: 9px;
width: 5px;
}
</style>
导入到主页中
首先注册导航栏,然后将导航栏添加到我们的主页中
代码语言:javascript复制<template>
<div class="home">
<Header/>
</div>
</template>
<script>
import Header from "@/components/Header";
export default {
name: 'home',
components: {Header},
Header,
}
</script>

轮播图 |
---|
创建轮播图组件Banner
components/Banner.vue
代码语言:javascript复制<template>
<el-carousel height="520px" :interval="3000" arrow="always">
<!--<el-carousel-item>-->
<!-- <img src="@/assets/img/banner1.png" alt="">-->
<!--</el-carousel-item>-->
<!--<el-carousel-item>-->
<!-- <img src="@/assets/img/banner2.png" alt="">-->
<!--</el-carousel-item>-->
<!--<el-carousel-item>-->
<!-- <img src="@/assets/img/banner3.png" alt="">-->
<!--</el-carousel-item>-->
<el-carousel-item v-for="banner in banner_list" :key="banner.name">
<a :href="banner.link">
<img :src="banner.image" alt="" :title="banner.note">
</a>
</el-carousel-item>
</el-carousel>
</template>
<script>
export default {
name: "Banner",
data() {
return {
banner_list: []
}
},
created() {
this.$axios({
url: this.$settings.base_url '/home/banners/',
method: 'get',
}).then(response => {
// window.console.log(response.data);
this.banner_list = response.data;
}).catch(errors => {
window.console.log(errors)
})
}
}
</script>
<style scoped>
.el-carousel__item h3 {
color: #475669;
font-size: 18px;
opacity: 0.75;
line-height: 300px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n 1) {
background-color: #d3dce6;
}
.el-carousel__item img {
text-align: center;
height: 520px;
margin: 0 auto;
display: block;
}
</style>
注册Banner并且使用Banner
代码语言:javascript复制<template>
<div class="home">
<Header/>
<Banner/>
</div>
</template>
<script>
import Header from '@/components/Header'
import Banner from '@/components/Banner'
export default {
name: 'home',
components: {
Header,
Banner,
},
}
</script>

页脚 |
---|
在components目录下创建有个Footer组件
components/Footer.vue
代码语言:javascript复制<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>
Home.vue中注册页脚组件,并使用
代码语言:javascript复制<template>
<div class="home">
<Header/>
<Banner/>
<Footer/>
</div>
</template>
<script>
import Header from '@/components/Header'
import Banner from '@/components/Banner'
import Footer from "@/components/Footer";
export default {
name: 'home',
components: {
Header,
Banner,
Footer,
},
}
</script>

后台home设计
创建home模块 |
---|
## 在apps目录下
(luffy) bash-3.2$ pwd
/Users/driverzeng/Desktop/luffy/luffyapi/luffyapi/apps
## 创建home
(luffy) bash-3.2$ python ../../manage.py startapp home
settings配置 |
---|
注册drf组件和home组件
settings/dev.py
代码语言:javascript复制INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'user',
'home',
]
总路由做路由分发 |
---|
luffyapi/urls.py
代码语言:javascript复制from django.contrib import admin
from django.urls import path, re_path, include
from django.views.static import serve
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
## 路由分发user模块
path('user/', include('user.urls')),
## 路由分发home模块
path('home/', include('home.urls')),
## 图片上传路径,必须是正则路由
re_path('^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})
]
表设计
基础表设计设计BaseModel |
---|
utils/models.py
代码语言:javascript复制from django.db import models
class BaseModel(models.Model):
orders = models.IntegerField(verbose_name='显示顺序')
is_show = models.BooleanField(verbose_name="是否上架", default=False)
is_delete = models.BooleanField(verbose_name="逻辑删除", default=False)
class Meta:
abstract = True
轮播图,表设计Banner |
---|
apps/home/models.py
代码语言:javascript复制from django.db import models
from utils.models import BaseModel
class Banner(BaseModel):
image = models.ImageField(upload_to='banner', verbose_name='轮播图', null=True, blank=True)
name = models.CharField(max_length=150, verbose_name='轮播图名称')
note = models.CharField(max_length=150, verbose_name='备注信息')
link = models.CharField(max_length=150, verbose_name='轮播图广告地址')
class Meta:
db_table = 'luffy_banner'
verbose_name = '轮播图'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
数据库迁移 |
---|
(luffy) bash-3.2$ python manage.py makemigrations
(luffy) bash-3.2$ python manage.py migrate
子路由 |
---|
apps/home/urls.py
代码语言:javascript复制from django.urls import path, re_path
from . import views
urlpatterns = [
path('banners/', views.BannerListAPIView.as_view())
]
home序列化 |
---|
apps/home/serializers.py
代码语言:javascript复制from rest_framework.serializers import ModelSerializer
from . import models
class BannerModelSerializer(ModelSerializer):
class Meta:
model = models.Banner
fields = ['name', 'note', 'image', 'link']
视图层 |
---|
from rest_framework.generics import ListAPIView
from utils.repsonse import APIResponse
from . import models, serializers
class BannerListAPIView(ListAPIView):
queryset = models.Banner.objects.filter(is_delete=False, is_show=True).order_by('-orders')
serializer_class = serializers.BannerModelSerializer
前后台跨域交互
解决后台跨域问题 |
---|
安装django-cors-headers
代码语言:javascript复制(luffy) bash-3.2$ pip install django-cors-headers
配置允许跨域
settings/dev.py
代码语言:javascript复制### 注册跨域app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
## 注册cors,解决跨域问题
'corsheaders',
'user',
'home',
]
### 添加跨域中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
## 添加跨域中间件
'corsheaders.middleware.CorsMiddleware',
]
### 允许跨域源
CORS_ORIGIN_ALLOW_ALL = True
配置Banner组件ajax与后台交互 |
---|
components/Banner.vue
代码语言:javascript复制<script>
export default {
name: "Banner",
// 添加钩子,渲染页面的时候,axios与后台交互
created() {
this.$axios({
url: this.$settings.base_url '/home/banners/',
method: 'get',
}).then(response => {
console.log(response.data)
}).catch((errors) => {
console.log(errors)
})
}
}
</script>
因为数据库没有数据,但是我们交互成功了。