zoukankan      html  css  js  c++  java
  • 2018.7.10 个人博客文章=>利用ORM创建分类和ORM的内置函数

    昨天的注册收尾工作

    其实就差了和MySql联系起来的部分,这部分很简单,首先要做的就是保存用户通过from传送过来的头像文件:

    """
    保存头像文件
    """
    file = request.FILES.get('avatar')
    file_path = os.path.join('static/img', file.name)
    with open(file_path, 'wb') as f:
    	for chunk in file.chunks():
    		f.write(chunk)  # 写文件
    

    然后就是保存用户输入的值到对应数据库的表,利用ORM可以很简单的写出来:

    v = request.POST
    result = models.UserInfo.objects.create(username=v.get('username'),password=v.get('password'),email=v.get('email'),nickname=v.get('username'),avatar='/' + file_path, )

    进入对应博客所需的路由配置问题

    我们访问一个博客主页的时候是不需要登陆信息的只要访问类似http://127.0.0.1:8000/blog/***.html之类的网址就可以进入对应博客获取需要的信息,所以在设置路由的时候我额外加了一个参数,用来将博主的名字来作为博客网址的一部分:

    re_path('^blog/(w+).html$', views.blog)
    

    在处理函数中多加一个name参数,用来接收(w+)处的参数:

    def blog(request, name):
        return render(request, 'blog.html', {'name': name})
    

    这样路由的文件就简单解决了,后续可能会优化一些。

    个人主页博客文章的类型分类(一对一)

    在写博客主页之前,我想先想一想页面中展示博客文章分类的部分。

    首先是获取对应的博客对象,这个很好获取,利用上面的name参数可以很简单的做到:

    blog = models.Blog.objects.filter(site=name).first()

    首先想到的就是利用当前博客的分类来反向查找对应的所有文章,计算出查找到的文章数就可以得到对应分类下的文章数了:

    # 当前博客所有分类
    cate_list = models.Category.objects.filter(blog=blog)
    for item in cate_list:	# 遍历每一个分类项
        c = item.article_set.all().count()	# 利用分类项反向查找到对应的所有文章并计算出文章数返回
        print(item,c)
    

    但是这种方法有一个不好的地方,那就是需要频繁的去数据库查询,这样后期会大大拖慢服务器的反应速度。

    我想到了利用Group By来一次性查询所有需要的值,SQL语句如下:

    select category_id, count(nid) as c from article where blog_id = *** group by category_id
    

    但是用ORM来做的话需要values和annotate函数配合使用来达到分组查询的目的:

    category_list = models.Article.objects.filter(blog=blog).values('category_id','category__title',).annotate(c=Count('nid'))  # 这里反向查找了分类名,为了更方便的显示在页面上
    

    个人主页博客文章的标签分类(多对多)

     差不多的道理:

    models.Article2Tag.objects.filter(tag__blog=blog).values('tag_id','tag__title').annotate(c=Count('id'))

    个人主页博客文章的时间分类

    时间分类需要注意的地方其实就是时间格式的转换,可以利用MySQL 中的DATE_FORMAT() 函数具体的可以参照我的小知识总结,SQL语句如下:

    select date_format(create_time,'%Y-%m'),count(nid) as c from article where blog_id=1 group by date_format(create_time,'%Y-%m')
    

    但是在ORM中怎么做呢,可以利用extra函数来为表增加额外的一个字段,以做到分组查询的目的:

    date_list = models.Article.objects.filter(blog=blog).extra(select={'c': "date_format(create_time,'%%Y-%%m')"}).values('c').annotate(ct=Count('nid'))
    

    Django ORM内置函数和函数的自定义

    ORM内置函数主要有基础函数和时间函数两种:

    # 基础函数
    Cast, Coalesce, Concat, ConcatPair, Greatest, Least, Length, Lower, Now, Substr, Upper,
    # 时间函数
    Extract, ExtractDay, ExtractHour, ExtractMinute, ExtractMonth,ExtractSecond, ExtractWeekDay, ExtractYear, Trunc, TruncDate, TruncDay,TruncHour, TruncMinute, TruncMonth, TruncSecond, TruncYear,
    

    通过annotate函数来调用这些基础函数例如:

    from django.db.models import FloatField
    from django.db.models import Value
    v = models.Article.objects.annotate(c=functions.Cast('nid', FloatField()))
    v = models.Article.objects.annotate(c=functions.Coalesce('title','summary'))
    v = models.Article.objects.annotate(c=functions.Concat('nid','title','summary'))
    v = models.Article.objects.annotate(c=functions.Concat('nid','title','summary',Value('666')))
    v = models.Article.objects.annotate(c=functions.Greatest('nid','num'))
    v = models.Article.objects.annotate(c=functions.Length('title'))
    v = models.Article.objects.annotate(c=functions.Substr('title',1,1))
    

    所有函数的功能列举如下(以下内容参照了这个大神的博客):

    # ########### 基础函数 ###########
    
        # 1. Concat,用于做类型转换
        # v = models.UserInfo.objects.annotate(c=Cast('pwd', FloatField()))
    
        # 2. Coalesce,从前向后,查询第一个不为空的值
        # v = models.UserInfo.objects.annotate(c=Coalesce('name', 'pwd'))
        # v = models.UserInfo.objects.annotate(c=Coalesce(Value('666'),'name', 'pwd'))
    
        # 3. Concat,拼接
        # models.UserInfo.objects.update(name=Concat('name', 'pwd'))
        # models.UserInfo.objects.update(name=Concat('name', Value('666')))
        # models.UserInfo.objects.update(name=Concat('name', Value('666'),Value('999')))
    
        # 4.ConcatPair,拼接(仅两个参数)
        # v = models.UserInfo.objects.annotate(c=ConcatPair('name', 'pwd'))
        # v = models.UserInfo.objects.annotate(c=ConcatPair('name', Value('666')))
    
        # 5.Greatest,获取比较大的值;least 获取比较小的值;
        # v = models.UserInfo.objects.annotate(c=Greatest('id', 'pwd',output_field=FloatField()))
    
        # 6.Length,获取长度
        # v = models.UserInfo.objects.annotate(c=Length('name'))
    
        # 7. Lower,Upper,变大小写
        # v = models.UserInfo.objects.annotate(c=Lower('name'))
        # v = models.UserInfo.objects.annotate(c=Upper('name'))
    
        # 8. Now,获取当前时间
        # v = models.UserInfo.objects.annotate(c=Now())
    
        # 9. substr,子序列
        # v = models.UserInfo.objects.annotate(c=Substr('name',1,2))
    
    # ########### 时间类函数 ########### # 1. 时间截取,不保留其他:Extract, ExtractDay, ExtractHour, ExtractMinute, ExtractMonth,ExtractSecond, ExtractWeekDay, ExtractYear, # v = models.UserInfo.objects.annotate(c=functions.ExtractYear('ctime')) # v = models.UserInfo.objects.annotate(c=functions.ExtractMonth('ctime')) # v = models.UserInfo.objects.annotate(c=functions.ExtractDay('ctime')) # # v = models.UserInfo.objects.annotate(c=functions.Extract('ctime', 'year')) # v = models.UserInfo.objects.annotate(c=functions.Extract('ctime', 'month')) # v = models.UserInfo.objects.annotate(c=functions.Extract('ctime', 'year_month')) """ MICROSECOND SECOND MINUTE HOUR DAY WEEK MONTH QUARTER YEAR SECOND_MICROSECOND MINUTE_MICROSECOND MINUTE_SECOND HOUR_MICROSECOND HOUR_SECOND HOUR_MINUTE DAY_MICROSECOND DAY_SECOND DAY_MINUTE DAY_HOUR YEAR_MONTH """ # 2. 时间截图,保留其他:Trunc, TruncDate, TruncDay,TruncHour, TruncMinute, TruncMonth, TruncSecond, TruncYear # v = models.UserInfo.objects.annotate(c=functions.TruncHour('ctime')) # v = models.UserInfo.objects.annotate(c=functions.TruncDate('ctime')) # v = models.UserInfo.objects.annotate(c=functions.Trunc('ctime','year'))

    ORM自定义函数的写法:

    from django.db.models.functions.base import Func
        class CustomeFunc(Func):
            function = 'DATE_FORMAT'
            template = '%(function)s(%(expressions)s,%(format)s)'
    
            def __init__(self, expression, **extra):
                expressions = [expression]
                super(CustomeFunc, self).__init__(*expressions, **extra)
    
        v = models.UserInfo.objects.annotate(c=CustomeFunc('ctime',format="'%%Y-%%m'"))
    

      

  • 相关阅读:
    [转载] c++ cout 格式化输出浮点数、整数及格方法
    [转]
    _jobdu_1001
    关于网页授权的两种scope的区别说明
    CentOS编译安装Python3
    Apache+OpenSSL实现证书服务器提供HTTPS
    Linux下安装Tomcat服务器和部署Web应用
    记一次肉机事件--yam
    通过关闭 UseDNS和GSSAPIAuthentication选项加速 SSH登录
    Git 系列之tag的用法---为你的代码标记版本号
  • 原文地址:https://www.cnblogs.com/yu-jie/p/9289908.html
Copyright © 2011-2022 走看看