python Actual Warfare - Blog System (Improvement)

Keywords: Python Django Database

The last blog of Blog System hasn't realized the functions of tag search, date search and classification search. This blog is mainly an increase of the above functions.

Add comments

Step 1: Create a new app:comment, add a new app in the main set. py, and modify the main urls.py file

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'',include('blog.urls')),
    url(r'',include('comments.urls')),

]

Step 2: Write a database form for reviews

from django.contrib.auth.models import User
from django.db import models

# Create your models here.
from blog.models import Post


class Comment(models.Model):
    user =models.ForeignKey(User,verbose_name='user')
    email = models.EmailField(verbose_name='Mail box')
    text = models.TextField(max_length=255,verbose_name='Comment text')
    # auto_now_add=True auto create_time for the latest change in comment information
    create_time = models.DateTimeField(auto_now_add=True,verbose_name='Creation time')
    post = models.ForeignKey(Post)
    class Meta:
        verbose_name = 'comment'
        verbose_name_plural = 'comment'

    def __str__(self):
        return  self.text[:4]

Step 3: Write comment routes comment.urls.py and comment.views.py

# comment.views.py
from django.shortcuts import render, get_object_or_404,redirect

# Create your views here.
from blog.models import Post
from comments.forms import CommentForm


def post_comment(request, id):
    # 1. Get blogs selected by users
    post = get_object_or_404(Post, id=id)
    # 2. If users submit comments
    if request.method == 'POST':
        print(request.POST)
        form = CommentForm(request.POST)
        # 2.1 Judging whether the form is legal
        if form.is_valid():
            comment = form.save(commit=False)
            comment.post = post
            comment.save()
        # 2.2 If it is not legal, submit error message
        else:
            return render(request, 'blog/detail.html',
                          context={
                              'errors': form.errors
                          })
    # 3. If it's not a POST request, visit the user details page
    return redirect(post.get_url())
# comment.urls
from django.conf.urls import url, include
from django.contrib import admin

from comments import views

app_name = 'comment'
urlpatterns = [
    url(r'^comment/blog/(?P<id>\d+)/$',views.post_comment,name='post_comment'),
]

Step 4: Write a comment form

# Synchronization and the Form of Database Comments
from comments.models import Comment


class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ['user','email','text']

Step 5: Modify the comments section of the HTML file

<section class="comment-area" id="comment-area">
                        <hr>
                        <h3>Comment</h3>
                        <form action="{% url 'comment:post_comment' post.id %}" method="post" class="comment-form">
                            {% csrf_token %}
                            <div class="row">
                                <div class="col-md-4">
                                    <label for="{{ form.user.id }}">{{ form.user.label }}</label>
                                    {{ form.user }}
                                </div>
                                <div class="col-md-4">
                                    <label for="{{ form.email.id }}">{{ form.email.label }}</label>
                                    {{ form.email }}
                                </div>
                                <div class="col-md-12">
                                    <label for="{{ form.text.id }}">{{ form.text.label }}</label>
                                    {{ form.text }}
                                    <button type="submit" class="comment-btn">Publish</button>
                                </div>
                            </div>    <!-- row -->
                        </form>
                        <div class="comment-list-panel">
                            <h3>Comments list, total <span>{{ comments.count }}</span> Article comment</h3>
                            <ul class="comment-list list-unstyled">
                                {% for comment in comments %}
                                    <li class="comment-item">
                                        <span class="nickname">{{ comment.user }}</span>
                                        <time class="submit-date"
                                              datetime="{{ comment.create_time }}">{{ comment.create_time }}</time>
                                        <div class="text">
                                            {{ comment.text }}
                                        </div>
                                    </li>
                                {% endfor %}

                            </ul>
                        </div>
                    </section>


Custom label

The functions of label search, date search and classification search are realized.

Step 1: Customize Tags

  1. Preparing (necessary) work:
