Django --- 开发博客系统

blog开发流程

1.分析博客页面:

1)完成网站的模块划分

2)从模板页面中抽象出父模板,完成模板页面继承

3)分析模块当中的数据模型,确定模型类当中的字段

2.分析博客实现的功能:

1)用户模块的注册登录,增删改查,模型类的继承,form验证,

2)一篇文章有一个作者,多个标签,一种类型,添加评论,浏览量,文章点赞

3)文章排行榜,归档

4)标签云

5)文章分页, 文章详情页

6)添加删除文章

首先调用django内部用户模块,相关字段都封装好,可以扩展补充


from django.db import models
from datetime import datetime
from django.contrib.auth.models import AbstractUser
 
 
# Create your models here.
 
 
class UserProfile(AbstractUser):
    """
    用户模块扩展,调用django内部模型类继承
    """
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')
    nick_name = models.CharField(max_length=10, verbose_name='昵称', blank=True, null=True)
 
    def __str__(self):
        return self.username
 
    class Meta:
        verbose_name = '用户信息'
        verbose_name_plural = verbose_name

配置url

from django.conf.urls import url
from .views import user_register, user_login, user_logout
 
urlpatterns = [
    url(r'^user_register/$', user_register, name='user_register'),
    url(r'^user_login/$', user_login, name='user_login'),
    url(r'^user_logout/$', user_logout, name='user_logout'),
]

用户模块视图

from django.shortcuts import render, redirect
from .models import UserProfile
from django.core.urlresolvers import reverse
from django.contrib.auth import authenticate, login, logout
from .forms import UserRegisterForm, UserLoginForm
 
 
def user_register(request):
    """
    用户注册模块
    添加了form表单验证
    """
    if request.method == 'GET':
        return render(request, 'reg.html')
    else:
        # 实例form类,用来验证用户提交的数据
        user_register_form = UserRegisterForm(request.POST)
        if user_register_form.is_valid():  # 返回值为True或False
            username = user_register_form.cleaned_data['username']
            password = user_register_form.cleaned_data['password']
            password1 = user_register_form.cleaned_data['password1']
 
            user = UserProfile.objects.filter(username=username)
            if user:
                return render(request, 'reg.html', {
                    'mag': '账号已存在'
                })
            else:
                if password1 == password:
                    a = UserProfile()
                    a.password = password
                    a.username = username
                    # 内部函数自动加密功能
                    a.set_password(password)
                    a.save()
                    return redirect(reverse('users:user_login'))
                else:
                    return render(request, 'reg.html', {
                        'msg': '密码不一致'
                    })
        else:
            return render(request, 'reg.html', {
                'user_register_form': user_register_form
            })
 
 
def user_login(request):
    """
    用户登录模块,调用django内部函数login,封装好了session功能
 
    """
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        user_login_form = UserLoginForm(request.POST)
        if user_login_form.is_valid():
            username = user_login_form.cleaned_data['username']
            password = user_login_form.cleaned_data['password']
 
            user = authenticate(username=username, password=password)
            if user:
                login(request, user)
                return redirect(reverse('index'))
 
            else:
                return render(request, 'login.html', {
                    'msg': '用户名或者密码错误!',
                    'user_login_form': user_login_form
                })
        else:
            pass
 
 
def user_logout(request):
    """
    用户退出模块, 调用django内部函数logout
 
    """
    logout(request)
    return render(request, 'index.html')

用户模块增加forms.py文件用来设置form验证

from django import forms
 
 
class UserRegisterForm(forms.Form):
    """form表单注册验证"""
    username = forms.CharField(max_length=20, min_length=6, required=True, error_messages={'invalid': '长度最大20,最小6'},)
    email = forms.EmailField(error_messages={
        # 自定义验证字段
        'invalid': '格式不对,最大长度20,最小6'
    }, required=False)
    url = forms.URLField(error_messages={
        'invalid': '格式不对,最大长度20,最小6'
    }, required=False)
    password = forms.CharField(max_length=20, min_length=6, required=True)
    password1 = forms.CharField(max_length=20, min_length=6, required=True)

页面的代码完善,登录前显示注册和登录功能,登录后只显示姓名和退出功能。

抽象出父模板,设置子模板继承,避免每个页面代码的重复

子模板代码的变化单独一个页面

 

已经完成用户模块和模板的继承,此次咱们来完成文章模块部分功能

开始部分

1.添加应用

2.更改settings配置

3.第三部配置文章模块url

重点开始

1.在models.py里添加需要的模型类

from django.db import models
from datetime import datetime
from users.models import UserProfile
 
 
# Create your models here.
 
