基于vue、VantUI、django的程序设计
首先构建vue项目,构建项目点这里
安装
npm install axios
axios简介
Axios 是一个基于 promise 的 HTTP 库,用于发起请求和接收响应,实现异步操作
基本使用
axios对象
请求响应拦截
在utils文件夹里新建ajax.js
创建一个axios对象并对外暴露
配置请求响应拦截器
import axios from "axios";
// 创建axios对象并暴露该对象可以被外部访问
// 创建对象时进行头信息设置及加载上一次携带的cookie
export const ajax = axios.create({
headers: {
source: "h5",
"Content-Type": "application/x-www-form-urlencoded", //用于指示资源的MIME类型,这个字段表明服务器要返回的内容是什么类型的数据
},
WithCredentials: true // 携带cookie
})
// 请求响应拦截器,有两个参数,参数1拦截成功函数,参数2拦截失败函数
// 处理完毕要放行(返回数据)
ajax.interceptors.request.use((req)=> {
console.log("拦截请求");
return req; // 不返回的话这个包就丢了
}, (err) => {
return Promise.reject(err);
});
ajax.interceptors.response.use((reqs)=>{
console.log("拦截响应")
return reqs;
}, (err) => {
return Promise.reject(err);
})
请求响应拦截器可以对请求和响应拦截并对拦截的数据操作。
如下:
这里配置了如果响应状态码为401的时候如何操作
// 响应拦截
ajax.interceptors.response.use((reqs)=>{
console.log("拦截响应")
return reqs;
}, (err) => {
if (err.response.status === 401) {
console.log("未登录。。。。")
}
return Promise.reject(err);
})
发起请求
在onMounted函数中调用axios.get()方法,参数是目标url。返回一个response,在then中进行处理。
axios.get()是通过get方法发起请求,返回一个响应。
<script setup>
import axios from "axios";
import {onMounted} from "vue";
// 此函数在页面元素加载前执行,也称为钩子函数或生命周期函数
onMounted(() => {
axios.get("http://www.baidu.com").then((response) => {
console.log("响应返回的数据" , response);
})
})
</script>
直接访问非本机目标会导致跨域问题,需要进一步配置
使用VantUI
ventui是一个vue组件库,和elementui不同,ventui主要面对移动端应用
npm install vant
使用vant元素
使用vant元素
eg:轮播图
<script setup>
import {ref} from "vue";
const bannerList = ref([
{
id :1 ,
img_url: "/static/home/banner/banner1.jpg",
},{
id :2 ,
img_url: "/static/home/banner/banner2.jpg",
},{
id :3 ,
img_url: "/static/home/banner/banner3.jpg",
}
])
</script>
<template>
<div class="home-banner-box">
<van-swipe class="swipe" :autoplay="3000" indicator-color="white">
<van-swipe-item v-for="item in bannerList" :key="item.id">
<img :src="item.img_url" alt="">
</van-swipe-item>
</van-swipe>
</div>
</template>
<style lang="less" scoped>
.home-banner-box{
img{
width: 100%;
height: auto;
}
}
</style>
cell单元格组件
<van-cell title="单元格" is-link />
<van-cell title="热门推荐" is-link value="全部榜单" />
<van-cell title="单元格" is-link arrow-direction="down" value="内容" />
正常是无法带有
创建django项目
创建django项目点这里
数据库设计和生成
配置数据库连接
打开setting.py,首先引入数据库依赖,然后找到DATABASES并配置。
import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库驱动
'NAME': 'trip_django', # 数据库名
"USER": "root", # 登录数据库的用户名
"PASSWORD": "1231", # 密码
"HOST": "127.0.0.1", # 数据库IP地址
"POST": "3306" # 数据库端口号
}
}
数据库设计
打开模块的models
设计规则
字段类型
Django提供了多种字段类型,用于表示不同的数据类型。以下是一些常用的字段类型:
AutoField
:自增列,通常不需要显式定义,因为Django会自动为每个model添加一个名为id
的自增主键字段。CharField
:字符串字段,必须指定max_length
参数。BooleanField
:布尔类型字段,不能为空,但可以添加Blank=True
允许在表单中为空。DateField
:日期类型字段,可以设置auto_now
(每次保存时自动更新为当前日期)和auto_now_add
(仅在第一次创建时自动设置为当前日期)等选项。DateTimeField
:日期时间类型字段,参数与DateField
相同。DecimalField
:十进制小数类型字段,需要指定max_digits
(总位数)和decimal_places
(小数位数)等参数。EmailField
:带有检查Email合法性的CharField。FloatField
:浮点类型字段。IntegerField
:整型字段。BigIntegerField
:长整型字段。TextField
:大文本字段,用于存储较长的字符串。URLField
:带有URL合法性校验的CharField。ImageField
:图片字段,需要Python Imaging库(Pillow)支持,可以指定height_field
和width_field
来保存图片的高度和宽度。FileField
:文件字段,用于存储上传的文件,需要指定upload_to
参数来指定文件上传的目录。
字段选项
除了字段类型外,还可以为字段指定一些选项来定制其行为:
null
:如果为True,则允许该字段在数据库中存储NULL值。默认为False。blank
:如果为True,则在Django admin中添加数据时可以允许该字段为空。这与null不同,null是与数据库相关的,而blank是与表单验证相关的。primary_key
:如果为True,则该字段将作为模型的主键。通常不需要显式设置,因为Django会自动为每个模型添加一个名为id
的自增主键字段。choices
:一个二维的元组列表,用于指定该字段的可选值。在Django admin中,这将使用select框代替文本框,并限定choices的值是元组中的值。max_length
:对于字符串类型的字段,指定最大长度。default
:为该字段指定一个默认值。verbose_name
:在Django admin中显示的字段名称。如果不设置,则使用属性名作为显示名称。db_column
:指定该字段在数据库中的列名。unique
:如果为True,则该字段的值在数据库中必须是唯一的。db_index
:如果为True,则为该字段创建数据库索引。
随后指定表名和排序规则
class Meta:
db_table = 'system_slider'
ordering = ['-reorder'] # 默认排序规则
eg:
from django.db import models
# Create your models here.
# 数据库中表的映射类,通过该文件构建和操作数据库
class Slider(models.Model):
# 轮播图
name = models.CharField('名称', max_length=32)
desc = models.CharField('描述', max_length=100, null=True, blank=True)
types = models.SmallIntegerField('展现的位置', default=10)
img = models.ImageField('图片地址', max_length=255, upload_to='%Y%m/slider')
reorder = models.SmallIntegerField('排序字段', default=0, help_text="数字越大越靠前")
start_time = models.DateTimeField('生效开始时间', null=True, blank=True)
end_time = models.DateTimeField('生效结束的时间', null=True, blank=True)
target_url = models.CharField('跳转的地址', max_length=255, null=True, blank=True)
is_valid = models.BooleanField('是否有效', default=True)
createdat = models.DateTimeField('创建时间', auto_now_add=True)
updated_at = models.DateTimeField('修改时间', auto_now=True)
class Meta:
db_table = 'system_slider'
ordering = ['-reorder'] # 默认排序规则
检查运行
python manage.py check
创建模型
python manage.py makemigrations
生成数据结构
生成数据结构前要先建库,库名和setting中配置的相同
python manage.py migrate
响应数据
规范相应数据结构
首先定义好格式
一个对象包裹着一个对象和一个列表
data = {
"meta": {
},
"object": []
}
从数据库查询数据
# 对数据源(数据库里的数据)进行过滤,相当于在sql中加where条件
quertset = Slider.objects.filter(is_valid=True)
将数据添加到响应的数据里
for item in quertset:
data["object"].append({
"id": item.id,
"img_url" : item.img.url,
"target" : item.target_url,
"name" : item.name,
})
返回响应
return http.JsonResponse(data)
整体
from django.http import HttpResponse
from django.shortcuts import render
from django import http
from system.models import Slider
# Create your views here.
def slider_list(request):
# 规范相应数据结构
data = {
"meta": {
},
"object": []
}
# 对数据源(数据库里的数据)进行过滤,相当于在sql中加where条件
quertset = Slider.objects.filter(is_valid=True)
for item in quertset:
data["object"].append({
"id": item.id,
"img_url" : item.img.url,
"target" : item.target_url,
"name" : item.name,
})
# 返回一个JSON格式的对象
return http.JsonResponse(data)
类视图响应数据
重写查询方法
首先重写查询方法,方法名为get_queryset。
代码中Q是查询条件,可以拼接多个条件。用&符号拼接。
paginate_by = 5表示每页有多少条数据
class SightListView(ListView):
paginate_by = 5 # 每页五条数据
def get_queryset(self):
query = Q(is_valid = True) # Q是查询条件,该对象可以拼接多个条件
# 热门
is_hot = self.request.GET.get('is_hot',None)
if is_hot:
query = query & Q(is_hot=True)
# 精选
is_top = self.request.GET.get('is_top',None)
if is_top:
query = query & Q(is_top=True)
print(query)
# 景点名称搜索
querySet = Sight.objects.filter(query)
return querySet
重写render_to_response方法
重写render_to_response方法,这个方法用于响应前端的请求。
context类是上下文对象,记录类的属性列表,
其中包含了ListView子类SightList的所有属性及数据
for item in page_obj.object_list:的含义是遍历所有当前页的数据
def render_to_response(self, context, **response_kwargs):
# 利用上下文对象获取页面信息
page_obj = context['page_obj']
# 合成响应数据
data = {
'meta': {
'total_count': page_obj.paginator.count,
'page_count': page_obj.paginator.num_pages,
'current_page': page_obj.number,
},
'objects': [],
}
for item in page_obj.object_list:
data['objects'].append({
'id': item.id,
'name': item.name,
'main_img': item.main_img.url,
'min_price': item.min_price,
'score': item.score,
'province': item.province,
'city': item.city,
'comment_count': 0
})
return http.JsonResponse(data)
在 Django 的分页功能中,page_obj
通常是一个表示当前页的分页对象,而 page_obj.object_list
是一个包含当前页所有对象的列表。
具体来说:
-
page_obj
:这是一个分页对象,它包含了关于当前页以及整个数据集分页信息的各种属性。它通常是通过 Django 的Paginator
类和相应的页面号码来创建的。 -
page_obj.object_list
:这是一个列表(或类似列表的可迭代对象),包含了根据分页逻辑从整个数据集中筛选出来的、属于当前页的对象。这些对象通常是模型实例,它们代表了数据库中的记录。
例如,如果你有一个包含 100 个对象的列表,并且你设置了每页显示 10 个对象,那么:
- 对于第一页,
page_obj.object_list
将包含列表中的前 10 个对象。 - 对于第二页,它将包含列表中的第 11 到第 20 个对象,以此类推。
获取指定分页
context['page_obj'].get_page(page_number)
当前视图完整代码
from django.db.models import Q
from django.shortcuts import render
from django import http
from django.views.generic import ListView
from sight.models import Sight
class SightListView(ListView):
paginate_by = 5 # 每页五条数据
def get_queryset(self):
query = Q(is_valid = True) # Q是查询条件,该对象可以拼接多个条件
# 热门
is_hot = self.request.GET.get('is_hot',None)
if is_hot:
query = query & Q(is_hot=True)
# 精选
is_top = self.request.GET.get('is_top',None)
if is_top:
query = query & Q(is_top=True)
print(query)
# 景点名称搜索
querySet = Sight.objects.filter(query)
return querySet
def render_to_response(self, context, **response_kwargs):
# 利用上下文对象获取页面信息
page_obj = context['page_obj']
# 合成响应数据
data = {
'meta': {
'total_count': page_obj.paginator.count,
'page_count': page_obj.paginator.num_pages,
'current_page': page_obj.number,
},
'objects': [],
}
for item in page_obj.object_list:
data['objects'].append({
'id': item.id,
'name': item.name,
'main_img': item.main_img.url,
'min_price': item.min_price,
'score': item.score,
'province': item.province,
'city': item.city,
'comment_count': 0
})
return http.JsonResponse(data)