Django建站+Vuejs前端

时间:2023-03-09 22:30:45
Django建站+Vuejs前端

第一节

@注意

千万注意格式、标签名字;

浏览器开发者模式修改页面不显示:在开发者模式下(F12进入),打开设置页面(F1),勾选 Disable cache (while DevTools is open)即可;

提示没有修改页面的权限,在pycharm的debug里面勾选allow unsigned requests;

html用chrome演示;

pycharm显示pip19版本但是turminal是9版本:进入第三方库目录,删掉pip19info文件夹,重新python -m pip install --upgrade pip;

@坑

php建站后使用比较麻烦

计算机基础

英语基础

@前后端分离

vuejs框架和django,vuejs接管django的views模块;

django打开页面是不停刷新,用vuejs可以不用太多跳转;

Django建站+Vuejs前端

@django的MTV

models

templates

views

@升级pip

python -m pip install --upgrade pip

@设计(Adobe xd 没有Linux版本,找个ui设计软件)

Django建站+Vuejs前端

1.https://semantic-ui.com/  源代码里找到dist/semantic.min.css,即打开view-source:https://semantic-ui.com/dist/semantic.min.css并复制,保存到semantic.min.css文件中,删除@import那一行(从@到;删掉,删多了会显示错误);

2.在html的head里面添加<link rel="stylesheet" href="项目内路径">

增加自己的mystyle.css,也添加到head引用;

3.设置四个导航栏(课程里四列,但是我四列就变两行了?)

<body>
<div class="top-menu">
<div class="ui container">
<div class="ui five column grid">
<div class="column">
首页
          </div>
<div class="column">
blog
</div>
<div class="column">
作品
          </div>
<div class="column">
联系
          </div>
</div>
</div>
</div> </body>

4.打开网页,f12,点击手机方式浏览,在head连加入以下,实现移动设备优先

<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">

5.修改mystyle.css文件

html{
font-size:10px;
}
.top-menu{
background:#000;
color:#fff;
padding-top:1rem;/*1rem表示根元素的大小*/
}
.top-menu .column{
text-align:center;
}

6.首页幻灯

https://www.swiper.com.cn/

找案例,看源代码,找css引用文件并点击打开,复制到新建的swiper.css文件中,并在html中引入样式;从案例中复制body里面的html内容到我的html中;复制案例中的js内容并保存到我的js文件里,在html的body结束前插入引用(django里面不用这种路径就)<script src="../statics/swiper.css" charset="utf-8"></script>

增加js自主添加的编码,也是复制案例里面的

<script>
var swiper = new Swiper('.swiper-container', {
spaceBetween: 30,
centeredSlides: true,
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
pagination: {
el: '.swiper-pagination',
clickable: true,
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
});
</script>

调整网页

<div class="swiper-slide">Slide 6</div>

替换为

<div class="swiper-slide"><img src="路径" alt=''></div>

调整mystyle.css

positon:fixed;位置为悬浮

heigh:3000px;框架高度

top:0;上边距

z-index:999;位于最高

width:100%;

height:3rem;(html{}里面font-size:10px;rem是font-size的倍数)

发现导航栏挡了一部分banner图(用一下方法,或直接在html里面将导航栏的透明度更改一下)

在之间创建一个div,id=’banner'

css里面创建

#banner{
margin-top:5rem
}

删除轮播图的箭头(删掉“<!-- Add Arrows --><div class="swiper-button-next"></div><div class="swiper-button-prev"></div>”)

7.做功能按钮

图片来源https://www.iconfont.cn/  新浪微博登录  图片都改为拼音不用中文;

文章简图  创客贴;

8.放入django

@创建项目,创建app,配置settings:

注册app;

STATIC_URL = '/statics/'
MEDIA_URL='/upload/'
MEDIA_ROOT=os.path.join(BASE_DIR,'upload').replace('//','/')

@修改urls

from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
from myblog import views urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index), ]+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

@migrate一下

@配置views.py里面的index

def index(request):
return render(request,'index.html')

