5.⾸页-轮播图-导航栏菜单⽬录
⾸页
1.对于⾸页要展⽰的数据和功能,我们先创建⼀个单独的字应⽤来完成。
cd renranapi/apps/
python ../../manage.py startapp home
2.总路由urls.py配置home路径
from django.urls import path,include
urlpatterns = [
path(r'xadmin/', xadmin.site.urls),
path('users/', include('users.urls')),
path('home/', include('home.urls')),
]
3.在apps/home/下创建⼦路由⽂件urls.py
from django.urls import path
from . import views
urlpatterns = [
# path('login/', obtain_jwt_token),
]
4.注册⼦应⽤,settings/dev.py,代码:
INSTALLED_APPS = [
'home',
]
1.轮播图功能实现
安装依赖模块和配置
图⽚处理模块
前⾯已经安装了,如果没有安装则需要安装
pip install pillow
上传⽂件相关配置
settings/dev.py
# 项⽬中存储上传⽂件的根⽬录[暂时配置],注意,media⽬录需要⼿动创建否则上传⽂件时报错
MEDIA_ROOT=os.path.join(BASE_DIR,'media')
# 访问上传⽂件的url地址前缀(MEDIA_ROOT路径别名)
MEDIA_URL ="/media/"
在xadmin中输出上传⽂件的Url地址
总路由urls.py新增代码:
from django.urls import re_path
f import settings
from django.views.static import serve
urlpatterns = [
# 前端发来的路径经过serve响应,到后台静态⽂件到路径图⽚,再经过serve响应到前端显⽰
re_path(r'media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}),
]
创建轮播图的模型
home/models.py
from django.db import models
# 论波图模型类
class Carousel(models.Model):
"""轮播图"""
# upload_to 存储⼦⽬录,真实存放地址会使⽤配置中的MADIE_ROOT+upload_to
image = models.ImageField(upload_to='carousel', 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='轮播图⼴告地址')
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 = 'rr_carousel'
verbose_name = '轮播图'
verbose_name_plural = verbose_name # 改掉名字的复数形式
def __str__(self):
return self.name
数据迁移
python manage.py makemigrations
python manage.py migrate
注册轮播图模型到xadmin中
import xadmin
from xadmin import views
from .models import Carousel
class CarouselModelAdmin(object):
list_display = ["id","name","link","is_show",] # 后台显⽰字段
list_editable = ["is_show",] # 可编辑列表
# 注册Carousel到xadmin中
ister(Carousel,CarouselModelAdmin)
修改后端xadmin中⼦应⽤名称
home/apps.py
class HomeConfig(AppConfig):
name = 'home'
verbose_name = '我的⾸页'
home/__init__.py
default_app_config = "home.apps.HomeConfig"
后台接⼝
1.路由home/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('carousel/list/', views.CarouselView.as_view()),
]
2.视图代码
settings/contains.py加⼊轮播图常量
# 轮波图数量
CAROUSEL_COUNTS = 3
视图 home/views.py
from django.shortcuts import render
from ics import ListAPIView
from .models import Carousel # 引⼊模型类
from renranapi.settings import contains # 引⼊常量
from .serializers import CarouselModelSerializer # 引⼊序列化器类
class CarouselView(ListAPIView):
# 就筛选3张图⽚轮播,放在序列化器中进⾏加⼯
queryset = Carousel.objects.filter(is_delete=False,is_show=True).order_by('orders','id')[0:contains.CAROUSEL_COUNTS]    serializer_class = CarouselModelSerializer
3.序列化器
home/serializers.py
from rest_framework import serializers
from .models import Carousel
class CarouselModelSerializer(serializers.ModelSerializer):
class Meta:
model = Carousel
fields = ['id','image','name','link']
客户端代码获取数据
Home.vue代码:
<template>
...
<div class="banner">
<el-carousel height="272px" indicator-position="none" :interval="interval">
<el-carousel-item v-for="(carousel_values,carousel_index) in carousel_list" :key="carousel_index">
<a :href="carousel_values.link">
<img :src="carousel_values.image" alt="">
</a>
</el-carousel-item>
</el-carousel>
</div>
.
..
</template>
<script>
import Header from "./common/Header";
import Footer from "./common/Footer";
export default {
name:"Home",
data(){
return {
carousel_list:[], //轮波图列表
interval:3000, //轮波间隔时间
}
},
// 页⾯加载,⾃动加载数据(轮波图)
created() {
this.$(`${this.$settings.host}/home/carousel/list/`)
.then((res)=>{//成功
this.carousel_list = res.data  //响应回来的数据
}).catch((error)=>{//失败
})
},
components:{
Header,
Footer,
}
}
</script>
.banner img{
max-height: 100%;
max-width: 100%;
}
</style>
2.导航功能实现
调整⾸页头部⼦组件的页⾯,Header.vue,效果:
<template>
<div class="header">
<nav class="navbar">
<div class="width-limit">
<!-- 左上⽅ Logo -->
<a class="logo" href="/"><img src="/static/image/nav-logo.png" /></a>
<!-- 右上⾓ -->
<!-- 未登录显⽰登录/注册/写⽂章 -->
<a class="btn write-btn" target="_blank" href="/writer"><img class="icon-write" src="/static/image/write.svg">写⽂章</a>        <router-link class="btn sign-up" id="sign_up" to="/user/register">注册</router-link>
<router-link class="btn log-in" id="sign_in" to="/user/login">登录</router-link>
<div class="container">
<div class="collapse navbar-collapse" id="menu">
<ul class="nav navbar-nav">
<li class="tab active">
<a href="/">
<i class="iconfont ic-navigation-discover menu-icon"></i>
<span class="menu-text">⾸页</span>
</a>
</li>
<li class="tab">
<a href="/">
<i class="iconfont ic-navigation-follow menu-icon"></i>
<span class="menu-text">关注</span>
</a>
<ul class="dropdown-menu">
<li><a href=""><i class="iconfont ic-comments"></i> <span>评论</span></a></li>
<li><a href=""><i class="iconfont ic-chats"></i> <span>简信</span></a></li>
<li><a href=""><i class="iconfont ic-requests"></i> <span>投稿请求</span></a></li>
<li><a href=""><i class="iconfont ic-likes"></i> <span>喜欢和赞</span></a></li>
<li><a href=""><i class="iconfont ic-follows"></i> <span>关注</span></a></li>
<li><a href=""><i class="iconfont ic-money"></i> <span>赞赏和付费</span></a></li>
<li><a href=""><i class="iconfont ic-others"></i> <span>其它提醒</span></a></li>
</ul>
</li>
<li class="tab">
<a href="/">
<i class="iconfont ic-navigation-notification menu-icon"></i>
<span class="menu-text">消息</span>
</a>
</li>
<li class="search">
<form target="_blank" action="/search" accept-charset="UTF-8" method="get">
<input type="text" name="q" id="q" value="" autocomplete="off" placeholder="搜索" class="search-input">
<a class="search-btn" href="javascript:void(0)"></a>
</form>
</li>
</ul>
</div>
</div>
<!-- 如果⽤户登录,显⽰下拉菜单 -->
</div>
</nav>
</div>
</template>
<script>
export default {
name: "Header"
}
</script>
<style scoped>
.header{
height: 56px;
}
.container {
width: 960px;
margin-right: auto;
margin-left: auto;
padding-left: 15px;
padding-right: 15px;
}
.container:after, .container:before {
content: " ";
display: table;
}
.container:after {
clear: both;
}
.navbar {
background-color: #fff;
border-color: #f0f0f0;
top: 0;
border-width: 0 0 1px;
border-radius: 0;
}
.navbar-nav {
float: left;
margin: 0;
}
.navbar:after, .navbar:before {
content: " ";
display: table;
box-sizing: border-box;
}
.nav:after, .nav:before {
content: " ";
display: table;
}
nav .width-limit {
min-width: 768px;
max-width: 1440px;
margin: 0 auto;
}
nav .logo {
float: left;
}
nav .logo img {
height: 100%;
vertical-align: middle;
border: 0;
}
.btn {
display: inline-block;
margin-bottom: 0;
font-weight: 400;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
border: 1px solid transparent;
white-space: nowrap;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857;
border-radius: 4px;
}
nav .write-btn {
float: right;
width: 100px;
height: 24px;
line-height: 24px;
margin: 8px 12px 0;
border-radius: 20px;
font-size: 15px;
color: #fff;
background-color: #ea6f5a;
text-decoration: none;
}
nav .log-in, nav .log-in:hover {
color: #969696;
}
nav .log-in {
float: right;
margin: 11px 6px 0 10px;
font-size: 15px;
}
nav .sign-up {
float: right;
width: 80px;
height: 24px;
line-height: 24px;
margin: 9px 5px 0 15px;
border: 1px solid rgba(236,97,73,.7);
border-radius: 20px;
font-size: 15px;
color: #ea6f5a;
background-color: transparent;
}
nav .icon-write {
margin-right: 3px;
width: 19px;
height: 19px;
vertical-align: middle;
}
nav .menu-text{
font-size: 17px;
}
nav .active a{
color: #ea6f5a;
}
nav .menu-icon {
width: 20px;
height: 20px;
vertical-align: baseline;
margin-right: 3px;
}
.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;
float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;
font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;
border:1px solid rgba(0,0,0,.15);border-radius:4px;
box-shadow:0 6px 12px rgba(0,0,0,.175);
background-clip:padding-box}
.dropdown-menu.pull-right{right:0;left:auto}
.dropdown-menu .divider{
height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}
.
dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;
line-height:1.42857;color:#333;white-space:nowrap}
.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{
text-decoration:none;color:#262626;background-color:#f5f5f5}
.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{
color:#fff;text-decoration:none;outline:0;background-color:#337ab7}
.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{
color:#777
}
.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{
text-decoration:none;background-color:transparent;background-image:none;filter:progid:adient(enabled = false);cursor:not-allowed}
.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857;color:#777;white-space:nowra @media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}
.navbar-right .dropdown-menu-left{left:0;right:auto}}
.dropdown-menu{
width:200px;margin-top:-1px;border-radius:0 0 4px 4px
}
.dropdown-menu li{margin:0}
.dropdown-menu a{height:auto;padding:10px 20px;line-height:30px}
.dropdown-menu a:hover{background-color:#f5f5f5}
.dropdown-menu i{margin-right:15px;font-size:22px;color:#ea6f5a;
vertical-align:middle
}
.dropdown-menu span{vertical-align:middle}
.dropdown-menu .badge{position:absolute;right:15px;margin-top:7px}
nav .nav .tab a {
height: 56px;
line-height: 26px;
padding: 15px;
background: none;
}
.
nav .tab:hover .dropdown-menu{
display: block;
}
nav .navbar-nav li {
margin-right: 10px;
float: left;
box-sizing: border-box;
height: 56px;
line-height: 56px;
}
.navbar-nav {
float: left;
margin: 0;
}
nav form {
position: relative;
top: 9px;
margin: 0 0 20px;
box-sizing: border-box;
line-height: 20px;
}
nav form .search-input {
padding: 0 40px 0 20px;
height: 38px;
font-size: 14px;
border: 1px solid #eee;
border-radius: 40px;
background: #eee;
transition: width .5s;
width: 240px;
django登录注册功能
outline: none;
}
nav form .search-input:focus {
width: 320px;
outline: none;
}
.navbar-default .navbar-collapse, .navbar-default .navbar-form {
border-color: #e7e7e7;
padding-left: 0;
padding-right: 0;
box-sizing: border-box;
width: auto;
border-top: 0;
box-shadow: none;
}
.navbar {
background-color: #fff;
top: 0;
border-radius: 0;
position: fixed;
right: 0;
left: 0;
z-index: 1030;
min-height: 50px;
margin-bottom: 20px;
border-bottom: 1px solid #f0f0f0;
}
nav {
height: 56px;
}
.navbar:after, .navbar:before {
content: " ";
display: table;
}
nav form .search-btn {
position: absolute;
display: block;
top: 0;
right: 10px;
width: 30px;
height: 30px;
padding: 0;
margin: 5px -1px 0 0;
background: transparent url("../../../static/image/search-focus.svg") no-repeat 6px 6px;
background-size: 20px;
}
nav form .search-input:focus~a{
border-radius: 50%;
background-color: #696969;
background-image: url("../../../static/image/search-blur.svg");
}
nav .sign-up:hover {
color: #ec6149;
border-color: #ec6149;
background-color: rgba(236,97,73,.05);
}
nav .write-btn:focus, nav .write-btn:hover {
color: #fff;
background-color: #ec6149;
}
</style>
创建模型
id name pid
1消息0
2⼴场0
3评论1
4留⾔1
1.引⼊⼀个公共模型【抽象模型,不会在数据迁移的时候为它创建表】
公共模型,保存项⽬的公共代码库⽬录下renranapi/utils/model.py⽂件中。
from django.db import models
# 公共模型类
class BaseModel(models.Model):
name = models.CharField(max_length=150, verbose_name='标题',null=True, blank=True)
orders = models.IntegerField(verbose_name='显⽰顺序',null=True, blank=True)
is_show = models.BooleanField(verbose_name="是否上架", default=True)
is_delete = models.BooleanField(verbose_name="逻辑删除", default=False)
created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间",null=True, blank=True)    updated_time = models.DateTimeField(auto_now=True, verbose_name="更新时间",null=True, blank=True)
class Meta:
# 设置当前模型在数据迁移的时候不要为它创建表
abstract = True
def __str__(self):
return self.name

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。