Create a package called templatetags (required and immutable package name) under an app. Suppose we create a template tags package under app named blog and create a file named blog_tags under that package.
 Ensure that the INSTALLD_APPS in the settings file must contain the app
 Modify the time display section of set.py

# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

#If USE_TZ=True is configured in setting s, then UTC time (naive time) is output.
# If USE_TZ=False is configured in setting, the output time is exactly the same as datetime.datetime.now().
# USE_TZ = True
USE_TZ = False
2. Next, write the following lines in the blog_tags file

from django import template

register = template.Library()
 3. Use {% load%} tags in templates to load custom tags or decorators
from django import template
from django.db.models import Count

from blog.models import Post, Category, Tag

register = template.Library()

@register.simple_tag
def get_recent_posts(num=3):
    return Post.objects.all().order_by('-create_time')[:num]


@register.simple_tag
def archives():

    return Post.objects.dates(field_name='create_time',
                              kind='month',
                              order='DESC')

@register.simple_tag
def get_category():
    return Category.objects.annotate(num_posts=Count('post')).filter(num_posts__gt=0)


@register.simple_tag
def get_tags():
    # return Tag.objects.all()
    return Tag.objects.annotate(num_posts = Count('post'))

Step 2: Write the routing and view functions for label lookup

Route

#blog.urls.py
from django.conf.urls import url

from django.contrib import admin

from blog import views

app_name = 'blog'
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'blog/(?P<id>\d+)/$', views.detail, name='detail'),
    url(r'^archive/(?P<year>\d{4})/(?P<month>\d{1,2})/', views.archive, name='archive'),
    url(r'^category/(?P<id>\d+)/', views.category, name='category'),
    url(r'^tag/(?P<id>\d+)/', views.tag, name='tag'),
    url(r'^search', views.search, name='search')
]

View function

from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404

# Create your views here.
from markdown import markdown

from blog.models import Post, Tag
from comments.forms import CommentForm


def index(request):
    # return HttpResponse('ok index!')
    posts = Post.objects.all()
    return render(request,'blog/index.html',context={
        'posts':posts
    })
def detail(request,id):
    # return HttpResponse('ok,%s detail' %(id))
    post = Post.objects.get(id=id)
    post.add_views()
    form = CommentForm()
    comments = post.comment_set.all()
    post.body = markdown(post.body,
                         extensions=['markdown.extensions.extra',
                                     'markdown.extensions.codehilite',
                                     'markdown.extensions.toc', ],
                         output_format='html')
    return render(request,'blog/detail.html',context={
        'post':post,
        'comments':comments,
        'form':form,
    })
def archive(request,year,month):
    posts = Post.objects.filter(
        create_time__year=year,
        create_time__month=month
    ).order_by('-create_time')

    return  render(request,'blog/index.html',context={
        'posts':posts
    })


def category(request,id):
    posts = Post.objects.filter(category_id=id)
    return render(request,'blog/index.html',
                  context={
                      'posts':posts

                  })


def tag(request,id):
    tag = get_object_or_404(Tag,id=id)
    posts = Post.objects.filter(tags=tag).order_by('-create_time')
    return render(
        request, 'blog/index.html',
        context={
            'posts': posts

        }


    )


def search(request):
    query = request.GET.get('query',None)
    posts = Post.objects.filter(
        Q(title__icontains=query) |
        Q(body__icontains=query)
    )

    if not posts:
        return render(request,'blog/index.html',
                      context={
                          'posts':posts,
                          'message':'No relevant information was found.'
                      }
                      )
    else:
        return render(request, 'blog/index.html',
                      context={
                          'posts': posts

                      }
                      )

Step 3: Modify the Html file to intercept only part of the code

The structure (directory) of the blog should be displayed on the details page of the blog, and the code to display the directory should be added.
Modifying View Functions

