一.首页搭建
1.轮播图
pip install Pillow (这是在后端操作的,在之前搭建的后端环境中直接安装这个模块)
默认情况下,Django会将上传的图片保存在本地服务器上,需要配置保存的路径。
我们可以将上传的文件保存在静态文件statics目录中,添加如下上传保存目录信息
# 访问静态文件的url地址前缀 STATIC_URL = '/static/' # 项目中存储上传文件的根目录[暂时配置],注意,static目录需要手动创建否则上传文件时报错 MEDIA_ROOT=os.path.join(BASE_DIR,"luffy/static")# 设置django的静态文件目录 STATICFILES_DIRS = [os.path.join(BASE_DIR,"luffy/static") ]
把Home子应用注册到settings的INSTALLED_APPS中,并在models.py里面创建模型。
INSTALLED_APPS = [...'home', ]
home的views.py
使用图片字段ImageFiled
,字段选项使用upload_to
可以设置保存图片的子目录,数据模型代码:
class bannerInfo(models.Model):"""轮播图"""# upload_to 存储子目录,真实存放地址会使用配置中的MADIE_ROOT+upload_toimage = models.ImageField(upload_to='banner', verbose_name='轮播图', null=True)name = models.CharField(max_length=150, verbose_name='轮播图名称')link = models.CharField(max_length=150, verbose_name='轮播图广告地址')orders = models.IntegerField(verbose_name='显示顺序')is_show=models.BooleanField(verbose_name="是否上架",default=False)is_delete=models.BooleanField(verbose_name="逻辑删除",default=False)class Meta:db_table = 'ly_banner'verbose_name = '轮播图'verbose_name_plural = verbose_namedef __str__(self):return self.name
模型数据迁移:
python manage.py makemigrations
python manage.py migrate
在xadmin站点添加轮播图数据
pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2
在配置文件中注册如下应用:
INSTALLED_APPS = [...'rest_framework','xadmin','crispy_forms','reversion',... ]# 修改使用中文界面 LANGUAGE_CODE = 'zh-Hans'# 修改时区 TIME_ZONE = 'Asia/Shanghai'
xadmin有建立自己的数据库模型类,需要进行数据库迁移
python manage.py makemigrations
python manage.py migrate
import xadmin xadmin.autodiscover() # version模块自动注册需要版本控制的 Model from xadmin.plugins import xversion xversion.register_models() urlpatterns = [path(r'xadmin/', xadmin.site.urls) ]
创建超级用户
python manage.py createsuperuser
luffy/home/adminx.py
import xadmin from xadmin import viewsclass BaseSetting(object):"""xadmin的基本配置"""enable_themes = True # 开启主题切换功能use_bootswatch = Truexadmin.site.register(views.BaseAdminView, BaseSetting)class GlobalSettings(object):"""xadmin的全局配置"""site_title = "路飞学城" # 设置站点标题site_footer = "路飞学城有限公司" # 设置站点的页脚menu_style = "accordion" # 设置菜单折叠 xadmin.site.register(views.CommAdminView, GlobalSettings)# 轮播图 from .models import bannerInfo class BannerInfoModelAdmin(object):list_display=["name","orders","is_show"] xadmin.site.register(bannerInfo, BannerInfoModelAdmin)
视图:
luffy/home/views.py
from django.shortcuts import render# Create your views here.from django.db.models import Q from rest_framework.views import APIView from rest_framework.response import Response from .models import bannerInfo class BannerInfoAPIView(APIView):"""轮播图列表"""def get(self,request):# 获取数据banners = bannerInfo.objects.filter(Q(is_show=True) & Q(is_delete=False)).order_by("-orders")# 调整banners的images字段# 序列化data = []for item in banners:data.append({# 拼接图片的url地址"image": "/static/" + item.image.url,"link":item.link,"orders":item.orders,})return Response(data)
路由代码:
子应用路由:luffy/home/urls.py
from django.urls import path,re_path from . import views urlpatterns = [path(r"banner/",views.BannerInfoAPIView.as_view()), ]
总路由:
urlpatterns = [...path('home/', include("home.urls")),# include 的值必须是 模块名.urls 格式,字符串中间只能出现一个圆点 ]
2.前端代码(去admin那边获取api数据的)
<template><div class="banner"><el-carousel trigger="click" height="506px"><el-carousel-item v-for="item in banner_list"><a :href="item.link"><img :src="item.image"></a></el-carousel-item></el-carousel></div> </template><script>export default {name:"Banner",data(){return {banner_list:[],};},created: function(){// 获取轮播图this.$axios.get("http://api.luffycity.cn:8000/home/banner/").then(res => {this.banner_list = res.data}).catch(error => {console.log(error);});}} </script><style scoped> .banner img{width: 100%; } </style>
3.前端去后端拿数据会涉及到跨域CORS的问题(前后端都需要设置)
1.后端
我们现在为前端和后端分别设置两个不同的域名
window 系统: C:\Windows\System32\drivers\etc\host
linux/mac系统: /etc/hosts
位置 | 域名 |
---|---|
前端 | www.luffycity.cn |
后端 |
编辑/etc/hosts
文件,可以设置本地域名
在文件中增加两条信息
127.0.0.1 api.luffycity.cn
127.0.0.1 www.luffycity.cn
通过浏览器访问drf项目,会出现以下错误信息
可以通过settings的ALLOWED_HOSTS,设置允许访问
# 设置哪些客户端可以通过地址访问到后端 ALLOWED_HOSTS = ['api.luffycity.cn','www.luffycity.cn','localhost', # 实际开发的时候不会写上localhost和127.0.0.1的'127.0.0.1', ]
现在,前端与后端分处不同的域名,我们需要为后端添加跨域访问的支持。
否则前端无法使用axios无法请求后端提供的api数据
我们使用CORS来解决后端对跨域访问的支持。
使用django-cors-headers扩展
在 Response(headers={"Access-Control-Allow-Origin":'客户端地址/*'})
pip install django-cors-headers
添加应用
INSTALLED_APPS = (...'corsheaders',... )
中间层设置【必须写在第一个位置】
MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware',... ]
添加白名单
# CORS组的配置信息 CORS_ORIGIN_WHITELIST = ('127.0.0.1:8080','localhost:8080','www.luffycity.cn:8080' ) CORS_ALLOW_CREDENTIALS = True # 允许ajax跨域请求时携带cookie
完成了上面的步骤,我们就可以通过后端提供数据给前端使用ajax访问了。
2.前端的配置
安装
npm install axios -S
导入
在main.js导入
// 导入axios import axios from 'axios'; // 从node_modules目录中导入包 // 设置vue的全局子对象 Vue.prototype.$axios = axios; // 把对象挂载vue中
2. 显示登陆页面
Login.vue,代码:
<template><div class="login box"><img src="https://www.luffycity.com/static/img/Loginbg.3377d0c.jpg" alt=""><div class="login"><div class="login-title"><img src="https://www.luffycity.com/static/img/Logotitle.1ba5466.png" alt=""><p>帮助有志向的年轻人通过努力学习获得体面的工作和生活!</p></div><div class="login_box"><div class="title"><span @click="login_type=1" :class="login_type==1?'current':''">密码登录</span><span @click="login_type=2" :class="login_type==2?'current':''">短信登录</span></div><div class="inp" :class="login_type==1?'show':''"><input v-model = 'username' type="text" placeholder="用户名 / 手机号码" class="user"><input v-model = 'password' type="password" name="" class="pwd" placeholder="密码"><div id="geetest1" title="验证码"></div><div class="rember"><p><input type="checkbox" class="no" name="a"></input><span>记住密码</span></p><p>忘记密码</p></div><button class="login_btn">登录</button><p class="go_login" >没有账号 <span>立即注册</span></p></div><div class="inp" :class="login_type==2?'show':''"><input v-model = 'username' type="text" placeholder="手机号码" class="user"><input v-model = 'password' type="password" name="" class="pwd" placeholder="短信验证码"><div class="rember"><p><input type="checkbox" class="no" name="a"></input><span>记住密码</span></p><p>忘记密码</p></div><button class="login_btn">登录</button><p class="go_login" >没有账号 <span>立即注册</span></p></div></div></div></div> </template><script>export default{name:"Login",data(){return {login_type:2,username:"",password:"",}},components:{}} </script><style scoped> .box{width: 100%;position: relative;} .box img{width: 100%; } .box .login {position: absolute;width: 500px;height: 400px;top: 50%;left: 50%;margin-left: -250px;margin-top: -300px; } .login .login-title{width: 100%;text-align: center; } .login-title img{width: 190px;height: auto; } .login-title p{font-family: PingFangSC-Regular;font-size: 18px;color: #fff;letter-spacing: .29px;padding-top: 10px;padding-bottom: 50px; } .login_box{width: 400px;height: auto;background: #fff;box-shadow: 0 2px 4px 0 rgba(0,0,0,.5);border-radius: 4px;margin: 0 auto;padding-bottom: 40px; } .login_box .title{font-size: 20px;color: #9b9b9b;letter-spacing: .32px;border-bottom: 1px solid #e6e6e6; display: flex;justify-content: space-around;padding: 50px 60px 0 60px;margin-bottom: 20px;cursor: pointer; } .login_box .title .current{color: #4a4a4a;border-bottom: 2px solid #84cc39; }.inp{width: 350px;margin: 0 auto;display: none; } .show{display: block; } .inp input{border: 0;outline: 0;width: 100%;height: 45px;border-radius: 4px;border: 1px solid #d9d9d9;text-indent: 20px;font-size: 14px;background: #fff !important; } .inp input.user{margin-bottom: 16px; } .inp .rember{display: flex;justify-content: space-between;align-items: center;position: relative;margin-top: 10px; } .inp .rember p:first-of-type{font-size: 12px;color: #4a4a4a;letter-spacing: .19px;margin-left: 22px;display: -ms-flexbox;display: flex;-ms-flex-align: center;align-items: center;/*position: relative;*/ } .inp .rember p:nth-of-type(2){font-size: 14px;color: #9b9b9b;letter-spacing: .19px;cursor: pointer; }.inp .rember input{outline: 0;width: 30px;height: 45px;border-radius: 4px;border: 1px solid #d9d9d9;text-indent: 20px;font-size: 14px;background: #fff !important; }.inp .rember p span{display: inline-block;font-size: 12px;width: 100px;/*position: absolute;*/ /*left: 20px;*/} #geetest{margin-top: 20px; } .login_btn{width: 100%;height: 45px;background: #84cc39;border-radius: 5px;font-size: 16px;color: #fff;letter-spacing: .26px;margin-top: 30px; } .inp .go_login{text-align: center;font-size: 14px;color: #9b9b9b;letter-spacing: .26px;padding-top: 20px; } .inp .go_login span{color: #84cc39; cursor: pointer; } </style>
在routes/index.js中,添加路由
import Vue from "vue" import Router from "vue-router"// 导入需要注册路由的组件 import Home from "../components/Home" import Login from "../components/Login" Vue.use(Router);// 配置路由列表 export default new Router({mode:"history",routes:[// 路由列表{name:"Home",path: "/home",component:Home,},{name:"Home",path: "/",component:Home,},{name:"Login",path: "/login",component:Login,}] })