class Category(models.Model):
    """文章类型"""
    name = models.CharField(max_length=10, verbose_name='文章类型')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')
 
    def __str__(self):
        return self.name
 
    class Meta:
        verbose_name = '类型信息'
        verbose_name_plural = verbose_name
 
 
class ArticleInfo(models.Model):
    """文章信息,与用户一对多关系,与文章类型一对一关系"""
    title = models.CharField(max_length=20, verbose_name='文章标题')
    author = models.ForeignKey(UserProfile, verbose_name='文章作者')
    category = models.ForeignKey(Category, verbose_name='文章类型')
    desc = models.TextField(verbose_name='文章描述')
    content = models.TextField(verbose_name='文章正文')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    click_num = models.IntegerField(default=0, verbose_name='浏览量')
    love_num = models.IntegerField(default=0, verbose_name='点赞量')
    image = models.ImageField(upload_to='article/%y/%m/%d', verbose_name='文章图片', max_length=200)
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')
 
    def __str__(self):
        return self.title
 
    class Meta:
        verbose_name = '文章信息'
        verbose_name_plural = verbose_name
 
 
class TagInfo(models.Model):
    """有关文章的标签,与文章多对多关系"""
    name = models.CharField(max_length=10, verbose_name='标签姓名')
    article = models.ManyToManyField(ArticleInfo, verbose_name='所属文章')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')
 
    def __str__(self):
        return self.name
 
    class Meta:
        verbose_name = '标签信息'
        verbose_name_plural = verbose_name
 
 
class CommentInfo(models.Model):
    comment_content = models.CharField(max_length=200, verbose_name='文章评论')
    comment_art = models.ForeignKey(ArticleInfo, verbose_name='所属文章')
    comment_man = models.ForeignKey(UserProfile, verbose_name='评论人')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')
 
    def __str__(self):
        return self.comment_content
 
    class Meta:
        verbose_name = '评论信息'
        verbose_name_plural = verbose_name

2.来创建一个超级后台管理

3. 要上传图片,配置媒体文件夹

总路由url添加:

settings添加:

settings应用进程添加最后一行:

上传完图片后django自动添加媒体目录

4 .在articles的admin.py里添加后台要显示的内容

from django.contrib import admin
from .models import ArticleInfo, TagInfo, Category
 
 
# Register your models here.
 
class ArticleInfoAdmin(admin.ModelAdmin):
    """文章内容"""
    list_display = ['title', 'author', 'category', 'desc', 'content', 'is_delete', 'click_num', 'love_num', 'image',
                    'add_time']
    fields = ['title', 'author', 'category', 'desc', 'content', 'is_delete', 'click_num', 'love_num', 'image',
              'add_time']
 
 
class TagInfoAdmin(admin.ModelAdmin):
    """标签内容"""
    list_display = ['name', 'add_time']
    fields = ['name', 'article', 'add_time']
    filter_horizontal = ['article']
 
 
class CategoryAdmin(admin.ModelAdmin):
    """文章类型内容"""
    list_display = ['name', 'add_time']
    fields = ['name', 'add_time']
 
 
admin.site.register(ArticleInfo, ArticleInfoAdmin)
admin.site.register(Category, CategoryAdmin)
admin.site.register(TagInfo, TagInfoAdmin)

5 . 去超帅的django后台看一看

6  . 主页实现最关键部分

