django----多對多三種創建方式 form組件


多對多三種創建方式

# 補充知識點 related_name 參數 正反向查詢的name
publish = models.ForeignKey(to='Book', related_name='pb')
# 這樣查publish表的時候就可以直接點pb了

全自動

 class Book(models.Model):
        title = models.CharField(max_length=255)
        # 多對多關系字段
        authors = models.ManyToManyField(to='Authors')
        
 class Authors(models.Model):
        name = models.CharField(max_length=32)

​ 好處:自始至終都沒有操作第三張表 全部都是orm自動幫你創建的 且內置 4個方法 操作第三張表 add set remove clear

​ 不足: 自動創建的第三張表 無法擴展 和 字段修改 擴展性較差

全手動

 class Book(models.Model):
        title = models.CharField(max_length=255)
        
 class Authors(models.Model):
        name = models.CharField(max_length=32)
 
 class Book2Author(models.Model):
        book = models.ForeignKey(to='Book')
        author = models.ForeignKey(to='Authors')
        # 添加其他字段
        create_time = models.DateField(auto_now_add=True)

​ 好處:第三張表中字段完全可以自定義

​ 壞處:不在支持orm的跨表查詢 以及內置的方法

半自動

class Book(models.Model):
        title = models.CharField(max_length=255)
        # 添加多對多關系字段
        authors = models.ManyToMangField(to='Authors', through='Book2Author', through_fields=('book','authors'))
        # through 告訴orm 用我自己建的外鍵
        
 class Authors(models.Model):
        name = models.CharField(max_length=32)
 
 class Book2Author(models.Model):
        book = models.ForeignKey(to='Book')
        author = models.ForeignKey(to='Authors')
        # 添加其他字段
        create_time = models.DateField(auto_now_add=True)
        # 該表中可以有任意多的外鍵字段

​ 當你的ManyToManyField 只有一個參數to的情況下 orm會自動幫你創建第三張表

​ 如果你加了through through_fields 那么 orm 就不會 幫你創建第三張表, 但是他會在內部幫你維護關系,讓你能夠使用orm的跨表查詢

though_fields = ('book','author') 內的字段是有順序的 在那張表就用那個字段 或者 去第三張表 看 第三張表查當前表通過那個字段 就是那個字段

through 是告訴django的orm 多對多對應關系是通過Book2Author來記錄的

優點: 結合了 全自動全手動的 兩個優點

form組件

​ 我們在好多場景下都需要對用戶的輸入做校驗,比如校驗用戶是否輸入,輸入的長度和格式等正不正確。如果用戶輸入的內容有錯誤就需要在頁面上相應的位置顯示對應的錯誤信息.。Django form組件就實現了上面所述的功能。


1.前端搭建頁面 >>> 渲染頁面
2.將數據傳輸后端處理 >>> 數據校驗
3.展示錯誤信息 >>> 展示信息

基本使用

​ 提示:注意參數 required不能為空 默認是True
initial 默認值 label 標簽名 invalid 無效的(格式) error_messages 校驗錯誤的提示信息
widget 后跟forms.widget.字段類型 括號內的attr 是添加屬性的

# form組件模塊導入
from django import forms
# 自定義form類 繼承forms.Form
class MyForm(forms.Form):
    # 定義需要校驗和前端展示的標簽或字段
    username = forms.CharField(max_length=8, min_length=3, label='用戶名', required=True,
                               initial='輸入....',
                               error_messages={
                                   'max_length':'最大8位',
                                   'min_length':'最小3位',
                                   'required':'不能為空',
                               },
                               widget=forms.widgets.TextInput(attrs={'class':'you is sd'})
                               )
    password = forms.CharField(max_length=16, min_length=5, label='密碼', required=True,
                               initial='輸入密碼.....',
                               error_messages={
                                   'max_length':'最大16位',
                                   'min_length':'最小3位',
                                   'required':'不能為空',
                               },
                               widget=forms.widgets.PasswordInput(attrs={'class':'password'})
                               )
    email = forms.EmailField(label='郵箱',error_messages={
        'required':'不能為空',
        'invalid':'格式不正確'
    })

form_obj 及 is_valid()

def form(request):
    # 生成MyForm對象
    form_obj = MyForm()
    # 判斷是否是post請求
    if request.method == 'POST':
        form_obj = MyForm(request.POST)
        # 判斷數據是否通過校驗
        if form_obj.is_valid():
            print('校驗成功')
            return HttpResponse('校驗成功')
        else:
            return render(request, 'test.html', locals())
    return render(request, 'test.html', locals())

前端渲染方式

{# 方式一 #}
    {{ form_obj.as_p }}
    {{ form_obj.as_ul }}
    {{ form_obj.as_table }}
{# 方式二 #}
    <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>
{# 方式三 #}   {# 推薦使用 #}
{# 使用對象點errors.0 拿到校驗錯誤信息#}
    {% for foo in form_obj %}
        <p>{{ foo.label }}:{{ foo }}<span>{{ foo.errors.0 }}</span></p>
    {% endfor %}

取消前端自動校驗

校驗數據的時候可以前后端都校驗 做一個雙重的校驗 但是前端的校驗可有可無 而后端的校驗則必須要有,因為前端的校驗可以通過爬蟲直接避開 前端取消瀏覽器校驗功能 form標簽指定novalidate屬性即可

正則校驗

# 導入模塊
from django.core.validators import RegexValidator
# 例子
phone = forms.CharField(required=False,
                       validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'),
                                  RegexValidator(r'^159[0-9]+$', '數字必須是159開頭')]
                       )

鈎子函數(Hook方法)

forms組件暴露給用戶可自定義的校驗規則 需要在類中寫(順序是先通過普通校驗 然后才是鈎子)

cleaned_data

​ 校驗通過的數據都會放在cleaned_data里面

主動拋錯誤信息

add_error() 兩個參數 第一個是錯誤的字段 第二個是 錯誤的信息

from django.core.exceptions import ValidationError
raise ValidationError('手機格式錯誤')

局部鈎子

​ 針對某一個字段做額外的校驗 校驗用戶名字是否含有 666 一旦有 就提示

# 局部鈎子固定寫法 clean_ + 需要校驗的字段
def clean_username(self):
    username = self.cleaned_data.get('username')
    if '666' in username:
        # 主動拋錯誤信息
        self.add_error('username', '名字中沒有666')
   	# 需要返回 username
	return username

全局鈎子

​ 針對多個字段做額外的校驗

# 局部鈎子固定寫法 clean
def clean(self):
	password = self.cleaned_data.get('password')
    confirm_password = self.cleaned_data.get('confirm_password')
    if not password == confirm_password:
        self.add_error('confirm_password', '兩次密碼不一致')
    return self.cleaned_data

多選框(了解知識點)

radioSelect

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用戶名",
        initial="張三",
        error_messages={
            "required": "不能為空",
            "invalid": "格式錯誤",
            "min_length": "用戶名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密碼")
    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性別",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )

單選Select

class LoginForm(forms.Form):
    ...
    hobby = forms.ChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
        label="愛好",
        initial=3,
        widget=forms.widgets.Select()
    )

多選Select

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
        label="愛好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

單選checkbox

class LoginForm(forms.Form):
    ...
    keep = forms.ChoiceField(
        label="是否記住密碼",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

多選checkbox

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
        label="愛好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM