返回验证码图片
后端:返回Http对象,content_type设置为image
# 验证码测试视图函数
def get_captcha(request):
img, code = generate_captcha() # 生成验证码
request.session['captcha_code'] = code # 将验证码保存到session中
buf = BytesIO() # 创建一个BytesIO对象,用于存储验证码图片
img.save(buf, 'png') # 将验证码图片保存到BytesIO对象中
return HttpResponse(buf.getvalue(),content_type="image/png") # 返回验证码图片的二进制数据
前端:设置imageUrl变量,img自动访问资源
<img :src="imageUrl" v-on:click=imgSrc(this) alt="验证码图片" style="width: 100px; margin-left: 40px;" />
但是没办法点击刷新验证码
重新绑定函数完成。
@click="imgSrc"
const imgSrc = () => {
imageUrl.value = imageUrl.value + '?' + new Date().getTime()
api.get_session().then((res) => {
console.log(res)
})
}
前端请求cookie丢失
原文链接:Django+vue 解决cookie跨域不携带问题(本地)以及上线后 - 春游去动物园 - 博客园
1排除了跨域问题,后端已经解决了跨域
后端通过
pip install django-cors-headers
sessting.py设置
SESSION_EXPIRE_AT_BROWSER_CLOSE = True # 会话cookie可以在用户浏览器中保持有效期。 False---session 在一段时间不活动后过期。True:关闭浏览器,则Cookie失效。
SESSION_COOKIE_SAMESITE = None
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CSRF_COOKIE_SAMESITE = None
CSRF_COOKIE_SECURE = False
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
'Cookie',
)
解决了跨域问题
前端通过代理域名,二次封装axios请求完成
vue.config.js
devServer: { //开启代理服务器
proxy:{
"/api": { // /api是自行设置的请求前缀,按照这个来匹配请求,有这个字段的请求,就会走到代理来。
target: "http://127.0.0.1:8081", // 需要代理的域名,目标域名,会替换掉匹配字段之前的路径
ws: false, // 是否启用websockets
changeOrigin: true, //是否跨域
pathRewrite: { //重写匹配的字段,如果不需要放在请求路径上,可以重写为""
"^/api": ""
}
},
}
},
request.js
const instance = axios.create({
timeout:5000,
baseURL:'/api', // 设置通用请求的地址前缀
withCredentials : true
})
可以传递cookie。
但是session无法获取,大概猜到原因,依然是跨域问题,在vue的api封装解决了跨域,但是session的设置是根据img的src路径直接访问,依然存在跨域问题,所以重点在于解决前端使用跨域解决获取验证码图片的操作
很难受,没怎么用心学VUE,在前端访问后端接口的时候后端传回图片的二进制数据流,但是前端一直无法显示,cors跨域问题已经解决,明白只要通过二次封装的axios请求就可以通过后端设置session。但是前端一直无法显示,尝试了无数方法,最后发现我的responetype设置到别的接口了,难怪一直没生效
vue3前端将二进制流文件显示
# index.js文件中请求函数
get_capt() {
return axios.get(base.baseUrl + base.captcha ,{responseType: 'blob'})
},
//使用的时候
// 生成验证码图片
const imgSrc = () => {
api.get_capt().then((res) => {
console.log(res)
const blob = new Blob([res.data]);
let url = window.URL.createObjectURL(blob); //根据返回的流文件创建url;url指向流
imageUrl.value = url; // 创建一个指向 blob 对象的 URL
console.log(imageUrl.value)
})
}
登录设置cookie状态
前端访问登录页面,登录后,后端向前端设置cookie。
前端直接访问主页面,后端通过cookie判断时候存在登录状态的cookie,如果没有就返回信息,让前端跳转到登录页面。如果有的话就根据cookie返回登录的用户信息
菜单部分设置采用后端传递前端的方式
数据库设计t_meau表中设计为自关联表,通过后端序列化后进行返回给前端,前端读取页面并显示
自关联序列化序列化,没招数了,多表关联都能用,自关联只能学着写了。自己摸索的
class Children2MeausSerializer(serializers.ModelSerializer):
class Meta:
model = meaus
fields = ['id', 'name', 'level', 'path']
class ChildrenMeausSerializer(serializers.ModelSerializer):
children = Children2MeausSerializer(many=True, read_only=True)
class Meta:
model = meaus
fields = ['id', 'name', 'level', 'path', 'children']
class MeausSerializer(serializers.ModelSerializer):
# 通过related_name='children'指定子级数据的反向查询字段名为children
children = ChildrenMeausSerializer(many=True, read_only=True)
class Meta:
model = meaus
fields = ['id', 'name', 'level', 'path', 'children']
上传用户头像并更改
通过el-upload,先判断传递图片是否符合要求,之后对传递的图片进行处理,并且保存为全局变量(需要对整个用户信息进行更新)获取到了图片信息之后通过请求后端接口将用户图像的图片信息传递过去。从后端拿到图片的地址在返回给前端。后端通过接收到图片的信息后将图片的上传到七牛云中进行云端储存,并且将储存的云端地址保存到mysql数据库当中。后端返回的时候将数据库的地址返回给前端,前端接收到数据地址进行赋值给表单或者弹窗中的图片地址,从而显示出图片
vue3的全局变量使用
// main.vue
const { proxy } = getCurrentInstance()
let user_img= proxy.$user_img
// main.js
const app = createApp(App)
app.config.globalProperties.$user_img = '用户的头像地址';
app.use(router).provide("$axios",axios).mount('#app')
重新捋一下
用户选择好图片之后,点击上传,发送上传请求给后端。后端接收到上传的文件流,将文件流发送到七牛云平台进行保存,返回一个图片的链接地址。后端将接收到的链接地址保存更新数据库并返回给前端页面进行展示。直接更改前端的src路径。
卡了我一天时间
解决方式:
通过element-plus的el-upload组件进行上传头像,起初认为action自动发送的请求会出现跨域问题,所以一直想要更新源码进行发送请求,最后实践得知不会出现跨域问题,因为我的后端需要cookie进行身份辨别,所以添加了:with-credentials="true"
<el-dialog class="avatarDialog" :showClose="false" center v-model="avatarDialogVisible" title="更新头像">
<el-upload
ref="upload"
class="avatar-uploader"
:show-file-list="false"
action='http://localhost:8081/user/upload_img/'
:with-credentials="true"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:auto-upload = 'true'
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
<template #footer>
<span class="dialog-footer">
<el-button @click="file_out">关闭</el-button>
</span>
</template>
</el-dialog>
后端就可以接收到前端发送的请求
@csrf_exempt
def upload_img(request):
if request.method == 'POST':
try:
user_id = request.COOKIES.get('user_id')
user = Users.objects.get(pk=user_id)
except KeyError:
return JsonResponse({"data":False,"msg":"登录过期,请重新登录"}, status=200)
# json_data = json.loads(request.body)
user_img = request.FILES['file'].file # 获取用户上传的头像图片文件流
file_name = upload_file(settings.AK, settings.SK, user_img)
user.img = f'{settings.BUCKET_URL}/{file_name}'
user.save() # 将头像地址保存到数据库中
print(f'文件地址:{settings.BUCKET_URL}/{file_name}')
return JsonResponse({'data':'调用了接口',"user_img":user.img},status=200)
通过封装好的upload_file函数,将文件流上传到七牛云保存,并返回相应的地址,将地址更新到数据库当中,减少了数据库的储存量,返回给前端图片的路径地址。在通过scr属性进行显示