from django.shortcuts import render, redirect
from .models import UserProfile
from django.core.urlresolvers import reverse
from articles.models import ArticleInfo, TagInfo
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
 
 
# Create your views here.
 
 
def index(request):
    """主页程序"""
    # 首先获取所有文章
    all_articles = ArticleInfo.objects.all()
    # 文章按照日期归档,按天排序参数就是day, 最新发表的要排在最前面
    # 所以设置order='DESC' ,默认是时间最小的排在最前面
    date_time = all_articles.datetimes('add_time', 'day', order='DESC')
    # 浏览量排行, 倒序排列加 - ,得到的是一个列表,取前六篇文章
    click_sort = all_articles.order_by('-click_name')[:6]
    # 站长推荐, 时间排序, 最新的用倒序, 同上
    pro_arts = all_articles.order_by('-add_time')[:6]
    # 获得所有标签, 呈现在页面上
    all_tags = TagInfo.objects.all()
    # 获得归档文本的时间, 从html页面传回要查看的参数
    year = request.GET.get('year', '')
    month = request.GET.get('month', '')
    day = request.GET.get('day', '')
    if year and month and day:
        # 按照日期筛选文章
        all_articles = all_articles.filter(add_time__year=year, add_time__month=month, add_time__day=day)
        all_articles_set = set(all_articles)
    # 从html页面传回tagid的参数,获得点击的标签的id值,通过tagid传参
    tagid = request.GET.get('tagid', '')
    # 此处设置目的是当点击日期和标签时,要呈现的就不是所有文章了,
    # 取标签和日期的交集, 把列表转化为集合再赋值
    if tagid:
        # 通过tagid获得tag,然后通过tag多对多关系获得所有文章
        tag = TagInfo.objects.filter(id=int(tagid))[0]
        all_articles = tag.article.all()
        all_articles_set1 = set(all_articles)
    try:
        a = list(all_articles_set & all_articles_set1)
        if a:
            all_articles = a
    except:
        pass
    # 分页器对象, 设置所有文章每页显示三篇
    pa = Paginator(all_articles, 3)
    # 从html页面传回要查看的哪一页的参数,默认值为1
    pagenum = request.GET.get('pagenum', 1)
    try:
        pages = pa.page(pagenum)
    except PageNotAnInteger:
        # 前一页最尽头就是第一页
        pages = pa.page(1)
    except EmptyPage:
        # 下一页最尽头就是最后一页, num_pages是总的页数
        pages = pa.page(pa.num_pages)
    # 所有相关参数传回HTML页面
    return render(request, 'index.html', {
        # 'all_articles': all_articles
        'pages': pages,  # 分页文章
        'click_sort': click_sort,  # 阅读量排序
        'pro_arts': pro_arts,  # 推荐排序
        'all_tags': all_tags,  # 呈现所有标签
        'tagid': tagid,
        'date_time': date_time,
        'year': year,
        'month': month,
        'day': day
    })

7. html页面相关代码

分页

 

    <ul id="pagination-flickr">
        {% if pages.has_previous %}
      <li class="previous-off">
          <a href="{% url 'index' %}?pagenum={{ pages.previous_page_number }}&tagid={{ tagid }}&year={{ year }}&month={{ month }}&day={{ day }}">«上一页</a>
      </li>
        {% endif %}
      <li class="active">{{ pages.number }}/{{ pages.paginator.num_pages }}
      </li>
        {% if pages.has_next %}
      <li class="next">
          <a href="{% url 'index' %}?pagenum={{ pages.next_page_number }}&tagid={{ tagid }}&year={{ year }}&month={{ month }}&day={{ day }}">下一页 »</a>
      </li>
        {% endif %}
     </ul>

文章归档(请求方式传参)

<h3>文章归档</h3>
            <ul>
                {% for date in date_time %}
                    <li>
                        <p><span class="tutime font-size-18">
                            <a href="{% url 'index' %}?year={{ date.year }}&month={{ date.month }}&day={{ date.day }}">{{ date.year }}年{{ date.month }}月{{ date.day }}日文章归档</a></span>
                        </p>
                    </li>
                {% endfor %}
            </ul>

标签云(请求方式传参)

 <h3>标签云</h3>
            <ul>
                {% for tag in all_tags %}
                    <li><a href="{% url 'index' %}?tagid={{ tag.id }}&pagenum={{ pages.number }}">{{ tag.name }}</a>
                    </li>
                {% endfor %}
            </ul>

文章评论详情

# 加修饰器, 没有登录用户点击后跳转制定路径 
@login_required(login_url='/users/user_login/')
def comment_add(request, art_id):
    """文章评论详情"""
    if request.user:
        print(request.user)
        if art_id:
            content = request.POST.get('comment', '')
            print(content)
            com = Comment()
            com.comment_man_id = request.user.id
            com.comment_art_id = int(art_id)
            com.comment_content = content
            com.save()
            return redirect(reverse('articles:article_detail', args=[art_id]))

点赞(ajax异步)

def love_add(request, art_id):
    """点赞设置"""
    if request.is_ajax():
        art = ArticleInfo.objects.filter(id=int(art_id))[0]
        art.love_name += 1
        art.save()
        result = {'a': 'ok'}
        return JsonResponse(result)

HTML

{% block myjs %}
    <script src="{% static 'js/jquery.min.js' %}"></script>
    <script>
        $(function () {
            $('#dian').click(function () {
                $.get("{% url 'articles:love_add' article.id %}", function(callback){
                    if (callback.a == 'ok') {
                        value = parseInt($('#zan').text());
                        value = value + 1;
                        $('#zan').text(value);
                        setTimeout(function () {
                             window.location.href = '/';
                        },5000)
                    }
                })
            })
        })
    </script>
{% endblock %}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值