一、ModelForm 核心价值
数据库模型
ModelForm
自动生成表单
数据验证
自动保存到数据库
减少重复代码
二、基础使用流程
1. 定义模型与ModelForm
from django. db import models
class Article ( models. Model) :
title = models. CharField( max_length= 200 )
content = models. TextField( )
pub_date = models. DateField( auto_now_add= True )
category = models. ForeignKey( 'Category' , on_delete= models. CASCADE)
class Category ( models. Model) :
name = models. CharField( max_length= 50 )
from django. forms import ModelForm
from . models import Article
class ArticleForm ( ModelForm) :
class Meta :
model = Article
fields = [ 'title' , 'content' , 'category' ]
2. 视图处理逻辑
from django. shortcuts import render, redirect
from . forms import ArticleForm
def create_article ( request) :
if request. method == 'POST' :
form = ArticleForm( request. POST)
if form. is_valid( ) :
article = form. save( )
return redirect( 'article_detail' , pk= article. pk)
else :
form = ArticleForm( )
return render( request, 'blog/article_form.html' , { 'form' : form} )
def update_article ( request, pk) :
article = Article. objects. get( pk= pk)
if request. method == 'POST' :
form = ArticleForm( request. POST, instance= article)
if form. is_valid( ) :
form. save( )
return redirect( 'article_detail' , pk= pk)
else :
form = ArticleForm( instance= article)
return render( request, 'blog/article_form.html' , { 'form' : form} )
三、模板渲染优化
1. 基础模板渲染
{# templates/blog/article_form.html #}
< form method = " post" >
{% csrf_token %}
{{ form.as_p }}
< button type = " submit" class = " btn btn-primary" > 保存</ button>
</ form>
2. 自定义字段渲染
< form method = " post" novalidate >
{% csrf_token %}
< div class = " form-group" >
{{ form.title.label_tag }}
{{ form.title }}
{% if form.title.help_text %}
< small class = " form-text text-muted" > {{ form.title.help_text }}</ small>
{% endif %}
{{ form.title.errors }}
</ div>
< div class = " form-group" >
{{ form.content.label_tag }}
{{ form.content }}
{{ form.content.errors }}
</ div>
</ form>
四、高级配置技巧
1. Meta 配置项详解
class ArticleForm ( ModelForm) :
class Meta :
model = Article
fields = '__all__'
exclude = [ 'pub_date' ]
labels = {
'title' : '文章标题' ,
'content' : '正文内容'
}
widgets = {
'pub_date' : forms. DateInput( attrs= { 'type' : 'date' } ) ,
'content' : forms. Textarea( attrs= { 'rows' : 6 } )
}
error_messages = {
'title' : { 'required' : '标题不能为空' }
}
2. 自定义验证逻辑
class ArticleForm ( ModelForm) :
class Meta :
model = Article
fields = [ 'title' , 'content' ]
def clean_title ( self) :
title = self. cleaned_data[ 'title' ]
if '广告' in title:
raise forms. ValidationError( "标题包含敏感词汇" )
return title
def clean ( self) :
cleaned_data = super ( ) . clean( )
if cleaned_data. get( 'title' ) and len ( cleaned_data[ 'content' ] ) < 100 :
self. add_error( 'content' , '正文内容至少需要100字' )
return cleaned_data
五、特殊场景处理
1. 多对多关系处理
class Tag ( models. Model) :
name = models. CharField( max_length= 20 )
class Article ( models. Model) :
tags = models. ManyToManyField( Tag)
class ArticleForm ( ModelForm) :
class Meta :
model = Article
fields = [ 'title' , 'tags' ]
widgets = {
'tags' : forms. CheckboxSelectMultiple
}
def create_article ( request) :
if request. method == 'POST' :
form = ArticleForm( request. POST)
if form. is_valid( ) :
article = form. save( commit= False )
article. author = request. user
article. save( )
form. save_m2m( )
return redirect( 'success' )
2. 文件上传处理
class Document ( models. Model) :
title = models. CharField( max_length= 100 )
file = models. FileField( upload_to= 'documents/' )
class DocumentForm ( ModelForm) :
class Meta :
model = Document
fields = [ 'title' , 'file' ]
def upload_document ( request) :
if request. method == 'POST' :
form = DocumentForm( request. POST, request. FILES)
if form. is_valid( ) :
form. save( )
return redirect( 'success' )
else :
form = DocumentForm( )
return render( request, 'upload.html' , { 'form' : form} )
六、最佳实践与优化
1. 字段选择策略
fields = [ 'title' , 'content' ]
exclude = [ 'created_at' ]
fields = '__all__'
2. 性能优化方案
class ArticleForm ( ModelForm) :
class Meta :
model = Article
fields = [ 'category' ]
def __init__ ( self, * args, ** kwargs) :
super ( ) . __init__( * args, ** kwargs)
self. fields[ 'category' ] . queryset = Category. objects. filter ( is_active= True )
3. 安全防护措施
class UserProfileForm ( ModelForm) :
class Meta :
model = User
fields = [ 'username' , 'email' ]
def __init__ ( self, * args, ** kwargs) :
super ( ) . __init__( * args, ** kwargs)
if not self. instance. is_staff:
del self. fields[ 'is_staff' ]
七、扩展方案
1. 动态字段生成
def get_article_form ( fields) :
class DynamicArticleForm ( ModelForm) :
class Meta :
model = Article
fields = fields
return DynamicArticleForm
ArticleForm = get_article_form( [ 'title' , 'category' ] )
2. 模型表单集 (ModelFormset)
from django. forms import modelformset_factory
ArticleFormSet = modelformset_factory(
Article,
fields= [ 'title' , 'category' ] ,
extra= 2 ,
can_delete= True
)
def manage_articles ( request) :
if request. method == 'POST' :
formset = ArticleFormSet( request. POST)
if formset. is_valid( ) :
formset. save( )
else :
formset = ArticleFormSet( queryset= Article. objects. filter ( is_draft= True ) )
return render( request, 'manage.html' , { 'formset' : formset} )