一、功能需求分析
1、banner
2、推荐文章列表
3、文章标签导航
4、文章列表
5、分页
二、模型设计
根据功能分析,我们需要如下表,大量的经验和功能积累
1、表和字段分析
a 文章分类表
b 文章表
c 文章评论表
d 推荐文章表
e 轮播图表
2、模型定义
定义一个基类模型,抽取公共字段
创建时间、更新时间、逻辑删除
a 分析每个表功能、根据字段编写模型代码
三、文章标签导航功能
1.接口设计
类目 说明
请求方式 GET
url /
参数说明 无参数
2.返回结果
返回新闻页面,直接在模版渲染
#insert news tag data
INSERT INTO tb_tag(name, create_time, update_time, is_delete) values
('Python基础', now(), now(), 0),
('Python高级', now(), now(), 0),
('Python函数', now(), now(), 0),
('PythonGUI', now(), now(), 0),
('Linux教程', now(), now(), 0),
('Python框架', now(), now(), 0);
四、新闻列表功能
1、业务流程分析
a 判断前端传递标签分类ID是否为空,是否为整数,是否超过范围
b 判断前端传递当前文章页数是否为空,是否为整数,是否超过范围
2、接口设计
类目 说明
请求方式 GET
url /news/
参数说明:
参数名 类型 是否必须 描述
tag 整数 否 标签分类ID
page 整数 是 当前文章页数
3、返回结果:
json
{
"errno": "0",
"errmsg": "",
"data": {
"total_pages": 61,
"news": [
{
"digest": "在python用import或者from...import或者from...import...as...来导入相应的模块,作用和使用方法与C语言的include头文件类似。其实就是引入...",
"title": "import方法引入模块详解",
"author": "python",
"image_url": "/media/jichujiaochen.jpeg",
"tag_name": "Python基础",
"update_time": "2018年12月17日 14:48"
},
{
"digest": "如果你原来是一个php程序员,你对于php函数非常了解(PS:站长原来就是一个php程序员),但是现在由于工作或者其他原因要学习python,但是p...",
"title": "给曾经是phper的程序员推荐个学习网站",
"author": "python",
"image_url": "/media/jichujiaochen.jpeg",
"tag_name": "Python基础",
"update_time": "2018年12月17日 14:48"
}
]
}
}
mysql -u root -p -D tzpj < tb_news_20181217.sql. 导入数据库
news/modile.py代码
from django.db import modelsfrom utils.models import BaseModelclass Tag(BaseModel): """ 文章分类标签模型 """ # 字段 name = models.CharField('标签名', max_length=64, help_text='标签名') class Meta: ordering = ['-update_time', '-id'] #排序 db_table = "tb_tag" #指明数据库表名 verbose_name = '文章标签' #在admin站点中显示点名称 verbose_name_plural = verbose_name #显示点复数名称 def __str__(self): return self.nameclass News(BaseModel): """ 文章模型 """ title = models.CharField('标题', max_length=150, help_text='标题') digest = models.CharField('摘要', max_length=200, help_text='摘要') content = models.TextField('内容', help_text='内容') clicks = models.IntegerField('点击量', default=0, help_text='点击量') image_url = models.URLField('图片url', default='', help_text='图片url') tag = models.ForeignKey('Tag', on_delete=models.SET_NULL, null=True) author = models.ForeignKey('user.User', on_delete=models.SET_NULL, null=True) class Meta: ordering = ['-update_time', '-id'] #排序 db_table = "tb_news" #指明数据库表名 verbose_name = '新闻' #在admin站点中显示点名称 verbose_name_plural = verbose_name #显示点复数名称 def __str__(self): return self.titleclass Comments(BaseModel): """ 评论模型 """ content = models.TextField('内容', help_text='内容') author = models.ForeignKey('user.User', on_delete=models.SET_NULL, null=True) news = models.ForeignKey('News', on_delete=models.CASCADE) class Meta: ordering = ['-update_time', '-id'] #排序 db_table = "tb_comments" #指明数据库表名 verbose_name = '评论' #在admin站点中显示点名称 verbose_name_plural = verbose_name #显示点复数名称 def __str__(self): return '<评论{}>'.format(self.id)class HotNews(BaseModel): """ 推荐文章模型 """ news = models.OneToOneField('News', on_delete=models.CASCADE) priority = models.IntegerField('优先级', help_text='优先级') class Meta: ordering = ['-update_time', '-id'] #排序 db_table = "tb_hotnews" #指明数据库表名 verbose_name = '热门文章' #在admin站点中显示点名称 verbose_name_plural = verbose_name #显示点复数名称 def __str__(self): return '<热门文章{}>'.format(self.id)class Banner(BaseModel): """ 轮播图 """ image_url = models.URLField('轮播图', help_text='轮播图url') priority = models.IntegerField('优先级', help_text='优先级') news = models.OneToOneField('News', on_delete=models.CASCADE) class Meta: ordering = ['priority', '-update_time', '-id'] #排序 db_table = "tb_banner" #指明数据库表名 verbose_name = '热门文章' #在admin站点中显示点名称 verbose_name_plural = verbose_name #显示点复数名称 def __str__(self): return '<轮播图{}>'.format(self.id) news/views.py代码
import loggingfrom django.shortcuts import renderfrom django.views import Viewfrom django.db.models import Ffrom django.core.paginator import Paginatorfrom .models import Tag, Newsfrom . import constantsfrom utils.res_code import json_responselogger = logging.getLogger('django')def index(request): """ 新闻首页视图 only默认带ID url: / :param request: :return: """ # 新闻标签 tags = Tag.objects.only('name').filter(is_delete=False) return render(request, 'news/index.html', context={ 'tags': tags })class NewsListView(View): """ 新闻列表视图 """ def get(self, request): # 1,获取参数 try: tag_id = int(request.GET.get('tag', 0)) except Exception as e: logger.error('标签错误, \n{}'.format(e)) tag_id = 0 try: tag_id = int(request.GET.get('tag', 0)) except Exception as e: logger.error('标签错误, \n{}'.format(e)) tag_id = 1 # 2,获取查询集 values返回字典 news_queryset = News.objects.values('id', 'title', 'digest','image_url', 'update_time','tag__name', 'author__username').annotate(tag_name=F('tag_name'),author=F('author__username')) #过滤 # if tag_id: # news = news_queryset.filter(is_dalete=False, tag_id=tag_id) # else: # news = news_queryset.filter(is_dalete=False) news = news_queryset.filter(is_dalete=False, tag_id=tag_id) or news_queryset.filter(is_dalete=False) # 3,分页 paginator = Paginator(news, constants.PER_PAGE_NEWS_COUNT) #获取当前页数据 get_page可以容错 news_info = paginator.get_page(page) # 4,返回数据 data = { 'total_pages': paginator.num_pages, 'news': list(news_info) } return json_response(data=data)序列化:把特定的内存对象转化成可以存储的字符串utils/res_code.py代码
import datetimefrom django.http import JsonResponsefrom django.core.serializers.json import DjangoJSONEncoder
class MyJSONEncoder(DjangoJSONEncoder):
def default(self, o): if isinstance(o, datetime.datetime): return o.astimezone().strftime('%Y-%m-%d %H:%M:%S') #转换为本地时间 else: return super().default(o)
def json_response(errno=Code.OK, errmsg='', data=None, kwargs=None): json_dict = { 'errno': errno, 'errmsg': errmsg, 'data': data } if kwargs and isinstance(kwargs, dict): json_dict.update(kwargs) return JsonResponse(json_dict, encoder=MyJSONEncoder)
五、推荐新闻 1,接口设计
类目 说明
请求方式 GET
url /
参数说明 无参数
2,返回结果
返回新闻页面,直接在模版渲染
news/vies.py代码
def index(request): """ 新闻首页视图 url: / """ # 新闻标签 tags = Tag.objects.only('name').filter(is_delete=False) # 热门新闻 objects.select_related('news')一次性从数据库多拿数据
hot_news = HotNews.objects.select_related('news').only('news__title', 'news__image_url', 'news_id').filter(is_delete=False).order_by('priority', '-news__clicks')[:constants.SHOW_HOTNEWS_COUNT] return render(request, 'news/index.html', context={ 'tags': tags, 'hot_news': hot_news })
六、轮播图功能 接口设计 1,接口说明: 类目 说明 请求方法 GET url定义 /news/banners/ 参数格式 无参数 2,返回结果: # json { 'erron': '0', 'errmsg': 'ok' 'data': { 'banners':[ { 'image_url':'/media/jichujiaochen.jpeg', 'news_id': 221, 'news_title': 'python算法快速排序' }, {
'image_url':'/media/python_advanced.jpeg', 'news_id': 707, 'news_title': 'python序列与映射的解包操作'
} ] } }