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页面相关代码
分页
文章归档(请求方式传参)
文章归档
{% for date in date_time %}
-
{% endfor %}
标签云(请求方式传参)
标签云
{% for tag in all_tags %}
- {{ tag.name }}
{% endfor %}
文章评论详情
# 加修饰器, 没有登录用户点击后跳转制定路径
@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 %}
{% endblock %}