1. 首页

1.1 轮播图

admin站点配置支持图片上传

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 = [
...
'luffy.apps.home',
]

使用图片字段ImageFiled,字段选项使用upload_to可以设置保存图片的子目录,数据模型代码:

class BannerInfo(models.Model):
"""
轮播图
"""
# upload_to 存储子目录,真实存放地址会使用配置中的MADIE_ROOT+upload_to
image = 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_name def __str__(self):
return self.name

模型数据迁移:

python manage.py makemigrations
python manage.py migrate

在xadmin站点添加轮播图数据

通过如下命令安装xadmin的最新版

在配置文件中注册如下应用

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

  

在总路由中添加xadmin的路由信息

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

  

创建轮播图的模型管理类

import xadmin
from xadmin import views class BaseSetting(object):
"""xadmin的基本配置"""
enable_themes = True # 开启主题切换功能
use_bootswatch = True xadmin.site.register(views.BaseAdminView, BaseSetting) class GlobalSettings(object):
"""xadmin的全局配置"""
site_title = "路飞学城" # 设置站点标题
site_footer = "路飞学城有限公司" # 设置站点的页脚
menu_style = "accordion" # 设置菜单折叠 xadmin.site.register(views.CommAdminView, GlobalSettings) # 轮播图
from home.models import bannerInfo
class BannerInfoModelAdmin(object):
list_display=["name","orders","is_show"]
xadmin.site.register(bannerInfo, BannerInfoModelAdmin)

路由代码:

子应用路由:

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 格式,字符串中间只能出现一个圆点
]

 

视图代码: 

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)
   前端代码: <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>

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,
}
]
})

修复关于前端无法正常显示图片的问题

1.在settings中设置 MEDIA_URL:

# 项目中存储上传文件的根目录[暂时配置],注意,static目录需要手动创建否则上传文件时报错
MEDIA_ROOT=os.path.join(BASE_DIR,"luffy/static") # 设置访问上传文件的url地址前缀
MEDIA_URL = "/media/"

  此时 MEDIA_URL = "/media/" 中meida 代表着MEDIA_ROOT中代表的路径

2.在视图函数中提供完整的域名地址

from django.db.models import Q
from rest_framework.views import APIView
from rest_framework.response import Response from luffy.apps.home.models import BannerInfo HOST = "http://api.luffycity.cn:8000"
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": HOST + item.image.url,
"link":item.link,
"orders":item.orders,
})
return Response(data)

3.在主urls 设置路由

from django.conf import settings
from django.views.static import serve urlpatterns = [
re_path(r'^media/(?P<path>.*)$', serve, {"document_root": settings.MEDIA_ROOT}),

  

Luffy之Xadmin以及首页搭建(轮播图,导航)的更多相关文章

  1. day76:luffy:项目前端环境搭建&轮播图的实现

    目录 1.项目前端环境搭建 1.创建项目目录 2.前端初始化全局变量和全局方法 3.跨域CORS 4.axios配置 2.轮播图功能的实现 1.安装依赖模块 2.上传文件相关配置 3.注册home子应 ...

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

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

  3. phpcms首页实现轮播图

    1.在你想要加轮播图的位置加入以下 <div id="flowDiagram" > <div id="button"> <span ...

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

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

  5. jQuery实现todo及轮播图

    内容: 1.todo程序 2.轮播图 1.todo程序 需求: 实现一个todo程序,可以添加数据,可以删除数据,可以修改数据,可以查看所有数据 另外实现自己的一系列弹窗:用于提示用户的提示框.用于警 ...

  6. 轮播图和xadmin后台管理

    一.数据库设计 轮播图 1.安装依赖 pip install Pillow 2.模型类:home/models.py class Banner(models.Model): ""& ...

  7. 模仿东京首页banner轮播,京东新闻上下滚动动画实现(动画实现)

    接着上篇 微信小程序-阅读小程序demo写:http://www.cnblogs.com/muyixiaoguang/p/5917986.html 首页banner动画实现 京东新闻上下动画实现 想着 ...

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

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

  9. js实现淘宝首页图片轮播效果

    原文:http://ce.sysu.edu.cn/hope2008/Education/ShowArticle.asp?ArticleID=10585 <!DOCTYPE html> &l ...

随机推荐

  1. nowcoder 合并回文子串

    链接:https://www.nowcoder.com/acm/contest/6/C来源:牛客网题目输入两个字符串A和B,合并成一个串C,属于A和B的字符在C中顺序保持不变.如"abc&q ...

  2. 操作系统04_IO管理

    输入输出系统 IO系统的层次结构 用户层IO软件 设备独立性软件 设备驱动程序 中断处理程序 对IO设备的控制方式 使用轮询的可编程IO方式 cpu不停地检查设备的状态,以字节为单位,非中断方式,利用 ...

  3. (转载)Unity3D连接本地或局域网MySQL数据库

    准备工作: 1.打开 Unity3D 安装目录,到这个路径下 Editor > Data > Mono > lib > mono > 2.0 拷贝出下图的五个动态链接库, ...

  4. (转载)MySQl数据库-批量添加数据的两种方法

    方法一:使用excel表格 方法二:使用insert语句(FileWriter批量写入) 使用excel表格 1.打开数据表,按照表的字段在excel中添加数据.注意:表中字段名必须和excel中的名 ...

  5. kylin3

    RDBMS: 关系数据库管理系统(Relational Database Management System),是将数据组织为相关的行和列的系统,而管理关系数据库的计算机软件就是关系数据库管理系统, ...

  6. HDU 4325 Flowers(树状数组+离散化)

    http://acm.hdu.edu.cn/showproblem.php?pid=4325 题意:给出n个区间和m个询问,每个询问为一个x,问有多少个区间包含了x. 思路: 因为数据量比较多,所以需 ...

  7. R语言学习 - 非参数法生存分析--转载

    生存分析指根据试验或调查得到的数据对生物或人的生存时间进行分析和推断,研究生存时间和结局与众多影响因素间关系及其程度大小的方法,也称生存率分析或存活率分析.常用于肿瘤等疾病的标志物筛选.疗效及预后的考 ...

  8. 【Java】【THINK】

    1. 新建类,应优先考虑“组织”对象,而不是继承.这样可以保持清爽. 2. Java对象&对象句柄: 声明了一个类型的变量也就是声明了一个该类型的对象.但是这个对象只是个抽象的概念,并不会在内 ...

  9. 函数indexOf()和lastIndexOf()

    返回前面起第一个字符的位置indexOf(“字符”); 它是从前面开始数(从左边开始数),而且只找第一个,然后返回该字符的位置,索引号都是从0开始的.返回的是个数值. var txt = “abcde ...

  10. Android JNI 数组操作

    JNI 中有两种数组操作,基础数据类型数组和对象数组,JNI 对待基础数据类型数组和对象数组是不一样的. 基本数据类型数组 对于基本数据类型数组,JNI 都有和 Java 相对应的结构,在使用起来和基 ...