@处理载入问题

引入模板{% load static %}

配置链接

<link href="{% static "css/semantic.min.css" %}" rel="stylesheet">
<link href="{% static "css/mystyle.css" %}" rel="stylesheet">
<link href="{% static "css/swiper.min.css" %}" rel="stylesheet">

相关的图片和js的引用也用类似格式修改

9.配置admin后台

配置models,创建首页模块

class Topmenu(models.Model):
#blank就是空的也可以存,default默认为空
title=models.CharField(default='',blank=True,null=True,max_length=20)
url=models.CharField(default='',blank=True,null=True,max_length=20)
def __str__(self):
return self.title

@创建超级用户python manage.py createsuperuser(用户名字前俩,密码s)

@注册首页模块

from django.contrib import admin
from myblog.models import Topmenu admin.site.register(Topmenu)

注册了账户就需要合并数据库,add首页导航栏几个名字,只写title

@处理views

from django.shortcuts import render
from .models import Topmenu
# Create your views here.
def index(request):
topmenu=Topmenu.objects.all()
content={
'topmenu':topmenu
}
return render(request,'index.html',content)

@处理html,载入数据库中的导航栏名称

                {% for item in topmenu %}
<div class="column">
{{ item.title }}
</div>
{% endfor %}

10.vue.js

@两种方式引入,开发用开发版本,会有报错提示

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

或者:

<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

@引用vue.js

复制第一个引用链接,浏览器打开,复制所有,在项目中创建vue.js文件;

html的head中插入

<script src="{% static 'js/vue.js' %}" charset="utf-8"></script>

刷新页面,查看开发者模式控制台,有(You are running Vue in development mode.)表示引用成功。

创建index.js并引用,先空着。

@编辑index.js

new Vue({
// el就是element
el:'#index',
data:{
// js语法:数组表示为中括号,对象用大括号
topmenu:[{title:'首页'},{title:'blog'},{title:'作品'},{title:'联系'},]
},
})

提示vue不能获取id,则说明页面中script加入的位置太靠前,应该放在要显示的位置的后面。

提示[Vue warn]: Error compiling template:,则说明script放在</div>前面了。

html中用<div v-for='item in topmenu' class="column">代替原来的for循环,此时不显示,body和script之间加入{% verbatim %}接管django,

@django模式的标签地址属性改为vuejs用的。

原为:

<img src="{static ‘image/77263a9a-6416-4131-a10e-c43ba516170d.jpg’}">

后为:

<img src="static/image/77263a9a-6416-4131-a10e-c43ba516170d.jpg">

@Ajax

https://www.npmjs.com/package/reqwest

@创建路由,在myblog子app里面创建api.py,下载djangorestframework,并在settings里面注册子app  'rest_framework'

@修改api.py

from rest_framework import serializers
from rest_framework.response import Response
from rest_framework.decorators import api_view
from myblog.models import Topmenu class Topmenuxuliehua(serializers.ModelSerializer):
class Meta:
depth=1
model=Topmenu
fields='__all__'
@api_view(['GET'])
def indexData(request):
print('ok')
return Response('ok')

@增加路由

path('api/index', api.indexData),

刷线如下图

Django建站+Vuejs前端

这就是rest_framework为django提供的json格式界面,点击get里面的json可查看json格式数据。

@页面载入js数据

def indexData(request):
topmenu=Topmenu.objects.all()
topmenuData=Topmenuxuliehua(topmenu,many=True)
return Response({'topmenu':topmenuData.data})

此时页面就可以读取js数据

@引用reqwest.js

复制reqwest文件到js文件夹中,引入到index页面的头部。

修改index.js

new Vue({
// el就是element
el:'#index',
data:{
// js语法:数组表示为中括号,对象用大括号
topmenu:[{title:'首页'},{title:'blog'},{title:'作品'},{title:'联系'},]
},
methods:{
getData:function(){
reqwest({
url:'/api/index',
method:'get',
success:function(data){
console.log(data)
}
})
}
}
})