def detail(request,id):
    # return HttpResponse('ok,%s detail' %(id))
    post = Post.objects.get(id=id)
    post.add_views()
    form = CommentForm()
    comments = post.comment_set.all()
    # post.body = markdown(post.body,
    #                      extensions=['markdown.extensions.extra',
    #                                  'markdown.extensions.codehilite',
    #                                  'markdown.extensions.toc', ],
    #                      output_format='html')
    md = Markdown(
        extensions=['markdown.extensions.extra',
                    'markdown.extensions.codehilite',
                    'markdown.extensions.toc', ],
        output_format='html'
    )
    # Convert markdown to serialized XHTML or HTML.
    post.body = md.convert(post.body)
    post.toc = md.toc
    return render(request,'blog/detail.html',context={
        'post':post,
        'comments':comments,
        'form':form,

    })

Right navigation bar

{#     Base template       #}

   <aside class="col-md-4">
                {% block toc %}

                {% endblock %}
                <div class="widget widget-recent-posts">
                    <h3 class="widget-title">Latest articles</h3>
                    <ul>
                        {% get_recent_posts as recent_posts %}
                        {% for post in recent_posts %}
                            <li>
                                <a href="{{ post.get_url }}">{{ post.title }}</a>
                            </li>
                        {% endfor %}
                    </ul>
                </div>
                <div class="widget widget-archives">
                    <h3 class="widget-title">File</h3>

                    <ul>
                        {% archives as dates %}
                        {% for date in  dates %}
                            <li>
                                <a href="{% url 'blog:archive' date.year date.month %}">{{ date.year }}year {{ date.month }}month</a>
                            </li>
                        {% endfor %}


                    </ul>
                </div>

                <div class="widget widget-category">
                    <h3 class="widget-title">classification</h3>

                    <ul>
                        {% get_category as categories %}
                        {% for category in categories %}

                            <li>
                                <a href="{% url 'blog:category' category.id %}">{{ category.name }}<span
                                        class="post-count">({{ category.num_posts }})</span></a>
                            </li>
                        {% endfor %}
                    </ul>
                </div>

                <div class="widget widget-tag-cloud">
                    <h3 class="widget-title">Tag cloud</h3>
                    <ul>
                        {% get_tags as tags %}
                        {% for tag in  tags %}
                            <li>
                                <a href="{% url 'blog:tag' tag.id %}">{{ tag.name }}</a>
                            </li>
                        {% endfor %}
                    </ul>
                </div>

Details page add blog directory

{# blog/detail.html #}
{% block toc %}
    <div><h3 class="widget-title">Article directory</h3>
        {{ post.toc | safe }}
    </div>
{% endblock %}
Search by category

Search by label

Search by time

Display blog directories

paging

Django provides a new class to help you manage paging data, which is stored in django/core/paginator.py. It can receive lists, tuples, or other iterative objects.

def index(request):
    all_posts = Post.objects.count()
    if all_posts % PER_PAGE != 0:
        page_nums = all_posts // PER_PAGE + 1
    else:
        page_nums = all_posts // PER_PAGE
    paginator = Paginator(Post.objects.all(),PER_PAGE)
    if  request.GET.get('page'):
        page = request.GET.get('page')
    else:
        page = 1
    try:
        posts = paginator.page(page)
    except (PageNotAnInteger,EmptyPage):
        posts = paginator.page(1)

        posts.has_previous()
        posts.has_next()
        posts.previous_page_number()
        posts.next_page_number()


    return render(request, 'blog/index.html',
                  context={
        'title':'Index',
        'posts':posts,
        'pages_num':page_nums,
    })
Modify the part of the html file on the home page about paging display
  <div class="pager">
            {% if posts.has_previous %}
                <a href="?page={{ posts.previous_page_number }}">Previous page</a>
            {% else %}
                <a href="#">Last page</a>

            {% endif %}


            <span class="current">The first {{ posts.number }} page / common {{ pages_num }} page</span>

            {% if posts.has_next %}
                <a href="?page={{ posts.next_page_number }}">next page</a>

            {% else %}
                <a href="#">Next page</a>

Posted by chelerblondi on Thu, 09 May 2019 17:56:39 -0700