django進階版2

批量插入數據

在一個表中插入不少條的數據,你應該很快就能想到用create,然而事實是這樣嗎?前端

def index(request):
    book_list=[]
    for i in range(1000):
        #models.Book.objects.create(title=f'第{i}本書')
        book=models.Book(title=f'第{i}本書')
        book_list.append(book)
    models.Book.objects.bulk_create(book_list)
    book_query=models.Book.objects.all()
    return render(request,'index.html',locals())
<body>
    {%for i in book_query%}
    <p>
        {{i.title}}
    </p>
    {%endfor%}
</body>

就像上面註釋的代碼是否是你的想法呢,想法能夠,但實現着實困難了點,一旦數據多了,就會形成數據庫的龐大壓力,而使用bulk_create一步到位,用哪一種方法就顯而易見了-。-python

自定義分頁器

這個東西聽上去是否是有點d,凡是自定義的,總感受是比通常的高端一點,反正我是這麼認爲的|^ _ ^|數據庫

這裏只提供思路啊,代碼就由你去實現了,fighting!django

首先咱們是否是須要定義一些變量來存總頁數,數據總量,每頁數據量等等。。。後端

current_page=request.GET.get('page',1)  #獲取用戶想要訪問的頁碼數,若是沒有則默認第一頁
current_page=int(current_page)  #轉成整形
per_page_num=10     #定義一下每頁須要多少條數據,這裏定義成10條哦
start_page=(current_page-1)*per_page_num    #每一頁的初始位置
end_page=current_page*per_page_num  #每一頁的末尾位置
book_query=models.Book.objects.all()
all_count=book_query.count()    #統計數據總量
#這裏須要用到一個divmod方法,來求出須要的總頁數
page_num,more=divmod(all_count,per_page_num)
if more:
    page_num+=1
page_html='' #這是待會要傳回前端頁面的標籤
x=current_page #先保存一下,以避免待會數據發生變化
if current<6:   #小於第6頁,就不會再往前滑動
    current=6
for i in range(current_page-5,current_page+6):  #一共展現11頁
    if x=i:
        page_html+=''<li class="active"><a href="?page=%s">%s</a></li>'%(i,i)'#設置高亮
    else:
        page_html += '<li><a href="?page=%s">%s</a></li>' % (i, i)
book_query=book_query[start_page:end_page]
return render(request,'index.html',locals())
{% for book_obj in book_queryset %}
    <p>{{ book_obj.title }}</p>
{% endfor %}
<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
    {{ page_html|safe }}
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>

哎,嘴上雖說着不寫代碼了,手仍是很誠實的,真是沒辦法啊-_-安全

以上就是自定義分頁器的內容了,不過呢,強大的python怎麼會沒有一個這樣的模塊給咱們使用呢?app

就很少bb了,直接上代碼函數

from app01.utils.mypage import Pagination
def login(request):
    book_query=models.Book.objects.all()
    current_page=request.GET.get('page',1)    
    all_count=book_queryset.count()
    #實例化產生對象
    page_obj=Pagination(current_page=current_page,all_count=all_count)
    #切片操做
    page_queryset=page_queryset[page_obj.start:page_obj.end]
    return render(request,'login.html',locals())

模塊中封裝的分頁器是真他媽的香啊。。。post

建立多表關係的3種方法

全自動

orm一上來就本身動(手建表),這個就不用我多說了吧,你們都懂的(邪魅一笑...)

好處在於他會幫你建立第三張表,但不能對第三張表中的字段進行二次操做,擴展性就比較差了

class Book(models.Model):
    ...
    authors = models.ManyToManyField(to='Author')

class Author(models.Models):
    ...

全手動

這個一看就感受很麻煩了吧,並且居然還有另外的缺點,orm查詢時不少方法都不支持,查詢起來就比較麻煩,很少說,果斷放棄吧

class Book(models.Model):
    ...

class Author(models.Models):
    ...

class Book2Author(models.Model):
    book_id = models.ForeignKey(to='Book')
    author_id = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)
    ...

半自動

orm親兒子,懂吧?

推薦指數6顆星,手動建表,可是會通知orm這表是本身建的,orm提供各類方法就好了,不過有四種方法仍然不支持add,set,remove,clear,不過問題不大哈

class Book(models.Model):
    ...
    authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book','author'))

'''
class Author(models.Model):
    ...
    books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=('author', 'book'))
'''
class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)
    ...
    # 1.半自動 必定要加兩個額外的參數
    through='Book2Author', through_fields=('book','author')
    # 2.後面字段的順序
    由第三張表經過哪一個字段查詢單表 就把哪一個字段放前面

form組件