此时页面可在开发者模式的console页看到没有成功执行console.log(data),需要添加方法

    // mounted方法是载入html时最先执行的方法
mounted(){
console.log('ok')
this.getData()
},

js可以正常工作

@修改index.js

new Vue({
// el就是element
el:'#index',
data:{
// js语法:数组表示为中括号,对象用大括号
topmenu:[]
},
// mounted方法是载入html时最先执行的方法
mounted(){
this.getData()
},
methods:{
getData:function(){
// 避免this指向错误,设置self
var self=this
reqwest({
url:'/api/index',
method:'get',
type:'json',
success:function(data){
console.log(data)
self.topmenu=data.topmenu
console.log(self.topmenu)
}
})
}
}
})

网站基础应用搭建完毕,接下来丰富网站

完整项目流程:

Django建站+Vuejs前端

11.丰富网站内容

@找b站封面图片

右击视频审核元素,找到上面的pic的class,复制里面的图片地址如‘//i0.hdslb.com/bfs/archive/91ca6962927787a14e6c0043d84db702ab14bb74.jpg@160w_100h.jpg’

链接前面加上‘http://’,后面改下w和h的值为1140,717,依次获得三张图片

@修改models.py(一旦修改model层,就要更新数据库),新增:

class Banner(models.Model):
img=models.ImageField(blank=True,null=True)
def __str__(self):
return self.id

在admin.py 里面增加对Banner的引用,并注册,此时admin后台页面就显示增加了Banner;

此时在Banner处增加图片,报错,提示__str__ returned non-string (type int);

将Banner里面的__str__改为__int__,网页还不对的话,就重新启动服务器;

因为之前配置了MEDIA_URL为‘/upload/’所以在整个项目第一层会将所有新上传媒体文件收录到upload文件夹中。

@将上传图片返回到网页

原先models层返回到views.py,现在是返回到api.py;

新增bannerData

#Author:Wen
from rest_framework import serializers
from rest_framework.response import Response
from rest_framework.decorators import api_view
from myblog.models import Topmenu,Banner class Topmenuxuliehua(serializers.ModelSerializer):
class Meta:
depth=1
model=Topmenu
fields='__all__' class BannerData(serializers.ModelSerializer):
class Meta:
# 设置depth标记,方便数据关联
depth=1
model=Banner
# 就一个img字段,所以可以用__all__,如果都选择型显示,可以fields=(['img','lala'])
fields='__all__'
@api_view(['GET'])
def indexData(request):
# 首页的导航栏
topmenu=Topmenu.objects.all()
topmenuData=Topmenuxuliehua(topmenu,many=True)
# 首页的Banner
banner=Banner.objects.all()
bannerData=BannerData(banner,many=True)
return Response({'topmenu':topmenuData.data,'banner':bannerData.data})

此时刷新http://127.0.0.1:8000/api/index,可以看到返回的json数据

@api(即rest_framework)的json数据被vuejs(即index.js)获取:index.js里面新增banner数组,设置变量获取数据,mounted方法中新增console.log(this)

查看页面的返回信息

Django建站+Vuejs前端

可见页面渲染需要调取banner的img属性

@用vuejs渲染index.html

<div v-for='item in banner' class="swiper-slide">
  <img :src="item.img" alt="" style="width:100%">
</div>

刷新就显示banner图

12.用户账号

@用户的前端制作

models里面新增用户模型

from django.contrib.auth.models import User

html修改,在{% endverbatim %}上面的</div>的上面新增


<div id="login">
<div class="userui">
<div class="ui container" style="background: #fff2f2">
<h3>登录</h3>
<div class="input">
<div class="item">
<input type="text" name="" value="" placeholder="用户名">
</div>
<div class="item">
<input type="text" name="" value="" placeholder='密码'>
</div>
</div>
<button type="button" name="button">取消</button>
<button type="button" name="button" style="background: #0d71bb;color: #ffffff">确定</button>
</div>
</div> </div>
 

修改css

#login{

}

