<script>
{#头像随性别切换#}
let genderButtons = document.getElementsByName('gender');
genderButtons.forEach(function (button) {
button.addEventListener('click', function () {
{#定义默认路径#}
let defaultMaleAvatar = '/static/avatar/default_male.png'
let defaultFemaleAvatar = '/static/avatar/default_female.png'
{#获取当前的值进行修改#}
let selectGender = $(this).val();
let avatarImg = $("#avatarImg")
if (selectGender === 'm') {
avatarImg.attr('src', defaultMaleAvatar)
} else if (selectGender === 'f') {
avatarImg.attr('src', defaultFemaleAvatar)
}
});
});
</script>
FileReader
对象$()[0].files[0]
DataURL
FileReader
对象调用方法onload实时预览<script>
{#头像预览#}
$("#selectAvatar").change(() => {
{#创建FileReader对象#}
let fileReader = new FileReader();
{#读取头像#}
let avatarData = $("#selectAvatar")[0].files[0];
{#读取文件内容转换为Data URL对象#}
fileReader.readAsDataURL(avatarData)
{#重新赋值,实现预览功能#}
fileReader.onload = () => {
$("#avatarImg").attr('src', fileReader.result)
}
})
</script>
def register(request):
register_form = RegisterForm()
if request.method == "POST" and request.is_ajax():
register_form = RegisterForm(request.POST)
# 使用forms组件校验,不合法返回错误信息
if not register_form.is_valid():
return json_response(code=2001, errors=register_form.errors)
# 拿出所有检验通过的数据
clean_data = register_form.cleaned_data
# 合法信息需要抛出confirm_password,userinfo表中没有
clean_data.pop('confirm_password')
# 获取头像数据
avatar = request.FILES.get("avatar")
# 拿不到数据就用默认头像
if not avatar:
if clean_data.get('gender') == 'm':
clean_data['avatar'] = "static/avatar/default_male.png"
else:
clean_data['avatar'] = "static/avatar/default_female.png"
else:
clean_data['avatar'] = avatar
# 注册,密码加密处理,clean_data解压赋值
user_obj = UserInfo.objects.create_user(**clean_data)
# 反向解析跳转地址
next_url = reverse("login")
return json_response(message=f"{user_obj.username}注册成功", next_url=next_url)
return render(request, 'register.html', locals())
$.each(response.errors, (spanId, errorMessage) => {
let tagId = "#id_" + spanId
{#根据id找到span添加报错信息#}
{#找到input的标签添加红框#} $(tagId).next().next().text(errorMessage[0]).parent().find('input').addClass("layui-form-danger")
})
import random
import string
from PIL import Image, ImageFont, ImageDraw
# Image:生成图片
# ImageDraw:图片内容绘制
# ImageFont:字体样式
# BytesIO:临时存储数据,返回二进制数据
from io import BytesIO, StringIO
# 列表推导式生成随机颜色
# 高亮度的还是少一点的好
def rgb_number():
return tuple([random.randint(0, 200) for _ in range(3)])
def create_captcha(img_type="RGB", img_size=(310, 38)):
# 白板对象
# 图片类型,图片大小,图片颜色
# img_obj = Image.new(img_type, img_size, rgb_number())
img_obj = Image.new(img_type, img_size, color=(241, 241, 241)) # 白板
# 画笔对象
img_draw = ImageDraw.Draw(img_obj)
# 指定字体和大小
img_font = ImageFont.truetype('static/font/汉仪晴空体简.ttf', 30)
captcha = ''
for i in range(4):
choices_list = list(string.digits + string.ascii_letters)
temp_captcha = random.choice(choices_list)
# 开始绘制
# 位置、字符、颜色、字体
img_draw.text((i * 30 + 10, 2), temp_captcha, rgb_number(), img_font)
captcha += temp_captcha
# 添加噪点
for _ in range(100):
x = random.randint(0, img_size[0] - 1)
y = random.randint(0, img_size[1] - 1)
img_draw.point((x, y), fill=rgb_number())
# 文件对象的内存缓冲区,可以用来读写二进制数据
io_obj = BytesIO()
# 将图像对象img_obj保存为PNG格式,并将保存后的数据写入到之前创建的BytesIO对象io_obj中。
img_obj.save(io_obj, 'png')
# 从BytesIO对象io_obj中获取保存的图像数据,并将其赋值给变量img_data
img_data = io_obj.getvalue()
# 返回验证码和图片数据
return captcha, img_data
def get_captcha(request):
# 获取验证码和图片
code, img_data = create_captcha(img_size=(122, 36))
# 将验证码保存在session中用于验证
request.session['captcha'] = code
return HttpResponse(img_data)
onclick
绑定事件
<img src="{% url 'get_captcha' %}" style="width: 100%; height: 38px" id="captcha"
onclick="this.src = '{% url 'get_captcha' %}' + '?t='+ new Date().getTime();">
使用的是Bootstrap3的模态框
具有登录渲染当前头像的功能
亮点:
@csrf_exempt
@login_required
def set_avatar(request):
if request.is_ajax():
if request.FILES:
# 获取头像
avatar = request.FILES.get('avatar')
# 使用保存更改
user_obj = request.user
user_obj.avatar = avatar
user_obj.save()
return json_response(message='头像修改成功')
return json_response(code=2001, error="请添加新的头像")
return json_response(code=2002, error='非Ajax请求')
@csrf_exempt
@login_required
def set_avatar(request):
if request.is_ajax():
if request.FILES:
# 获取头像
avatar = request.FILES.get('avatar')
# 需要手动拼接路径,模型层的up_load不起作用,甚至需要图片名字手动加参数才可以不重名
file_path = os.path.join('media', 'avatar', avatar.name)
# 保存文件
with open(file_path, 'wb') as f:
# 保存图片是个易错点
for line in avatar.chunks():
f.write(line)
# 拼接保存在数据库中的路径
path = os.path.join('avatar', avatar.name)
UserInfo.objects.filter(username='iron').update(avatar=path)
return json_response(message='头像修改成功')
return json_response(code=2001, error="请添加新的头像")
return json_response(code=2002, error='非Ajax请求')
ajax
请求)
{#编辑广告第一步#}
{#编辑广告第一步#}
$(".set-adv").click(function (event) {
event.preventDefault()
{#获取当前广告ID#}
let id = $(this).attr('value')
$.ajax({
url: "{% url 'set_adv_first' %}",
type: "post",
data: {"id": id},
success: function (response) {
if (response.code === 2000) {
console.log(response)
$('input[name="set_adv_mobile"]').attr('value', response.mobile);
$('input[name="set_adv_title"]').attr('value', response.title);
$('input[name="set_adv_desc"]').attr('value', response.desc);
$('#set-adv-img').attr('src', response.img);
// 在指定的 input 标签后面插入一个新的 input 标签
$('input[name="set_adv_mobile"]').after(
$('<input>').attr({
type: 'hidden', // 设置为隐藏类型
name: 'now_id', // 设置 input 的 name 属性为 now_id
value: response.now_id // 设置 input 的 value 属性为 now_id 的值
})
)
if (response.is_background_img) {
{#修改前端显示效果#}
$('#set_adv_background').next().addClass('layui-form-onswitch')
{#修改后端可以接收到的值#}
$("#set_adv_background").click()
}
} else {
alert(response.error)
}
}
})
})
{#编辑广告第二步#}
$("#set-adv-button").click((event) => {
event.preventDefault()
{#创建formData#}
let formData = new FormData()
{#获取form数据#}
$.each($("#set-avd-form").serializeArray(), (_, dataDict) => {
formData.append(dataDict.name, dataDict.value)
})
{#获取广告数据#}
let advData = $("#setSelectAdv")[0].files[0];
formData.append('set_adv_img', advData)
console.log(formData)
{#发送ajax#}
$.ajax({
url: "{% url 'set_adv_second' %}",
type: "post",
data: formData,
processData: false,
contentType: false,
success: (response) => {
console.log(response)
if (response.code === 2000) {
{#成功提示并跳转#}
Swal.fire({
title: response.message,
icon: "success",
customClass: {
popup: 'swal2-custom',
icon: 'swal2-icon-custom'
}
}).then(() => {
window.location.reload()
});
} else {
console.log(response.code)
Swal.fire({
icon: "error",
title: response.error,
customClass: {
popup: 'swal2-custom',
icon: 'swal2-icon-custom'
}
});
}
}
})
})
{#右侧广告开始#}
<div class="col-md-2 right-content">
{% block right-content %}
{% for adv_obj in adv_queryset %}
<div class="advertisement" style="display: none;">
{% adv_show adv_obj.pk %}
</div>
{% endfor %}
{% endblock %}
</div>
{#右侧广告结束#}
<script>
$(document).ready(() => {
{#页面总高度#}
let totalDocumentHeight = $(document).height();
// 对高度进行400px的整除取整数
let numAdsToShow = Math.floor(totalDocumentHeight / 400);
// 确保广告数量不会少于0或超过广告对象的总数
let advCount = {{ adv_queryset|length }};
numAdsToShow = Math.min(numAdsToShow, advCount);
// 根据计算出的数量显示广告
$('.advertisement').slice(0, numAdsToShow).show();
</script>
onclick
属性中,或者在页面的其他JavaScript脚本中。<script>
// 点赞功能
function votePost(article_id, flag) {
{#三元表达式 和C的一样 和Python的不一样#}
{#flag = true ? flag === 'Digg' : false#}
{#简写#}
flag = flag === 'Digg'
{#获取提示信息的div#}
let divEle = $("#message-error")
{#用于后续修改点赞点踩数量#}
let upEle = $("#digg_count")
let downEle = $("#bury_count")
$.ajax({
url: "{% url 'up_down' %}",
type: "post",
data: {
"flag": flag,
{#右边注意需要是字符串格式#}
{#{% csrf_token %}写在页面中即可,没有要求说写在表单里#}
"csrfmiddlewaretoken": "{{ csrf_token }}",
"article_id": article_id,
},
success: function (response) {
if (response.code === 2000) {
{#渲染信息#}
divEle.text(response.message)
{#修改点赞点踩#}
upEle.text(response.up_num)
downEle.text(response.down_num)
} else {
{#失败处理#}
{#html自动转义#}
divEle.html(response.error)
}
}
})
}
</script>
更多【python-Django 仿博客园练习】相关视频教程:www.yxfzedu.com