Django个人博客开发之高级优化表单、模型

表单自定义校验
之前的学习过程当中讲解了form表单的定义,首先,我们来回顾一下form表单的定义和使用的流程
以文章的评论为案例。
1、定义form.py文件,在form文件当中定义表单校验类
2、在视图当中调用form表单类
3、前端渲染表单类
总的看起来,学习的过程当中要注意以下几点

  1. 表单定义
    \OurBlog\Article\forms.py
#coding:utf-8
from django import forms
from ckeditor_uploader.fields import RichTextUploadingFormField

class CommentForm(forms.Form):
    """
    自定义form表单,完成评论表单
    """
    content = RichTextUploadingFormField(label = "评论内容") #创建一个文本标签元素

from Article.models import Comment
class CommentForm_about_model(forms.ModelForm):
    """
    按照数据库模型进行表单的定义
    """
    class Meta:
        model = Comment #创建表单对应的数据模型的类
        fields = ["content"]  #要创建的字段
        labels = {
            "content": "评论内容" #设置content字段的label标签

        }
        # fields 要展示的字段,接收的是一个列表,如果不写默认是models的所有字段(__all__)
        # exclude 不要展示的字段,接收的是一个列表,排除的字段,默认没有
        # widgets 是一个模型字段的名称对应的样式的字典
        # labels 是一个模型字段的名称对应的标签的字典
        # help_texts 是一个模型字段的名称对应的帮助文档的字典
        # error_messages是一个模型字段的名称对应的错误提示的字典,这个将在后面学习开发CMDB的时候用户注册用的比较频繁
  1. 在视图当中调用form表单类
    在视图文件导入表单类,并且实例化
    \OurBlog\Article\views.py
from Article.forms import CommentForm_about_model
def Article(request):
    form = CommentForm_about_model()
    return render(request, "article/aboutMe.html",{"form":form})

在前端调用和渲染,注意,我们用的是ckeditor插件,所以需要插件的样式,我们需要在{% block style %}模块进行导入我们的js文件

<!--......-->
{% block style %}
<link href="/static/article/css/main.css" rel="stylesheet">
<script src = "/static/article/js/jquery.js"></script>
<script src = "/static/ckeditor/ckeditor-init.js"></script>
<script src = "/static/ckeditor/ckeditor/ckeditor.js"></script>
{% endblock %}
<!--......-->
        <div>
            {{ form }}
        </div>
        <!--......-->

效果如下:
在这里插入图片描述
上述的功能足够90%的需求使用,但是评论的内容限制,(不允许提交html代码等),这些完全符合当前业务需求的点是不好设置的,那么就需要学习如何自定义校验了。
自定义校验是在form表单里面通过"clean_字段名称"开头的类来进行的
在form表单当中,我们进行数据校验需要三步:
1、 将我们收到的数据传入表单
2、 进行校验 is_valid
3、 获取校验之后的数据 clean_data

首先views进行表单数据校验

from Article.forms import CommentForm_about_model
def Article(request):
    form = CommentForm_about_model()
    if request.method == "POST" and request.POST:
        data = CommentForm_about_model(request.POST)
        if data.is_valid(): #校验数据
            #……

然后进行自定义校验

def clean_content(self):
    """
    form表单自定义校验的函数名称必须是clean_加上字段名称
    校验content,函数名称就叫做clean_content
    """
    data = self.cleaned_data.get("content") #获取提交的值
    if "while" in data: #判断条件
        raise forms.ValidationError("don't speek while") #这个错误类型是form表单类定义好的,这里引发的错误,会放到errors当中
    else:
        return data #如果正常,我们需要返回数据

