Django实战——个人博客网站(二)

写博客

先上个图 结构是用 django forms类 写的 比较方便
在这里插入图片描述
在index 新建一个 forms.py

from django import forms


class CommentForm(forms.Form):
    """
    评论表单用于发表博客的评论。评论表单的类并根据需求定义了三个字段:称呼、邮箱和评论内容。这样我们就能利用它来快速生成表单并验证用户的输入。
    """
    name = forms.CharField(label='称呼', max_length=16, error_messages={
        'required': '请填写您的称呼',
        'max_length': '称呼太长咯'
    })

    email = forms.EmailField(label='邮箱', error_messages={
        'required': '请填写您的邮箱',
        'invalid': '邮箱格式不正确'
    })

    content = forms.CharField(label='评论内容', error_messages={
        'required': '请填写您的评论内容!',
        'max_length': '评论内容太长咯'
    })
TYPES = (
    ('1','前端'),
    ('2','文学'),
    ('3','艺术'),
    ('4','科学')
)
TAGS = (
    ('python','python'),
    ('web','web'),
    ('django','django'),
    ('html','html')
)
class Writeblog(forms.Form):
    title = forms.CharField(label='标题',widget=forms.TextInput,max_length=16,error_messages={
        'required': '请填写您的称呼',
        'max_length': '称呼太长咯'
    })
    author = forms.CharField(label='作者',max_length=5,error_messages={
        'required': '请填写您的称呼',
        'max_length': '称呼太长咯'
    })
    content = forms.CharField(label='正文',widget=forms.Textarea,error_messages={
        'required': '请填写您的评论内容!',
        'max_length': '评论内容太长咯'
    })
    catagroy = forms.ChoiceField(label='分类',choices=TYPES,widget=forms.RadioSelect)
    tag = forms.ChoiceField(label='标签',choices=TAGS,widget=forms.CheckboxSelectMultiple)

在视图中导入forms,创建一个write url

  url(r'^write/$',write),

当点击 网页上的超链接 访问这个路由 进入write.html

def write(request):
    if request.method == 'GET':
        form = Writeblog()
        return render(request, 'write.html', locals())

在网页上填好数据后 点击提交 后端接受POST请求
接收到数据 保存到创建的对象中去 多选框值得获取 要分类 1 个 或者多个的情况
tag 是多对多的关系 所以 先保存其他的数据 再进行添加tag的数据

else:
        blog = Blog()
        blog.title = request.POST['title']
        name = request.POST.getlist('tag')
        blog.author = request.POST['author']
        blog.content = request.POST['content']
        blog.catagory_id = request.POST['catagroy']
        blog.save()
        print('name:',name)
        if len(name) == 1:
            tag = Tag.objects.get(name=name[0])
            blog.tags.add(tag)
            blog.save()
        elif len(name) == 0:
            pass
        else:
            for t in name:
                print(t)
                tag = Tag.objects.get(name=t)
                blog.tags.add(tag)
            blog.save()
        return redirect('/blog/')

写完后 需要在页面上进行展示 博客列表

来个博客展示页面的路由

  url(r'^blog/$',blog),

博客展示每一页定位三篇 超过的分页处理 分类要用到的库

from django.core.paginator import Paginator,
 PageNotAnInteger, EmptyPage, InvalidPage

思路是先从数据库中获取到所有博客的对象信息,进行分页处理后,然后发送前端,还要处理好阅读量 和 评论数
评论和博客 是多对一的关系 对于Blog 有一个 comment_set属性可以获取博客的评论信息
每一篇博客的评论数是 0 -n 个
先获取所有博客的对象数据,按照最新的时间排序

 bolg = Blog.objects.order_by('-created').all()

再 遍历blog 获取每一篇博客的评论数量,因为我不怎么会用ajax发送数据 导致我很难将 这个评论数发送给前端 我就想了一个方法 直接给blog加一个commentNum的字段 我遍历出每个博客的评论数 然后直接添加回 blog中的commentNum 这样我在前端只需要用
{{ blog. commentNum}} 就可以获取到评论数

for i in bolg:
           com = i.comment_set.count()
           i.commentNum = com
           i.save()
           comments = Comment.objects.order_by('-blog_id').all()

修改完评论数后 再重新获取一下blog的对象

 bolgs = Blog.objects.order_by('-created').all()

接下来进行分页的处理 分页的处理 是参考网上的 本来我也不会

  # 将数据按照规定每页显示 3 条, 进行分割
        paginator = Paginator(bolgs, 3)

        if request.method == "GET":
            # 获取 url 后面的 page 参数的值, 首页不显示 page 参数, 默认值是 1
            page = request.GET.get('page')
            try:
                blogs = paginator.page(page)
            # todo: 注意捕获异常
            except PageNotAnInteger:
                # 如果请求的页数不是整数, 返回第一页。
                blogs = paginator.page(1)
            except InvalidPage:
                # 如果请求的页数不存在, 重定向页面
                return HttpResponse('找不到页面的内容')
            except EmptyPage:
                # 如果请求的页数不在合法的页数范围内,返回结果的最后一页。
                blogs = paginator.page(paginator.num_pages)

            template_view = 'blog.html'
            print(locals())
            return render(request, template_view, locals())

