1. 程式人生 > >Python自動化開發學習24-Django(ModelForm)

Python自動化開發學習24-Django(ModelForm)

python django

使用ModelForm創建

接下來要使用的表結構如下:

# models.py 文件

class UserType(models.Model):
    caption = models.CharField(max_length=32)

class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    email = models.EmailField()
    user_type = models.ForeignKey(to=‘UserType‘, on_delete=models.CASCADE)

表結構寫好之後,生成數據庫:
···
python manage.py makemigrations
python manage.py migrate
···
ModelForm
上節就說過,ModelForm很簡單,所以就下面幾行,沒太多內容:

# forms.py 文件

class UserInfo(forms.ModelForm):

    class Meta:
        model = models.UserInfo
        fields = ‘__all__‘

處理函數

# views.py 文件

def user_info(request):
    if request.method == ‘GET‘:
        obj = forms.UserInfo()
        return render(request, ‘user_info.html‘, {‘obj‘: obj})
    elif request.method == ‘POST‘:
        obj = forms.UserInfo(request.POST)
        return render(request, ‘user_info.html‘, {‘obj‘: obj})

HTML
最後再頁面上顯示出來

<form action="." method="POST">
    {% csrf_token %}
    {{ obj.as_p }}
    <input type="submit" value="提交">
</form>

最後打開頁面查看一下,也是可以自動生成html標簽的,並且效果上和之前用的Form基本沒什麽區別。

自定義label

上面在頁面中顯示的名稱是默認的變量名,如果要顯示中文,需要在models裏定一個變量 verbose_name。
之前在 Python自動化開發學習19-Django 裏講過models的參數。verbose_name :Admin中顯示的字段名稱,默認顯示為變量名。我們用ModelForm也是一樣的,因為Admin裏用的就是ModelForm。

修改的代碼並行下面要將的內容一起了。

顯示選項的內容

因為現在usertype表裏是空的,所以select下拉列表裏沒有其他選項。添加幾條數據後,頁面上會有相應的選項了,但是顯示的內容是對象。為了讓他顯示內容,還要在類裏定一個 __str__ 方法。
連同上面顯示中文標簽一起,修改為下面的樣子:

# modelspy 文件

class UserType(models.Model):
    caption = models.CharField(max_length=32)

    def __str__(self):
        return self.caption

class UserInfo(models.Model):
    username = models.CharField(verbose_name="用戶名", max_length=32)
    email = models.EmailField(verbose_name="電子郵件")
    user_type = models.ForeignKey(verbose_name="用戶類型", to=‘UserType‘, on_delete=models.CASCADE)

定制頁面顯示的字段

上面的ModelForm裏面的元類的fields變量,設置的是顯示所有的字段,也可以傳入一個列表,只顯示要求的那些字段。或者是使用exclude,表示排除哪些字段:

        # fields = ‘__all__‘
        # fields = [‘username‘, ‘user_type‘]
        exclude = [‘email‘]

ModelForm 中 Form 的功能

先了解一下ModelForm和Form的關系。
之前學習使用的Form,繼承的是BaseForm。我這裏用的ModelForm,父類是BaseModelForm,再網上找繼承的還是BaseForm。
之前學習Form的時候,講到Form的2個功能,驗證和生成html標簽。全部都是在BaseForm這個類裏實現的。所以這些功能在ModelForm裏一樣都有,並且用起來和Form幾乎也是一樣的。

元類裏的參數

講師的博客地址:http://www.cnblogs.com/wupeiqi/articles/6229414.html
在上面的例子中,已經用的了3個參數了,model、fields、exclude。下面看見一共有哪些常用的參數:

  • model :對應models的哪張表
  • fields :顯示的字段,__all__表示全部字段
  • exclude :排除的自動
  • labels :自定義標簽名,字典類型 labels = {‘username‘: "名字", ‘email‘: "郵箱", ‘user_type‘: "類型"} 對應上面的例子。如何還在models裏設置了verbose_name,還是以這裏的labels為準。
  • help_texts :提示信息,顯示在輸入框後面。字典類型和上面一樣。
  • widgets :自定義插件,用的還是form的插件,如果直接導入會重名,要加別名 from django.forms import widgets as my_widgets 。用法舉例:widgets = {‘username‘: my_widgets.Textarea(attrs={‘class‘: ‘c1‘})}
  • error_messages :自定義錯誤信息,整體錯誤信息的key是 from django.core.exceptions import NON_FIELD_ERRORS 也就是 ‘__all__‘
  • field_classes :自定義Form驗證的類。默認models裏是CharField,那麽對於Form的類也是CharField。這個設置可以改掉實現自定義。用法舉例:field_classes = {‘username‘: forms.fields.EmailField} 。如果直接導入fields依然會有重名的問題,用as改掉
  • localized_fields :本地化,根據不同時區顯示數據。參數是需要本地化的字段名的元祖,比如:localized_fields=(‘create_time‘,)

