Day 05 BBS项目04 个人站点完善+文章详情+点踩
侧边栏 分类
前端
<div class="col-3">
<div class="list-group text-center">
<button type="button" class="list-group-item list-group-item-action active">
随笔
</button>
{% for category in categorys %}
# 这里配置的路径 是 /用户名/分类/分类id
<a href="/{
{ user.username }}/category/{
{ category.id }}.html">{
{ category.name }}({
{ category.count }})</a>
{% endfor %}
</div>
<div class="list-group text-center">
<button type="button" class="list-group-item list-group-item-action active">
标签
</button>
{% for tag in tags %}
<a href="/{
{ user.username }}/tag/{
{ tag.id }}.html">{
{ tag.name }}({
{ tag.count }})</a>
{% endfor %}
</div>
<div class="list-group text-center">
<button type="button" class="list-group-item list-group-item-action active">
时间
</button>
{% for month in gpby_month %}
<a href="/{
{ user.username }}/time/{
{ month.month|date:'Y/m' }}.html">{
{ month.month|date:'Y年m月' }}({
{ month.count }})</a>
{% endfor %}
</div>
后端
categorys = models.Category.objects.filter(blog=user.blog).annotate(count=Count('article__id')).values(
'name', 'count', 'id')
tags = models.Tag.objects.filter(blog=user.blog).annotate(count=Count('article__id')).values('name',
'count',
'id')
gpby_month = models.Article.objects.filter(blog=user.blog).annotate(
# 这里用了一个 直接切分时间的方法
month=TruncMonth('publish_time')).values(
'month').annotate(count=Count('id')).order_by('-month').values('month', 'count')
# 这是返回的信息 按照分类的 按照标签的 按照 时间的
url 配置
# /人名/类型/
url('^(?P<name>\w+)/(?P<type>category|tag|time)/(?P<content>.*).html$', views.user_info),
## 个人站点路由设计 放在后 以免出现 用户名与网站名重复现象
url('^(?P<name>\w+)$', views.user_info),
完成后端
def user_info(request, name, **kwargs):
user = models.User_info.objects.filter(username=name).first()
print(kwargs)
if user:
query = kwargs.get('type', None)
if user.blog:
articles = user.blog.article_set.all()
if query == 'category':
content = kwargs.get('content')
articles = articles.filter(category__id=content)
elif query == 'tag':
content = kwargs.get('content')
articles = articles.filter(tag__id=content)
elif query == 'time':
year, month = kwargs.get('content').split('/')
articles = articles.filter(publish_time__year=year, publish_time__month=month)
categorys = models.Category.objects.filter(blog=user.blog).annotate(count=Count('article__id')).values(
'name', 'count', 'id')
tags = models.Tag.objects.filter(blog=user.blog).annotate(count=Count('article__id')).values('name',
'count',
'id')
gpby_month = models.Article.objects.filter(blog=user.blog).annotate(
month=TruncMonth('publish_time')).values(
'month').annotate(count=Count('id')).order_by('-month').values('month', 'count')
return render(request, 'userinfo.html',
{
'articles': articles, 'user': user, 'categorys': categorys, 'tags': tags,
'gpby_month': gpby_month})
else:
return render(request, 'userinfo.html', {
'articles': '这个作者很懒什么都没留下!', 'user': user, 'code': 101})
return render(request, 'userinfo.html')
文章页
前端
<body>
<style>
img {
width: 100%;
height: 100%;
}
#UpAndDown {
width: 100px;
height: 50px;
background-color: transparent;
position: fixed;
right: 30px;
bottom: 30px;
border-radius: 4px;
outline: none;
border: none;
z-index: 2;
}
#avatar {
width: 80px;
height: 80px;
border-radius: 40px;
}
.status {
color: #f44a28;
}
i {
cursor: pointer;
}
#UpAndDown > p {
font-size: 12px;
color: rgba(201, 0, 0, 0.67);
}
</style>
<div class="jumbotron jumbotron-fluid bg-primary">
<div class="container">
<div id="avatar" class="float-right">
<img src="/media/{
{ article.blog.user_info.avatar }}" class="rounded-circle thumbnail">
<p class="text-warning text-center">{
{ article.blog.user_info.username }}</p>
</div>
<h4 class="display-4">我是{
{ article.blog.user_info.username }}</h4>
<p class="lead">{
{ article.blog.site_name }}</p>
<h1>欢迎!来到{
{ article.blog.site_title }}</h1>
</div>
</div>
<div class="row">
<div class="col2"></div>
<div class="col8" style="margin-left: 60px">
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h3 class="display-4">{
{ article.title }}</h3>
<p class="lead">{
{ article.introduction }}</p>
</div>
</div>
</div>
<div class="col2">
<div id="UpAndDown" class="float-right">
<i class="iconfont icon-dianzan up">{
{ article.up_num }}</i> <i id="down"
class="iconfont icon-diancai">{
{ article.down_num }}</i>
<p></p>
</div>
</div>
</div>
后端
返回文章信息 在页面布局就好了
def article_info(request, name, id):
user = models.User_info.objects.filter(username=name).first()
article = user.blog.article_set.get(id=id)
return render(request, 'articles.html', {
'article': article})
点赞点踩
前端
主要是在这里
<div class="col2">
<div id="UpAndDown" class="float-right">
<i class="iconfont icon-dianzan up">{
{
article.up_num }}</i> <i id="down"
class="iconfont icon-diancai">{
{
article.down_num }}</i>
<p></p>
</div>
</div>
$('.iconfont').click(function () {
{
#找到带有up的 i 标签 找到了就是true 没有就是false#}
var is_up = $(this).hasClass('up')
{
# 找到 i 标签下的提示p标签 错误信息在这里打印#}
var p = $('#UpAndDown>p')
{
#ajax 发送请求#}
$.ajax({
url: '/upordowm',
method: 'post',
data: {
article_id: '{
{ article.id }}',
is_up: is_up,
csrfmiddlewaretoken: '{
{ csrf_token }}'
},
success: (result) => {
{
# 那里点了 亮那里#}
$(this).addClass('status')
{
# p 增加提示信息#}
p.html(result.msg)
if (result.code === 100)
{
# 给后面的点赞点踩数量 加1 不加number默认字符串相加 #}
$(this).html(Number($(this).html()) + 1)
{
#两面中后所有格式清除#}
setTimeout(() => {
p.html(' ')
$(this).removeClass('status')
}, 2000)
}
})
})
后端
def upordown(request):
result = {
'code': 100, 'msg': ' '}
print(request.POST)
if request.user.is_authenticated:
article_id = request.POST.get('article_id')
user_id = request.user.id
is_up = request.POST.get('is_up')
is_up = json.loads(is_up)
like_and_select = models.LikeAndCollect.objects.filter(article_id=article_id, user_id=user_id).count()
if like_and_select:
result['code'] = 101
result['msg'] = '已经点过赞了哦!'
else:
with transaction.atomic():
models.LikeAndCollect.objects.create(article_id=article_id, user_id=user_id,
like=is_up)
if is_up:
models.Article.objects.filter(pk=article_id).update(up_num=F('up_num') + 1)
result['msg'] = '点赞成功!'
else:
models.Article.objects.filter(pk=article_id).update(down_num=F('down_num') + 1)
result['msg'] = '点踩成功!'
else:
result['code'] = 109
result['msg'] = '请先<a href="/signin/">登录</a>'
return JsonResponse(result)
注意
up_num 和 down_num 是新增给 article的两个字段