前端代码(几乎没用到什么js代码)
遍历被分页处理过的 bolgs
{% for i in bolgs%}
这里面填充 博客的各种信息 以及评论数
{% endfor %}

   {% for blog in blogs %}
    <div align="center" id="center">
        <div id="header1">
            <a id="title" href="/detail/{{ blog.id }}">{{ blog.title }}</a>
        </div>
        <div id="end">
            {{ blog.content | truncatechars:100}}
        </div><p>Tagged: <a href="#"><span id="author">{{ blog.catagory }}</span></a></p>
     <p><a href="#"><strong>Comments ({{ blog.commentNum }})</strong></a>
         <span>&nbsp;&bull;&nbsp;</span>  <span id="created">{{ blog.created |date:"Y-m-d H:i" }}</span>  <span>&nbsp;&bull;&nbsp;</span>  <a href="#"><strong>read &nbsp;({{ blog.readnum }})</strong></a></p>
    </div>
    {% endfor %}
    <div id="pages" class="text-center" >
        <nav>
            <ul class="pagination">
                <li class="step-links">
                {% if blogs.number > 1 %}
                     <a class='active' href="?page=1">首页&nbsp;</a>
                {% endif %}
                {% if blogs.has_previous %}
                    <a class='active' href="?page={{ blogs.previous_page_number }}">上一页</a>
                {% endif %}

                <span class="current">
                    Page {{ blogs.number }} of {{ blogs.paginator.num_pages }}</span>

                {% if blogs.has_next %}
                    <a class='active' href="?page={{ blogs.next_page_number }}">下一页</a>
                {% endif %}
                {% if blogs.number < blogs.paginator.num_pages %}
                  <a class='active' href="?page={{ blogs.paginator.num_pages }}">&nbsp;尾页</a>
                {% endif %}
                </li></ul></nav></div>
        </div>

效果图
在这里插入图片描述

点击博客的标题 会跳转到详情页 这时候会访问一个detail的路由

<a id="title" href="/detail/{{ blog.id }}">{{ blog.title }}</a>

然后这里要记录一下 阅读数
每进一次 路由 都把 num +1 然后修改 blog 中的 readnum 字段的属性 再发送给前端 显示阅读数 路由会带着 博客的id 确定进入的是那一个博客
然后先得到博客点击前的阅读数
num = Blog.objects.filter(id=blog_id).values(‘readnum’)
这个num 是一个querySet对象 需要先转成字典或者列表 再取出值
这里用了
num = list(num)
num = num[0][‘readnum’] + 1
再保存回数据库中

def detail(request,blog_id):
    blog_id = int(blog_id)
    blog = Blog.objects.get(id=blog_id)
    num = Blog.objects.filter(id=blog_id).values('readnum')
    num = list(num)
    num = num[0]['readnum'] + 1
    blog.readnum = num
    blog.save()

在详情页中 还有评论 和展示评论的 功能
老样子 在forms中创建好表单

class CommentForm(forms.Form):
    """
    评论表单用于发表博客的评论。评论表单的类并根据需求定义了三个字段:称呼、邮箱和评论内容。这样我们就能利用它来快速生成表单并验证用户的输入。
    """
    name = forms.CharField(label='称呼', max_length=16, error_messages={
        'required': '请填写您的称呼',
        'max_length': '称呼太长咯'
    })

    email = forms.EmailField(label='邮箱', error_messages={
        'required': '请填写您的邮箱',
        'invalid': '邮箱格式不正确'
    })

    content = forms.CharField(label='评论内容', error_messages={
        'required': '请填写您的评论内容!',
        'max_length': '评论内容太长咯'
    })

在视图中,创建这个表单对象 发送给前端 显示

if request.method == 'GET':
        form = CommentForm()

前端

  <form action="/reflash/{{ blog.id }}/" method="post">
                {% csrf_token %}
                {% for field in form %}
                    <div class="input-field" style="padding-top: 10px">
                        {{ field.label }}: {{ field }}
                    </div>
                    <div class="error" style="color: red;">
                        {{ field.errors }}
                    </div>
                {% endfor %}
                <button type="submit" style="margin-top: 10px">提交</button>
            </form>

给评论也来个分页处理,先从数据库获取该博客下的所有评论 分页处理后发给前端

   comments = Comment.objects.filter(blog_id=blog_id).order_by('-created').all()
    num = Comment.objects.filter(blog_id=blog_id).count()
    paginator = Paginator(comments, 3)
    if request.method == 'GET':
        form = CommentForm()
        # 获取 url 后面的 page 参数的值, 首页不显示 page 参数, 默认值是 1
        page = request.GET.get('page')
        print('page:', page)
        try:
            blogs = paginator.page(page)
        # todo: 注意捕获异常
        except PageNotAnInteger:
            # 如果请求的页数不是整数, 返回第一页。
            blogs = paginator.page(1)
        except InvalidPage:
            # 如果请求的页数不存在, 重定向页面
            return HttpResponse('找不到页面的内容')
        except EmptyPage:
            # 如果请求的页数不在合法的页数范围内,返回结果的最后一页。
            blogs = paginator.page(paginator.num_pages)

楼层数的显示 直接用django中自带的 {{forloop.counter}} 是从1 开始计数 这样省去了遍历计数的麻烦

 <span id="authors">{{forloop.counter}}&nbsp; {{ comment.name }} </span>

在这里插入图片描述
提交评论 表单把数据发送给 reflash 路由进行处理

 <form action="/reflash/{{ blog.id }}/" method="post">

在 reflash 视图中,接收到 前端传过来的评论信息
保存至数据库 然后访问 detail 路由
在detail 中 会从数据库中获取评论 然后再发给 前端
这就实现了 评论完后 显示评论出来 其实就是 刷新了一下页面

def reflash(request,blog_id):
    if request.method == 'POST':
        blog_id = int(blog_id)
        blog = Blog.objects.get(id=blog_id)
        form = CommentForm(request.POST)
        if form.is_valid():
            clean_data = form.cleaned_data
            clean_data['blog'] = blog
            Comment.objects.create(**clean_data)
        return redirect('/detail/%s'%blog_id)
发布了9 篇原创文章 · 获赞 25 · 访问量 1575
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览