#login .userui{
position:fixed;
top:30rem;
width:100%;
height: 20rem; }
#login .userui .ui.container{
background: #fff;
padding:1rem 1rem 1rem 1rem;
border:1px solid #efefef;
text-align: center;
} #login .userui .ui.container .item{
width:100%;
height:4rem;
margin-bottom: 1rem;
}
/*div下面的div用点,div下面不是div用空格*/
#login .userui .ui.container .item input{
width:100%;
height:100%;
border:1px solid #a96216;
border-radius:2rem;
text-align: center;
} #login .userui .ui.container button{
background: #FFFFFF;
width:8rem;
height:3rem;
margin-left:1rem;
border:1px solid #0f0f10; }

@交互

修改api.py,新增

# 用户管理
from django.contrib.auth import login
from django.contrib.auth.models import User

@让登陆框默认隐藏

index.js--data--新增userui:false,

index.html里面找到要设置为点击打开登陆页面的div,新增@click='showuserui()'

index.js--methods新增(别忘了前面加逗号)

showuserui:function(){
this.userui=!this.userui
}

@前端捕获用户账号密码

index.js--data新增‘username’和‘password’两个空数据;

index.html--input标签中新增‘v-model='username'’;

@向后台发送

index.html确定按钮新增@click='userlogin()'

index.js新增方法


userlogin:function(){
var self=this
reqwest({
url:'/api/index',
method:'post',
data:{
username:self.username,
password:self.password
},
success:function() {
console.log('ok')
},
error:function(err){
console.log(err)
},
})
},
 

api.py装饰器中增加‘POST’方法

注意:出现favicon.ico缺失错误

<link rel="icon" href="data:;base64,=">

@后台验证账号

api.py

from django.contrib.auth import login,authenticate
#函数中新增
username=request.POST['username']
password=request.POST['password'] user=authenticate(username=username,password=password)
print(user)
if user!=None:
login(request,user)
return Response({'loginType':'ok'})

@处理跨站请求csrftoken

js.cookies.js文件复制到static/js文件夹中

html--在index.js引入前插入

<script type="text/javascript">
var csrftoken=Cookies.get('csrftoken')
console.log(csrftoken)
</script>

index.js--在userlogin方法下加入

type:'json',
headers:{
'X-CSRFTOKEN':csrftoken
},

此时前端账号登录就能保证打开后台页面后台也可以登录。

@

@登录就关闭登录框,并且登录按钮改为“我的”

index.js--method-userlogin-reqwest-seccess里面新增

if(data.loginType=='ok'){
self.userui=false

index.html

<div v-if='loginButton' @click='showuserui()' class="column">
登陆
</div>
<div v-else class="column">
我的
</div>

index.js--data--新增loginButton:true,

index.js--method-userlogin-reqwest-seccess里面if下面新增loginButton:false,

@后台验证是否登录

因为登录失败,django捕获的request.user.id都为none,所以用此判断登录状态

if userid!=None:
loginType='ok'

index.js新增loginType:true??

if(data.loginType=='ok'){
self.loginType=true
}else{self.loginType=false}

@13.多app的关联

@13p

在app的templates路径下新建app同名文件夹,将html放进去;render()后面的渲染页面路径为app名称/html文件名;

在app的static路径下新建app同名文件夹,把存放静态文件的文件夹放进去;

新增的静态文件需要settings内注册地址:

STATICFILES_DIRS=[
os.path.join(BASE_DIR,'ak','static'),
os.path.join(BASE_DIR,'myblog','static'),
]

html中引入静态文件夹,修改静态文件引入路径为django模式路径

14.MYSQL

@准备

pip install mysqlclient;

配置settings

下载workbench,输入数据库密码,创建数据库库名与django里的settings一致;

创建django超级用户;

数据迁移;

刷新页面发现banner图和导航栏不见了,在django官方后台提交材料;

@

15.15p

@include

15-10

@可以右键复制整体HTML;注意引用网页模板的时候别落下js的引用。

@ Django建站+Vuejs前端

@

@

@