1、互联网项目(产品经理提需求),传统行业项目(客户提需求)
2、项目开发流程
需求分析(组长,项目经理,产品经理)
原型设计(产品经理)
美工UI切图
设计程序,数据库(上面两个可以跟设计数据库同步操作)
分任务开发(张三写用户相关,李四写订单相关),多人协同开发(git,svn)
假设过了三个月所有任务开发完了
测试(专门的测试)
上线
3、项目开发模式
瀑布模式
敏捷开发
多人博客
博客首页
登录: 图片验证码
注册: 上传头像
自己有自己的个人站点(根据分类,标签,时间,过滤文章)
自己的后台管理
发表博客(富文本编辑器,xss攻击处理)
查看,删除
文章分类
随笔档案
文章标签
文章
文章详情
评论(根评论,子评论)
点赞点踩
# 表设计(8张)
1、用户表: UserInfo表
2、博客表: Blog表
3、分类表: Category
4、标签表: Tag
5、文章: Article(文章和详情一个表)
6、评论: Comment
7、点赞点踩表: UpAndDown
8、文章标签中间表
# 表中字段
1、用户表: UserInfo表(通过继承auth_user扩展)
phone
avatar(头像)
blog(关联字段)
2、博客表: Blog表
title
name
style
3、分类表: Category
name
blog
4、标签表: Tag
name
blog
5、文章: Article(文章和详情一个表)
title
desc
content
create_time
blog
category
tag(多对多)
6、评论: Comment
user
article
create_time
content
7、点赞点踩表: UpAndDown
user
article
is_up
create_time
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
phone = models.CharField(max_length=32, verbose_name='手机号')
# upload_to文件上传以后存放的路径
# FileField本质是varchar类型
avator = models.FileField(upload_to='avator/', default='avator/default.png')
blog = models.OneToOneField(to='Blog', on_delete=models.CASCADE, null=True)
class Blog(models.Model):
title = models.CharField(max_length=32, verbose_name='博客标题')
name = models.CharField(max_length=32, verbose_name='博客描述')
style = models.CharField(max_length=32, verbose_name='博客样式')
class Tag(models.Model):
name = models.CharField(max_length=32, verbose_name='标签名称')
blog = models.ForeignKey(to='Blog', on_delete=models.CASCADE)
class Category(models.Model):
name = models.CharField(max_length=32, verbose_name='分类名称')
blog = models.ForeignKey(to='Blog', on_delete=models.CASCADE)
class Article(models.Model):
title = models.CharField(max_length=32, verbose_name='文章标题')
desc = models.CharField(max_length=128, verbose_name='文章描述')
content = models.TextField(verbose_name='文章内容')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='文章创建时间')
# 关联字段
blog = models.ForeignKey(to='Blog', on_delete=models.CASCADE)
category = models.ForeignKey(to='Category', on_delete=models.CASCADE)
tag = models.ManyToManyField(to='Tag', through='TagToArticle', through_fields=('article', 'tag'))
class TagToArticle(models.Model):
tag = models.ForeignKey(to='Tag', on_delete=models.CASCADE)
article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
class UpAndDown(models.Model):
user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE)
article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
is_up = models.BooleanField(verbose_name='是否是点赞')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='点赞点踩创建时间')
class Comment(models.Model):
user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE)
article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
content = models.CharField(max_length=255, verbose_name='评论内容')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='评论创建时间')
# 存父评论的id号
comments = models.ForeignKey(to='self', on_delete=models.CASCADE)
执行迁移文件的两条命令
python manage.py makemigrations
python manage.py migrate
blog_forms.py
from django import forms
from django.forms import widgets
from blog.models import UserInfo
class BlogForm(forms.Form):
username = forms.CharField(min_length=3, max_length=18, required=True, label='用户名',
error_messages={'min_length': '最小为3位', 'max_length': '最大为18位', 'required': '该字段必填'},
widget=widgets.TextInput(attrs={'class': 'form-control'}))
password = forms.CharField(min_length=3, max_length=18, required=True, label='密码',
error_messages={'min_length': '最小为3位', 'max_length': '最大为18位', 'required': '该字段必填'},
widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
re_password = forms.CharField(min_length=3, max_length=18, required=True, label='确认密码',
error_messages={'min_length': '最小为3位', 'max_length': '最大为18位', 'required': '该字段必填'},
widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
email = forms.EmailField(required=True, label='邮箱',
error_messages={'min_length': '最小为3位', 'max_length': '最大为18位', 'required': '该字段必填',
'invalid': '邮箱不合法'},
widget=widgets.TextInput(attrs={'class': 'form-control'}))
def clean_username(self):
username = self.cleaned_data.get('username')
count = UserInfo.objects.filter(username=username).count()
if count:
self.add_error('username', '用户名已存在')
else:
return username
def clean(self):
pwd = self.cleaned_data.get('password')
re_pwd = self.cleaned_data.get('re_password')
if pwd == re_pwd:
return self.cleaned_data
else:
self.add_error('re_password', '两次密码输入不一致')
setting中配置媒体资源
# 由于FileField会自动保存文件,所以默认以MEDIA_ROOT开始往下找,如果没有配,默认以根路径开始
# 以后上传的文件,都是从media路径往下找
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}"></script>
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
<title>注册</title>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">用户注册</h1>
<form action="" id="id_form">
{% csrf_token %}
{% for form in forms %}
<div class="form-group">
<label for="{{ form.auto_id }}">{{ form.label }}</label>
{{ form }}
<span class="pull-right text-danger"></span>
</div>
{% endfor %}
<div class="form-group">
<label for="id_myfile">头像
<img src="/static/img/default.png" id="id_img" alt=""
style="width: 80px;height: 80px;margin-top: 10px;margin-left: 20px;">
</label>
<input type="file" id="id_myfile" name="avator" style="display: none;">
</div>
<div class="text-center"><input type="button" class="btn btn-danger" id='id_submit' value="提交"></div>
</form>
</div>
</div>
</div>
<script>
$(function () {
// 获取头像信息
$('#id_myfile').on('change', function () {
var filereader = new FileReader();
filereader.readAsDataURL($(this)[0].files[0]);
filereader.onload = function () {
$('#id_img').attr('src', filereader.result);
}
});
// 检测用户名是否存在
$('#id_username').on('blur', function () {
var _this = $(this);
$.ajax({
url: '/blog/check_username/',
method: 'post',
data: {
'username': $('#id_username').val(),
'csrfmiddlewaretoken': $("[name='csrfmiddlewaretoken']").val()
},
success: function (data) {
if (data !== 100) {
_this.next('span').html(data.msg);
}
}
})
});
// 提交数据
$('#id_submit').on('click', function () {
var formdata = new FormData();
formdata.append('avator', $('#id_myfile')[0].files[0]);
res = $('#id_form').serializeArray();
$.each(res, function (key, value) {
formdata.append(value['name'], value['value'])
});
// console.log(formdata);
$.ajax({
url: '',
method: 'post',
data: formdata,
processData: false,
contentType: false,
success: function (data) {
if (data.code == 100) {
console.log(data.msg);
location.href = data.url;
} else {
$.each(data.error, function (key, value) {
$('#id_' + key).next('span').text(value[0]).parent().addClass('has-error')
});
setTimeout(function () {
$('.text-danger').text('').parent().removeClass('has-error')
}, 3000);
}
}
})
});
})
</script>
</body>
</html>
// 获取头像信息
$('#myfile').on('change', function () {
// 借助于文件阅读器
var filereader = new FileReader();
// 把图片读到filereader对象中
filereader.readAsDataURL($(this)[0].files[0]);
// 文件完全读到文件阅读器以后再执行
filereader.onload = function () {
$('#img').attr('src', filereader.result);
}
});
总路由
path('blog/', include(('blog.urls','blog'), namespace='blog')),
blog路由
path('register/', views.Register.as_view(), name='register'),
path('login/', views.Login.as_view(), name='login'),
from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
from django.views import View
from blog.blog_forms import BlogForm
from blog.models import UserInfo
class Register(View):
def get(self, request, *args, **kwargs):
forms = BlogForm()
return render(request, 'register.html', context={'forms': forms})
def post(self, request, *args, **kwargs):
res = {'code': 100, 'msg': 'success'}
forms = BlogForm(request.POST)
if forms.is_valid():
data = forms.cleaned_data
data.pop('re_password')
files = request.FILES.get('avator')
if files:
data['avator'] = files
UserInfo.objects.create_user(**data)
res['url'] = '/blog/login/'
return JsonResponse(res)
else:
res['code'] = 101
res['msg'] = '数据验证失败'
res['error'] = forms.errors
return JsonResponse(res)
// 提交数据
$('#id_submit').on('click', function () {
var formdata = new FormData();
formdata.append('avator', $('#id_myfile')[0].files[0]);
res = $('#id_form').serializeArray();
$.each(res, function (key, value) {
formdata.append(value['name'], value['value'])
});
$.ajax({
url: '',
method: 'post',
data: formdata,
processData: false,
contentType: false,
success: function (data) {
if (data.code == 100) {
console.log(data.msg);
location.href = data.url;
} else {
$.each(data.error, function (key, value) {
$('#id_' + key).next('span').text(value[0]).parent().addClass('has-error')
});
// 过3秒钟,错误信息清除,在匿名函数中执行
setTimeout(function () {
$('.text-danger').text('').parent().removeClass('has-error')
}, 3000);
}
}
})
});
def check_username(request):
res = {'code': 100, 'msg': None}
if request.is_ajax():
username = request.POST.get('username')
count = UserInfo.objects.filter(username=username).first()
if count:
res['code'] = 102
res['msg'] = '该用户已存在'
return JsonResponse(res)
// 检测用户名是否存在
// 当光标不再username控件上就发送ajax请求,去后台查询
$('#id_username').on('blur', function () {
var _this = $(this);
$.ajax({
url: '/blog/check_username/',
method: 'post',
data: {
'username': $('#id_username').val(),
'csrfmiddlewaretoken': $("[name='csrfmiddlewaretoken']").val()
},
success: function (data) {
if (data !== 100) {
_this.next('span').html(data.msg);
}
}
})
});
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}">script>
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}">script>
<title>登录title>
head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">用户登录h1>
<form action="" id="form">
{% csrf_token %}
<div class="form-group">
<label for="id_username">用户名label>
<input type="text" name="id_username" id="id_username" class="form-control">
div>
<div class="form-group">
<label for="id_password">密码label>
<input type="password" name="id_password" id="id_password" class="form-control">
div>
<div class="form-group">
<label for="id_code">验证码label>
<div class="row">
<div class="col-md-6">
<input type="text" name="id_code" id="id_code" class="form-control">
div>
<div class="col-md-6">
<img src="/blog/get_code/" alt="" width="450px" height="30px" id="id_img">
div>
div>
div>
<div class="form-group text-center">
<input type="button" id="id_submit" class="btn btn-danger" value="提交">
div>
form>
div>
div>
div>
<script>
$(function () {
// 点击切换图形验证码
$('#id_img').on('click', function () {
$(this).attr('src', $(this).attr('src') + '?' + Math.random())
});
$('#id_submit').on('click', function () {
formdata = new FormData();
$.each($('#form').serializeArray(), function (key, value) {
formdata.append(value.name, value.value)
});
$.ajax({
url: '/blog/login/',
method: 'post',
data: formdata,
processData: false,
contentType: false,
success: function (data) {
if (data.code !== 100) {
alert(data.msg)
} else {
location.href = data['url']
}
}
})
});
})
script>
body>
html>
def get_code(request):
# 生成一张图片(Image模块下的new函数,返回一个Image对象)
img = Image.new('RGB', (450, 30), generate_rgb())
# 把图片放到画板上
img_draw = ImageDraw.Draw(img)
img_font = ImageFont.truetype('./static/font/ss.TTF', 25)
code_str = ''
for i in range(5):
lower_char = chr(random.randint(97, 122))
upper_char = chr(random.randint(65, 90))
num_char = str(random.randint(0, 9))
res = random.choice([lower_char, upper_char, num_char])
code_str += res
img_draw.text((i * 70 + 40, i), str(res), generate_rgb(), font=img_font)
for i in range(170):
img_draw.point([random.randint(0, 450), random.randint(0, 30)], fill=generate_rgb())
# 把验证码存到session中
request.session['code'] = code_str
print(code_str)
# 图片保存(写到内存中)
fp = BytesIO()
img.save(fp, 'png')
# 把内容全取出来
data = fp.getvalue()
return HttpResponse(data)
class Login(View):
def get(self, request, *args, **kwargs):
return render(request, 'login.html')
def post(self, request, *args, **kwargs):
res = {'code': 100, 'msg': None}
if request.is_ajax():
username = request.POST.get('id_username')
password = request.POST.get('id_password')
code = request.POST.get('id_code')
if request.session['code'].lower() == code.lower():
user = auth.authenticate(username=username, password=password)
if user:
auth.login(request, user)
res['msg'] = '登录成功'
res['url'] = '/blog/index/'
else:
res['code'] = 103
res['msg'] = '账号或密码有误'
else:
res['code'] = 101
res['msg'] = '验证码错误'
return JsonResponse(res)
else:
res['code'] = 102
res['msg'] = '请求有误'
return JsonResponse(res)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}">script>
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}">script>
<title>登录title>
head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">用户登录h1>
<form action="" id="form">
{% csrf_token %}
<div class="form-group">
<label for="id_username">用户名label>
<input type="text" name="id_username" id="id_username" class="form-control">
div>
<div class="form-group">
<label for="id_password">密码label>
<input type="password" name="id_password" id="id_password" class="form-control">
div>
<div class="form-group">
<label for="id_code">验证码label>
<div class="row">
<div class="col-md-6">
<input type="text" name="id_code" id="id_code" class="form-control">
div>
<div class="col-md-6">
<img src="/blog/get_code/" alt="" width="450px" height="30px" id="id_img">
div>
div>
div>
<div class="form-group text-center">
<input type="button" id="id_submit" class="btn btn-danger" value="提交">
div>
form>
div>
div>
div>
<script>
$(function () {
// 点击切换图形验证码
$('#id_img').on('click', function () {
$(this).attr('src', $(this).attr('src') + '?' + Math.random())
});
$('#id_submit').on('click', function () {
formdata = new FormData();
$.each($('#form').serializeArray(), function (key, value) {
formdata.append(value.name, value.value)
});
$.ajax({
url: '/blog/login/',
method: 'post',
data: formdata,
processData: false,
contentType: false,
success: function (data) {
if (data.code !== 100) {
alert(data.msg)
} else {
location.href = data['url']
}
}
})
});
})
script>
body>
html>
def logout(request):
auth.logout(request)
return redirect(reverse('blog:index'))
class Index(View):
def get(self, request, *args, **kwargs):
return render(request, 'index.html')
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}">script>
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}">script>
<title>首页title>
head>
<body>
<div class="container-fluid">
<div class="row">
<div class="header">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a class="navbar-brand" href="{% url 'blog:index' %}">博客公园a>
div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="{% url 'blog:index' %}">首页a>li>
<li><a href="#">新闻a>li>
ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
div>
<button type="submit" class="btn btn-default">Submitbutton>
form>
{% if request.user.is_authenticated %}
<ul class="nav navbar-nav navbar-right">
<li><a href="#">{{ request.user.username }}a>li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-haspopup="true" aria-expanded="false">更多<span class="caret">span>a>
<ul class="dropdown-menu">
<li><a href="#" id="change_pwd" data-toggle="modal"
data-target=".bs-example-modal-lg">修改密码a>li>
<li><a href="#">修改头像a>li>
<li><a href="{% url 'blog:logout' %}">退出a>li>
ul>
li>
ul>
{% else %}
<ul class="nav navbar-nav navbar-right">
<li><a href="{% url 'blog:register' %}">注册a>li>
<li><a href="{% url 'blog:login' %}">登录a>li>
ul>
{% endif %}
div>
div>
nav>
div>
<div class="body">
<div class="content_left col-md-2">111div>
<div class="content_middle col-md-7">222div>
<div class="content_right col-md-3">333div>
div>
div>
div>
body>
html>
def get_banner(request):
banner_info = [
{'img_url': '/static/img/glasses-banner1.jpg', 'desc': '广告位出租', 'target_url': 'http://www.baidu.com'},
{'img_url': '/static/img/glasses-banner2.jpg', 'desc': '点我买苹果手机12', 'target_url': 'http://www.sina.com'},
{'img_url': '/static/img/glasses-banner3.jpg', 'desc': '北京到上海特价飞机票', 'target_url': 'http://www.bilibi.com'},
]
return JsonResponse(banner_info, safe=False)
<div class="content_middle col-md-7">
<div class="lbt">
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active">li>
<li data-target="#carousel-example-generic" data-slide-to="1">li>
<li data-target="#carousel-example-generic" data-slide-to="2">li>
ol>
<div class="carousel-inner" role="listbox">
<div class="item active">
<img class="banner-img" src="xxx" alt="...">
<div class="carousel-caption">
<a href="" class="link_a">xxxa>
div>
div>
<div class="item">
<img class="banner-img" src="xxx" alt="...">
<div class="carousel-caption">
<a href="" class="link_a">xxxa>
div>
div>
<div class="item">
<img class="banner-img" src="xxx" alt="...">
<div class="carousel-caption">
<a href="" class="link_a">xxxa>
div>
div>
div>
<a class="left carousel-control" href="#carousel-example-generic" role="button"
data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true">span>
<span class="sr-only">Previousspan>
a>
<a class="right carousel-control" href="#carousel-example-generic" role="button"
data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true">span>
<span class="sr-only">Nextspan>
a>
div>
div>
<div class="article">
{% for article in article_list %}
<div class="ever" style="margin-top: 15px">
<h4 class="media-heading">{{article.title}}h4>
<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="media/{{ article.blog.userinfo.avator }}" alt="" height="60px;" width="60px;">
a>
div>
<div class="media-body">
{{ article.desc }}
div>
<div class="article_bottom">
<span><a href="{% url 'blog:my_site' article.blog.userinfo.username %}">{{ article.blog.userinfo.username }}a>span>
<span>{{ article.create_time|date:'Y-m-d H:i:s' }}span>
<span class="glyphicon glyphicon-thumbs-up"> 0span>
<span class="glyphicon glyphicon-briefcase"> 10span>
div>
div>
<hr>
div>
{% endfor %}
div>
div>
<script>
$.ajax({
url: '/blog/get_banner/',
method: 'post',
data: {'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()},
success: function (data) {
$.each(data, function (key, value) {
$('.banner-img')[key].src = value.img_url;
$('.link_a')[key].href = value.target_url;
$($('.link_a')[key]).html(value['desc']);
})
}
})
script>
class Index(View):
def get(self, request, *args, **kwargs):
banner = ['/static/img/glasses-banner1.jpg', '/static/img/glasses-banner2.jpg',
'/static/img/glasses-banner3.jpg']
article_list = models.Article.objects.all()
return render(request, 'index.html', locals())
def post(self, request, *args, **kwargs):
pass
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<style>
.article_bottom span {
margin-right: 10px;
}
style>
<script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}">script>
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}">script>
<title>首页title>
head>
<body>
<div class="container-fluid">
<div class="row">
<div class="header">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigationspan>
<span class="icon-bar">span>
<span class="icon-bar">span>
<span class="icon-bar">span>
button>
<a class="navbar-brand" href="/">博客公园a>
div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="/">首页a>li>
<li><a href="#">新闻a>li>
ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
div>
<button type="submit" class="btn btn-default">Submitbutton>
form>
{% if request.user.is_authenticated %}
<ul class="nav navbar-nav navbar-right">
<li><a href="#">{{ request.user.username }}a>li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-haspopup="true" aria-expanded="false">更多<span class="caret">span>a>
<ul class="dropdown-menu">
<li><a href="#" id="change_pwd" data-toggle="modal"
data-target=".bs-example-modal-lg">修改密码a>li>
<li><a href="#">修改头像a>li>
<li><a href="{% url 'blog:logout' %}">退出a>li>
ul>
li>
ul>
{% else %}
<ul class="nav navbar-nav navbar-right">
<li><a href="{% url 'blog:register' %}">注册a>li>
<li><a href="{% url 'blog:login' %}">登录a>li>
ul>
{% endif %}
div>
div>
nav>
div>
<div class="body">
<div class="content_left col-md-2">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">招商广告h3>
div>
<div class="panel-body">
招商广告栏位出租
div>
div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">北京时间h3>
div>
<div class="panel-body">
北京时间x点x分
div>
div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">招商广告h3>
div>
<div class="panel-body">
招商广告栏位出租
div>
div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">北京时间h3>
div>
<div class="panel-body">
北京时间x点x分
div>
div>
div>
<div class="content_middle col-md-7">
<div class="lbt">
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active">li>
<li data-target="#carousel-example-generic" data-slide-to="1">li>
<li data-target="#carousel-example-generic" data-slide-to="2">li>
ol>
<div class="carousel-inner" role="listbox">
<div class="item active">
<img class="banner-img" src="xxx" alt="...">
<div class="carousel-caption">
<a href="" class="link_a">xxxa>
div>
div>
<div class="item">
<img class="banner-img" src="xxx" alt="...">
<div class="carousel-caption">
<a href="" class="link_a">xxxa>
div>
div>
<div class="item">
<img class="banner-img" src="xxx" alt="...">
<div class="carousel-caption">
<a href="" class="link_a">xxxa>
div>
div>
div>
<a class="left carousel-control" href="#carousel-example-generic" role="button"
data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true">span>
<span class="sr-only">Previousspan>
a>
<a class="right carousel-control" href="#carousel-example-generic" role="button"
data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true">span>
<span class="sr-only">Nextspan>
a>
div>
div>
<div class="article">
{% for article in article_list %}
<div class="ever" style="margin-top: 15px">
<h4 class="media-heading">{{article.title}}h4>
<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="media/{{ article.blog.userinfo.avator }}" alt="" height="60px;" width="60px;">
a>
div>
<div class="media-body">
{{ article.desc }}
div>
<div class="article_bottom">
<span><a href="{% url 'blog:my_site' article.blog.userinfo.username %}">{{ article.blog.userinfo.username }}a>span>
<span>{{ article.create_time|date:'Y-m-d H:i:s' }}span>
<span class="glyphicon glyphicon-thumbs-up"> 0span>
<span class="glyphicon glyphicon-briefcase"> 10span>
div>
div>
<hr>
div>
{% endfor %}
div>
div>
<div class="content_right col-md-3">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">招商广告h3>
div>
<div class="panel-body">
招商广告栏位出租
div>
div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">北京时间h3>
div>
<div class="panel-body">
北京时间x点x分
div>
div>
div>
<div class="content_right col-md-3">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">招商广告h3>
div>
<div class="panel-body">
招商广告栏位出租
div>
div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">北京时间h3>
div>
<div class="panel-body">
北京时间x点x分
div>
div>
div>
div>
div>
div>
{% include 'change_pwd.html' %}
<script>
$(function () {
// 校验密码是否正确
$('#old_password').blur(function (data) {
var _this = $(this);
$.ajax({
url: '/blog/check_old_password/',
method: 'post',
data: {'old_password': $(this).val(), 'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()},
success: function (data) {
if (data.code !== 100) {
_this.next('span').html(data.msg).parent().addClass('has-error')
} else {
_this.next('span').html('').parent().removeClass('has-error')
}
}
})
});
// 修改密码
$('#btn').on('click', function () {
if ($('div').hasClass('has-error')) {
return;
}
$.ajax({
url: '/blog/update_password/',
method: 'post',
data: {
'new_password': $('#new_password').val(),
're_new_password': $('#re_new_password').val(),
'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val(),
},
success: function (data) {
if (data.code == 100) {
alert(data.msg);
location.reload();
} else {
$('#re_new_password').next().html(data.msg).parent().addClass('has-error')
}
}
})
});
// 获取banner图
$.ajax({
url: '/blog/get_banner/',
method: 'post',
data: {'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()},
success: function (data) {
$.each(data, function (key, value) {
$('.banner-img')[key].src = value.img_url;
$('.link_a')[key].href = value.target_url;
$($('.link_a')[key]).html(value['desc']);
})
}
})
})
script>
body>
html>
# 路由
path('admin/', admin.site.urls),
# admin.py中注册
from django.contrib import admin
from blog import models
admin.site.register(models.UserInfo)
admin.site.register(models.Article)
admin.site.register(models.Blog)
admin.site.register(models.Category)
admin.site.register(models.UpAndDown)
admin.site.register(models.Comment)
admin.site.register(models.Tag)
admin.site.register(models.TagToArticle)
# setting中配置国际化
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
# 表名显示中文
class Meta:
verbose_name_plural='标签表'
# 数据显示中文
def __str__(self):
return self.name
1、用户上传的头像能够在浏览器中访问到
2、默认情况下,static下的都能访问
3、media文件夹下的图片不能访问,需要手动打开
4、使用方式
项目根路径下新建media文件夹
setting中配置MEDIA_ROOT=os.path.join(BASE_DIR,'media')
路由中配置:
from django.urls import re_path
from django.views.static import serve
from django.conf import settings
re_path('^media/(?P.*)$' , serve,{'document_root': settings.MEDIA_ROOT}),
# 个人站点 访问tag/category/achive
re_path(r'^my_site/(?P\w+)/(?Ptag|category|achive)/(?P.*).html$' , views.my_site,name='my_site'),
re_path(r'^my_site/(?P\w+)/' , views.my_site, name='my_site'),
def my_site(request, name, **kwargs):
obj = UserInfo.objects.filter(username=name).first()
if obj:
article_list = models.Article.objects.filter(blog__userinfo__username=name)
query = kwargs.get('query', None)
if query == 'category':
condition = kwargs.get('condition')
article_list = article_list.filter(category_id=condition)
elif query == 'tag':
condition = kwargs.get('condition')
article_list = article_list.filter(tagtoarticle__tag_id=condition)
elif query == 'achive':
year, month = kwargs.get('condition').split('/')
article_list = article_list.filter(create_time__year=year, create_time__month=month)
return render(request, 'my_site.html', locals())
else:
return render(request, 'error.html')
{% extends 'base.html' %}
{% block content %}
<div class="article">
{% for article in article_list %}
<div class="ever" style="margin-top: 15px">
<h4 class="media-heading"><a href="{% url 'blog:article_detail' name article.id %}">{{ article.title }}a>h4>
<div class="media">
<div class="media-body">
{{ article.desc }}
div>
<div class="article_bottom pull-right">
@posted by
<span>{{ article.blog.userinfo.username }}span>
<span>{{ article.create_time|date:'Y-m-d H:i:s' }}span>
<span><i class="fa fa-hand-pointer-o fa-lg">i> {{ article.up_num }}span>
<span><i class="fa fa-comment fa-lg">i> {{ article.comment_num }}span>
<span><a href="">编辑a>span>
div>
div>
<hr>
div>
{% endfor %}
div>
{% endblock %}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<title>Documenttitle>
head>
<body>
<div class="error-panel server-error error-404 text-center">
<img src="//static.hdslb.com/error/very_sorry.png">
<div style="text-align: center; padding: 0 0 40px 0;">
<a class="rollback-btn" style="padding: 0 20px; float: none;">返回上一页a>
div>
div>
body>
html>
def up_and_down(request):
res = {'code': 100, 'msg': None}
if request.is_ajax():
if request.user.is_authenticated:
article_id = request.POST.get('article_id')
obj = models.UpAndDown.objects.filter(user_id=request.user.id, article_id=article_id).first()
if obj:
res['code'] = 103
res['msg'] = '您已经提交过'
else:
# 写数据库
is_up = request.POST.get('is_up')
is_up = json.loads(is_up)
# 点赞点踩表增加数据
models.UpAndDown.objects.create(is_up=is_up, user_id=request.user.id, article_id=article_id)
# 文章表点赞点踩数量加1
try:
with transaction.atomic():
if is_up:
models.Article.objects.filter(id=article_id).update(up_num=F('up_num') + 1)
res['msg'] = '点赞成功'
else:
models.Article.objects.filter(id=article_id).update(down_num=F('down_num') + 1)
res['msg'] = '点踩成功'
res['code'] = 100
except Exception as e:
res['code'] = 104
res['msg'] = '数据异常'
else:
res['code'] = 102
res['msg'] = '请登录后再操作'
else:
res['code'] = 101
res['msg'] = '非法操作'
return JsonResponse(res)
{% extends 'base.html' %}
{% block ext_css %}
{% load static %}
<link rel="stylesheet" href="{% static 'css/my_css.css' %}">
{% endblock %}
{% block content %}
{% csrf_token %}
<h2>{{ article.title }}h2>
<hr>
<div class="content" style="text-indent:2em;">{{ article.content }}div>
{# 点赞点踩 #}
<div class="upanddown clearfix">
<div id="div_digg">
<div class="diggit up_or_down">
<span class="diggnum" id="digg_count">{{ article.up_num }}span>
div>
<div class="buryit up_or_down">
<span class="burynum" id="bury_count">{{ article.down_num }}span>
div>
<div class="clear">div>
<div class="diggword" id="digg_tips" style="color: red;">
div>
div>
div>
<hr>
{# 评论 #}
<div class="comment_list">
评论列表
<ul class="list-group">
{% for comment in comment_list %}
<li class="list-group-item">
<div>
<span>#{{ forloop.counter }}楼span>
<span>{{ comment.create_time|date:'Y-m-d H:i:s' }}span>
<span><a
href="{% url 'blog:my_site' comment.user.username %}">{{ comment.user.username }}a>span>
<span class="replay pull-right" parent="{{ comment.pk }}"
username="{{ comment.user.username }}"><a>回复a>span>
{% if comment.comments_id %}
<p>@{{ comment.article.blog.userinfo.username }}p>
<p><span>{{ comment.content }}span>p>
{% else %}
<p><span>{{ comment.content }}span>p>
{% endif %}
div>
li>
{% endfor %}
ul>
div>
<hr>
{% if request.user.is_authenticated %}
<div class="comment" style="margin-top: 15px;">
<div class="form-group">
<div>发表评论div>
<textarea name="content" id="content_textarea" cols="100" rows="15">textarea>
div>
<div class="form-group">
<button class="btn btn-info" id="id_btn">提交button>
div>
div>
{% else %}
<div>登录后才能发表评论,立即 <a href="{% url 'blog:login' %}">登录a> 或 <a href="{% url 'blog:register' %}">注册a>, 访问 <a
href="/">网站首页a>div>
{% endif %}
{% endblock %}
{% block ext_js %}
<script>
$(function () {
parent_id = '';
$('.up_or_down').on('click', function () {
var _this = $(this);
is_up = true;
if ($(this).children().hasClass('burynum')) {
is_up = false;
}
$.ajax({
url: '/blog/up_and_down/',
method: 'post',
data: {
article_id: '{{ article.id }}',
is_up: is_up,
csrfmiddlewaretoken: $('input[name="csrfmiddlewaretoken"]').val(),
},
success: function (data) {
if (data.code == 100) {
num = Number(_this.children('span').html()) + 1;
_this.children('span').html(num);
}
$('#digg_tips').html(data.msg);
}
})
});
$('#id_btn').on('click', function () {
let content = $('#content_textarea').val();
if (parent_id) {
// 子评论
str = content.indexOf('\n') + 1;
content = content.slice(str);
}
$.ajax({
url: '/blog/commit_comment/',
method: 'post',
data: {
article_id: '{{ article.id }}',
content: content,
parent_id: parent_id,
csrfmiddlewaretoken: $('input[name="csrfmiddlewaretoken"]').val(),
},
success: function (data) {
content_text = '';
var username = data.username;
var content = $('#content_textarea').val();
if (data.code == 100) {
if (parent_id) {
var parent_name = data.parent_name;
content_text = `
${username}
${parent_name}
${content}
`;
} else {
content_text = `
${username}
${content}
`;
}
$('#content_textarea').val('');
$('.list-group').append(content_text);
parent_id = '';
}
}
})
});
// replay功能
$('.replay').on('click', function () {
username = $(this).attr('username');
parent_id = $(this).attr('parent');
replay = `@${username}\n`;
$('#content_textarea').html(replay).focus();
});
});
script>
{% endblock %}
def commit_comment(request):
res = {'code': 100, 'msg': '评论成功'}
if request.is_ajax():
if request.user.is_authenticated:
parent_id = request.POST.get('parent_id')
user_id = request.user.id
article_id = request.POST.get('article_id')
content = request.POST.get('content')
try:
with transaction.atomic():
models.Comment.objects.create(user_id=user_id, content=content, article_id=article_id,
comments_id=parent_id)
article = models.Article.objects.filter(id=article_id).update(comment_num=F('comment_num') + 1)
res['username'] = request.user.username
if parent_id:
old_user_id = models.Comment.objects.filter(pk=parent_id).first().user_id
res['parent_name'] = models.UserInfo.objects.filter(pk=old_user_id).first().username
# from django.core.mail import send_mail
#
# send_mail('您的文章{}被评论了'.format(article.title), '{}评论了{}'.format(settings.EMAIL_HOST_USER,
# content), settings.EMAIL_HOST_USER,
# models.UserInfo.objects.filter(pk=old_user_id).first().email)
except Exception as e:
print(e)
res['code'] = 103
res['msg'] = '内部错误'
else:
res['code'] = 102
res['msg'] = '用户未登录'
else:
res['code'] = 101
res['msg'] = '非法操作'
return JsonResponse(res)
同12.2章节
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>后台页面title>
{% block ext_css %}
{% endblock %}
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'font-awesome-4.7.0/css/font-awesome.min.css' %}">
<script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}">script>
<link rel="stylesheet" href="{% static 'bootstrap/js/bootstrap.min.js' %}">
head>
<body>
<div class="header">
<nav class="navbar navbar-default navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">后台管理a>
div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="/">首页 <span class="sr-only">(current)span>a>li>
<li class=""><a href="{% url 'blog:update_avator' %}">修改头像 <span class="sr-only">(current)span>a>li>
ul>
div>
div>
nav>
div>
div>
<div class="container-fluid">
<div class="row">
<div class="left_content col-md-3">
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne"
aria-expanded="true" aria-controls="collapseOne">
操作
a>
h4>
div>
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
aria-labelledby="headingOne">
<div class="panel-body">
<ul class="nav">
<li><a href="{% url 'blog:create_article' %}">新增文章a>li>
<li><a href="">新增随笔a>li>
ul>
div>
div>
div>
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingTwo">
<h4 class="panel-title">
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion"
href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
分类
a>
h4>
div>
<div id="collapseTwo" class="panel-collapse collapse" role="tabpanel"
aria-labelledby="headingTwo">
<div class="panel-body">
div>
div>
div>
div>
div>
<div class="col-md-9">
<div>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#home" aria-controls="home" role="tab"
data-toggle="tab">文章a>li>
<li role="presentation"><a href="#profile" aria-controls="profile" role="tab"
data-toggle="tab">评论a>
li>
<li role="presentation"><a href="#messages" aria-controls="messages" role="tab"
data-toggle="tab">日志a>
li>
<li role="presentation"><a href="#settings" aria-controls="settings" role="tab"
data-toggle="tab">标签a>
li>
ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="home">
{% block content %}
{% endblock %}
div>
<div role="tabpanel" class="tab-pane" id="profile">
评论的内容
div>
<div role="tabpanel" class="tab-pane" id="messages">
日志的内容
div>
<div role="tabpanel" class="tab-pane" id="settings">
标签的内容
div>
div>
div>
div>
div>
div>
{% block ext_js %}
{% endblock %}
body>
html>
{% extends 'backend/base.html' %}
{% block content %}
<table class="table table-hover table-striped">
<thead>
<tr>
<th>标题th>
<th>评论数th>
<th>点赞数th>
<th>操作th>
<th>操作th>
tr>
thead>
<tbody>
{% for article in article_list %}
<tr>
<td>
<a href="/{{ article.blog.userinfo.username }}/article/{{ article.pk }}.html">{{ article.title }}a>
td>
<td>{{ article.comment_num }}td>
<td>{{ article.up_num }}td>
<td><a href="{% url 'blog:update_article' article.id %}">编辑a>td>
<td><a href="">删除a>td>
tr>
{% endfor %}
tbody>
table>
{% endblock %}
def admin_index(request):
article_list = models.Article.objects.filter(blog=request.user.blog).all()
return render(request, 'backend/admin_index.html', locals())
{% extends 'backend/base.html' %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<div class="form-group">
<label for="">文章标题label>
<input type="text" class="form-control" name="title" value="{{ article.title }}">
div>
<div class="form-group">
<label for="">文章内容label>
<p><textarea name="content" id="editor_id" cols="30" rows="10">{{ article.content }}textarea>p>
div>
<div class="form-group">
<label for="">分类label>
{% for category in category_list %}
<input type="radio" name="category_id" value="{{ category.id }}">{{ category.name }}
{% endfor %}
div>
<div class="form-group">
<label for="">标签label>
{% for tag in tag_list %}
<input type="checkbox" name="tag_id" value="{{ tag.id }}">{{ tag.name }}
{% endfor %}
div>
<div class="text-center">
<button class="btn btn-primary">创建文章button>
div>
form>
{% endblock %}
def create_article(request):
if request.method == 'GET':
category_list = models.Category.objects.filter(blog=request.user.blog).all()
tag_list = models.Tag.objects.filter(blog=request.user.blog).all()
return render(request, 'backend/create_article.html', locals())
else:
title = request.POST.get('title')
content = request.POST.get('content')
category_id = request.POST.get('category_id')
tag_id = request.POST.getlist('tag_id')
soup = BeautifulSoup(content, 'html.parser')
desc = soup.text[0:90]
res_script = soup.find_all('script')
for script in res_script:
script.decompose()
article = models.Article.objects.create(title=title, content=str(soup), description=desc, blog=request.user.blog,
category_id=category_id)
ll = []
for tag in tag_id:
ll.append(models.TagToArticle(tag_id=tag, article_id=article.pk))
models.TagToArticle.objects.bulk_create(ll)
return redirect(reverse('blog:admin_index'))
{% extends 'backend/base.html' %}
{% block content %}
<form action="{% url 'blog:update_article' article.id %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="">文章标题label>
<input type="text" class="form-control" name="title" value="{{ article.title }}">
div>
<div class="form-group">
<label for="">文章描述label>
<input type="text" class="form-control" name="desc" value="{{ article.desc }}">
div>
<div class="form-group">
<label for="">文章内容label>
<textarea name="content" id="editor_id" cols="30" rows="10">{{ article.content }}textarea>
div>
<div class="text-center">
<button class="btn btn-primary">修改button>
div>
form>
{% endblock %}
{% block ext_js %}
{% load static %}
<script charset="utf-8" src="{% static 'kindeditor/kindeditor-all.js' %}">script>
<script>
KindEditor.ready(function (K) {
window.editor = K.create('#editor_id', {
width: '100%',
height: '500px',
uploadJson: '/blog/upload_img/',
filePostName: 'myfile',
extraFileUploadParams: {
csrfmiddlewaretoken: '{{ csrf_token }}',
}
});
});
script>
{% endblock %}
def update_article(request, id):
if request.method == 'GET':
article = models.Article.objects.get(pk=id)
return render(request, 'backend/update_article.html', locals())
else:
title = request.POST.get('title')
desc = request.POST.get('desc')
content = request.POST.get('content')
models.Article.objects.filter(pk=id).update(title=title, description=desc, content=content)
return redirect(reverse('blog:admin_index'))
{% extends 'backend/base.html' %}
{% block content %}
{% csrf_token %}
<div class="form-group">
<label for="">原始头像label>
<img src="/media/{{ user.avator }}" alt="" width="80" height="80">
div>
<div class="form-group">
<label for="upload_avator">上传新头像
<img src="/media/{{ user.avator }}" alt="" width="80" height="80" id="id_img">
label>
<input type="file" name="myfile" value="上传头像" id="upload_avator" style="display: none">
div>
<div class="text-center">
<button class="btn btn-primary" id="id_btn">修改头像button>
div>
{% endblock %}
{% block ext_js %}
{% load static %}
<script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}">script>
<script>
$(function () {
$('#upload_avator').on('change', function () {
filereader = new FileReader();
formdata = new FormData();
filereader.readAsDataURL($(this)[0].files[0]);
filereader.onload = function () {
$('#id_img').attr('src', filereader.result);
formdata.append('avator', $('#id_img').attr('src'));
}
});
$('#id_btn').on('click', function () {
formdata.append('myfile', $('#upload_avator')[0].files[0]);
formdata.append('csrfmiddlewaretoken', $('input[name="csrfmiddlewaretoken"]').val());
$.ajax({
url: '',
method: 'post',
data: formdata,
contentType: false,
processData: false,
success: function (data) {
if (data.code == 100) {
window.location.href = data.url
} else {
alert(data.msg)
}
}
})
});
})
script>
{% endblock %}
@login_required(login_url='/blog/login/')
def update_avator(request):
res = {'code': 100, 'msg': 'success'}
if request.is_ajax():
try:
request.user.avator = request.FILES.get('myfile')
request.user.save()
res['url'] = reverse('blog:update_avator')
except Exception as e:
res['code'] = 101
res['msg'] = 'error'
return JsonResponse(res)
else:
return render(request, 'update_avator.html')