在这里插入图片描述
那么大家可以想一想我们是否可以重写或者重写调用Django父类当中的方法?
Django数据库模型对象 queryset
queryset是查询集,就是传到服务器上的url里面的内容。
Objects就是Django定义好的一个queryset,queryset定义在manager方法当中
Objects常用的方法
All
Filter
Order_by
Limit
Add
Create
Update
delete
对于queryset对象,需要掌握以下几点:

  1. Django会对查询返回的结果集QuerySet进行缓存,这里是为了提高查询效率。也就是说,在你创建一个QuerySet对象的时候,Django并不会立即向数据库发出查询命令,只有在你需要用到这个QuerySet的时候才会去数据库查询。
  2. Objects是django实现的mvc框架中的数据层(model)m,django中的模型类都有一个objects对象,它是一个django中定义的QuerySet类型的对象,它包含了模型对象的实例。简单的说,objects是单个对象,queryset是多个对象。
  3. QuerySet 可以被构造,过滤,切片,做为参数传递,这些行为都不会对数据库进行操作。只有查询的时候才真正的操作数据库。
    1、循环(Iteration):QuerySet 是可迭代的,在你遍历对象时就会执行数据库操作。
    2、切片(Slicing): QuerySet 是可以用 Python 的数组切片语法完成切片。一般来说对一个未查询的 QuerySet 切片就返回另一个未查询的 QuerySet (新 QuerySet 不会被执行)。
    切片的step操作会导致结果集进行数据库查询, 也就是我们常说的步长
    Article.objects.all()[1:10] 不查询
    Article.objects.all()[1:10:2] 查询
    3、repr(). 调用 QuerySet 的 repr() 方法时,查询就会被运行。
    4、 len() .调用 QuerySet 的 len() 方法,查询就会被运行
    Django 还提供了 count() 方法,他使用了 SQL 的 SELECT COUNT(*) 机制

Django自定义queryset
在上面的案例当中,我们研究QuerySet,但实际工作当中,我们需求的查询和orm查询往往有差距,所以我们需要自定义

  1. 表级的自定义查询
    \OurBlog\Article\models.py
class ArticleManager(models.Manager):
    """
    返回文章的总数
    定义一个查询集
    """
    def article_conunt(self,keyword = ""): #查询集的名称
        return self.filter(title__icontains = keyword).count() #__icontains进行数据模糊查询 类似like

class Article(models.Model):
    """
    一篇文章可以有一个作者,一个作者可以有一篇文章,
    一篇文章有多条评论
    一个文章有多个分类
    一个分类有多篇文章
    """
    #......  这里省略了已经写好的代码
    #安装查询集
    objects = ArticleManager() #安装查询集


    def __str__(self):
        return "文章:%s" % self.title

视图调用
\OurBlog\Article\views.py

def example(request):
    all_data = Article.objects.all()
    count = Article.objects.article_count("while没有写例子") #调用自定义的查询方法
    return render(request,"article/example_model.html",locals())

前端调用
\OurBlog\Article\templates\article\example_model.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Model Example</title>
</head>
<body>
    {% for article in all_data %}
        <p>
            {{ article.title }}
        </p>
    {% endfor %}
    <p>
        {{ count }}
    </p>
</body>
</html>

  1. 行级的自定义查询
    定义自定义查询类:
class Article(models.Model):
    """
    一篇文章可以有一个作者,一个作者可以以有一篇文章,
    一篇文章有多条评论
    一个文章有多个分类
    一个分类有多篇文章
    """
    title = models.CharField(max_length = 32,verbose_name = "文章标题")
    time = models.DateField(verbose_name = "文章发表日期")
    description = RichTextUploadingField(verbose_name = "文章描述")
    content = RichTextUploadingField(verbose_name = "文章内容")

    picture = models.ImageField(verbose_name = "文章图片",upload_to = "images/article")
    author = models.ForeignKey(Author)
    classify = models.ManyToManyField(Classify)
    commant = models.ForeignKey(to=Comment, verbose_name="文章评论", blank = True,null = True) #文章可以有评论,也可以没有,""代表blank,None代表null

    def valid_title(self):
        """
        定义查询集
        """
        title = self.title #获取title字段的内容
        if "while" in title: #进行判断返回指定结果
            return "这个文章牛"
        else:
            return "一般般吧"

前端调用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Model Example</title>
</head>
<body>
    {% for article in all_data %}
        <p>
            {{ article.title }} <!--这里显示文章的title-->
            {{ article.valid_title }} <!--这里显示我们自定义查询集返回的结果-->
        </p>

    {% endfor %}
    <p>
    <!--这里返回查询文章的总数-->
        {{ count }} 
    </p>
</body>
</html>

效果如下:
在这里插入图片描述
如果你的文章中是不同的title,查询出来的结果是不一样的,就不像我这个这么统一了,我这个是为了偷懒,全是复制粘贴添加的一样的数据,快去试试自己的Blog

猜你喜欢

转载自blog.csdn.net/ALLENsakaru/article/details/84205130
今日推荐