元類裏的很多字段設置都和Form裏的用法是一樣的。但是Form裏是一個字段一個字段設置的,而ModelForm是整張表設置的。所以這裏的設置傳入的都是字典,key就是字段名,value就是和Form裏設置的值一樣了。

ModelForm 中 Model 的功能

這裏主要就是數據的增刪改查了

添加數據

直接獲取到對象,用is_valid()方法驗證通過後,直接對對象用一個save()方法就能完成數據的添加。下面是可以完成數據添加的處理函數:

# views.py 文件

def user_info(request):
    if request.method == ‘GET‘:
        obj = forms.UserInfo()
        return render(request, ‘user_info.html‘, {‘obj‘: obj})
    elif request.method == ‘POST‘:
        obj = forms.UserInfo(request.POST)
        if obj.is_valid():
            obj.save()
        return render(request, ‘user_info.html‘, {‘obj‘: obj})

多對多的情況

例子就不寫了。如果是有多對多的關聯,默認也是會更新多對多關聯的第三張表的數據的。
實際上save()方法內部是拆分成2步執行的,先操作當前的這張表,然後去操作多對多關聯的第三張表。save()方法有個默認參數 def save(self, commit=True): 默認設置就是上面那樣執行的。如果參數是False,就是不幫我們自動更新第三張表。如果要用False參數具體用法如下:

instance = obj.save(False)  # 不在任何操作
instance.save()  # 保存當前的表的數據
obj.save_m2m()  # 保存第三張表的數據

填入默認值

要在生成html的時候,在頁面內填入默認值。首先要做一步model操作,去數據庫裏獲取一條數據對象,然後把這個對象作為ModelForm的instance參數傳入。代碼如下:

    if request.method == ‘GET‘:
        user_obj = models.UserInfo.objects.filter(id=1).first()
        obj = forms.UserInfo(instance=user_obj)
        return render(request, ‘user_info.html‘, {‘obj‘: obj})

更新數據

上面填入默認值,在做修改的時候經常會用到。修改完成後提交到後臺,就要進行數據更新了。這裏不能用直接save()方法,因為這樣會變成新建。數據更新用的還是save()方法,但是要再傳入一個參數,告訴系統要把新的數據更新到表的哪一條,否則就是新建。具體的做法如下:

    elif request.method == ‘POST‘:
        user_obj = models.UserInfo.objects.filter(id=1).first()
        obj = forms.UserInfo(request.POST, instance=user_obj)
        if obj.is_valid():
            obj.save()
        return render(request, ‘user_info.html‘, {‘obj‘: obj})

這裏和上面填入默認值的做法差不多,只不過這裏把需要更新的數據也傳遞進來了。

添加額外的字段

比如一個login登錄的應用場景。頁面上除了有用戶名和密碼以外,還可以加一個單選框“記住我”。這個額外的字段是不記錄到數據庫裏的,而是會寫到cookie或者session裏。這種情況,可以把這個字段定義在ModelForm類裏作為公有屬性(靜態屬性),定義的時候完全和定義Form的字段是一樣的:

# forms.py 文件

class UserInfo(forms.ModelForm):

    is_remembered = forms.fields.CharField(
        widget=my_widgets.CheckboxInput(),
        label="記住我",
    )

    class Meta:
    # 元類裏的內容就略了

這樣這個額外的字段在頁面裏會顯示在最後面,有Form的全部功能,驗證和生成html。但是不會有model操作。

Python自動化開發學習24-Django(ModelForm)