1. 程式人生 > >Django個人部落格開發之高階優化表單、模型

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