萬萬沒想到,從這裏纔開始重點,我太難了啊 T.T

開始了啊,加入咱們要設計一個註冊頁面,用戶name不能包含dsb這串字符,密碼不小於3位,這顯然比較簡單

def reg(request):
    back_dic={'username':'','password':''}
    if request.method=='POST':
        username=request.POST.get('username')
        password=request.POSt.get('password')
        if 'dsb' in username:
            back_dic['username']='你輸入的用戶名不符合社會主義核心價值觀'
        if len(password)<3:
            back_dic['password']='過短了哦,嫌棄ing'
    return render(request,'reg.html',local())
<form action="" method="post">
    <p>username:
        <input type="text" name="username">
        <span style="color: red">{{ back_dic.username }}</span>
    </p>
    <p>password:<input type="text" name="password">
    <span style="color: red">{{ back_dic.password }}</span>
    </p>
    <input type="submit">
</form>

這樣寫起來,若是有不一樣的輸入錯誤狀況顯然比較麻煩,因此就要用到form組件了

首先,寫一個類

from django import forms

class Myform(forms.Form):
    username=forms.CharField(min_length=3,max_length=8)
    password=forms.CharField(min_length=3,max_length=8)
    email=forms.EmailField()
#如何校驗數據
from app01 import views
obj=views.Myform({'username':'jason','password':'123','email':'123'})
#判斷數據是否合法
obj.is_valid()
#查看符合條件的數據
obj.cleaned_data
#查看不符合條件的數據
obj.errors
#須要注意的是,全部的參數必須傳值,能夠多傳,不能少傳

如何渲染頁面

第一種方式

封裝成度過高,可擴展性差

<p>
{{form_obj.as_p}}
{{form_obj.as_ul}}
</p>

第二種方式

<p>
    {{ form_obj.username.label }}{{ form_obj.username }}
</p>
<p>
    {{ form_obj.password.label }}{{ form_obj.password }}
</p>
<p>
    {{ form_obj.email.label }}{{ form_obj.email }}
</p>

手寫代碼量太多,明顯不方便

第三種方式

推薦使用

{% for foo in form_obj %}
<p>{{ foo.label }}{{ foo }}</p>
{% endfor %}

如何顯示錯誤信息

因爲form組件會自動前端校驗數據,但前端校驗又不太安全,因此咱們取消他,來後端校驗

在前端中的form表單中添加參數novalidata便可

<!--展現錯誤信息   用對象點errors.0-->
<form action="" method="post" novalidate>
    {% for foo in form_obj %}
    <p>
        {{ foo.label }}:{{ foo }}
        <span style="color: red">{{ foo.errors.0 }}</span>
    </p>
    {% endfor %}
    <input type="submit">
</form>

設置錯誤信息

from django import forms


class MyRegForm(forms.Form):
    username = forms.CharField(min_length=3,max_length=8,label='用戶名',
                               error_messages={
                                   'min_length':'用戶名最短三位',
                                   'max_length':'用戶名最長八位',
                                   'required':'用戶名不能爲空'
                               },initial='我是初始值',required=False
                              )
    password = forms.CharField(min_length=3,max_length=8,label='密碼',error_messages={
                                'min_length':'密碼最短三位',
                                'max_length':'密碼最長八位',
                                'required':'密碼不能爲空'
                            })
    email = forms.EmailField(label='郵箱',error_messages={
                                'required':'郵箱不能爲空',
                                'invalid':'郵箱格式不正確'
                            },required=False)

forms組件鉤子函數

針對字段 你能夠作額外的校驗 經過鉤子函數

局部鉤子

# 當你須要對某一個字段數據進行額外的一些列校驗 你能夠考慮使用鉤子函數
# 針對單個字段的  使用局部鉤子
def clean_username(self):
    username = self.cleaned_data.get('username')
    if 'dsb' in username:
        # 給username字段下面提示錯誤信息
        self.add_error('username','用戶名不符合社會主義核心價值觀')
    return username

全局鉤子

def clean(self):
    password=self.cleaned_data.get('password')
    if not password == confirm_password:
        self.add_error('confirm_password','兩次密碼不一致')
    return self.cleaned_data

正則校驗

from django import forms
from django.forms import Form
from django.core.validators import RegexValidator

class MyForm(Form):
    user = forms.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'), RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')],
    )

改變input框的屬性值

widget= widgets.TextInput()
widget=widgets.PasswordInput()
如何讓forms組件渲染出來的input框有form-control類屬性
widget= widgets.TextInput(attrs={'class':'form-control others'})  # 若是有多個類屬性 空格隔開
widget=widgets.PasswordInput(attrs={'class':'form-control others'})
相關文章
相關標籤/搜索