建一个图片类网站需要多少钱,网站备案查询怎么查,wordpress看板娘素材,公司做网站用什么主机Django表单集
一、知识要点概览表
类别知识点掌握程度要求基础概念FormSet、ModelFormSet深入理解内联表单集InlineFormSet、BaseInlineFormSet熟练应用表单集验证clean方法、验证规则熟练应用自定义配置extra、max_num、can_delete理解应用动态管理JavaScript动态添加/删除表…Django表单集
一、知识要点概览表
类别知识点掌握程度要求基础概念FormSet、ModelFormSet深入理解内联表单集InlineFormSet、BaseInlineFormSet熟练应用表单集验证clean方法、验证规则熟练应用自定义配置extra、max_num、can_delete理解应用动态管理JavaScript动态添加/删除表单掌握使用
二、基础模型和表单设置
# models.py
from django.db import modelsclass Author(models.Model):name models.CharField(max_length100)email models.EmailField()bio models.TextField()def __str__(self):return self.nameclass Book(models.Model):author models.ForeignKey(Author, on_deletemodels.CASCADE)title models.CharField(max_length200)isbn models.CharField(max_length13)publication_date models.DateField()price models.DecimalField(max_digits10, decimal_places2)def __str__(self):return self.title# forms.py
from django import forms
from .models import Author, Bookclass AuthorForm(forms.ModelForm):class Meta:model Authorfields [name, email, bio]class BookForm(forms.ModelForm):class Meta:model Bookfields [title, isbn, publication_date, price]三、基本表单集实现
1. 创建表单集
# forms.py
from django.forms import modelformset_factory, formset_factory# 创建Book模型的表单集
BookFormSet modelformset_factory(Book,formBookForm,extra2, # 额外空表单数量max_num5, # 最大表单数量can_deleteTrue # 允许删除
)# 创建自定义表单集
class BaseBookFormSet(forms.BaseModelFormSet):def clean(self):super().clean()titles []for form in self.forms:if form.cleaned_data:title form.cleaned_data.get(title)if title in titles:raise forms.ValidationError(书籍标题不能重复)titles.append(title)# 使用自定义表单集基类
BookFormSet modelformset_factory(Book,formBookForm,formsetBaseBookFormSet,extra2
)2. 视图实现
# views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import BookFormSet, AuthorFormclass BookFormSetView(View):template_name books/book_formset.htmldef get(self, request):formset BookFormSet(querysetBook.objects.none())return render(request, self.template_name, {formset: formset})def post(self, request):formset BookFormSet(request.POST)if formset.is_valid():instances formset.save()messages.success(request, f成功保存{len(instances)}本书籍信息)return redirect(book_list)return render(request, self.template_name, {formset: formset})def manage_books(request, author_id):author get_object_or_404(Author, idauthor_id)if request.method POST:formset BookFormSet(request.POST,querysetBook.objects.filter(authorauthor))if formset.is_valid():books formset.save(commitFalse)for book in books:book.author authorbook.save()# 处理删除的书籍for obj in formset.deleted_objects:obj.delete()return redirect(author_detail, pkauthor.pk)else:formset BookFormSet(querysetBook.objects.filter(authorauthor))return render(request, books/manage_books.html, {formset: formset,author: author})四、内联表单集实现
1. 创建内联表单集
# forms.py
from django.forms import inlineformset_factory# 创建Author-Book内联表单集
BookInlineFormSet inlineformset_factory(Author, # 父模型Book, # 子模型formBookForm,extra2,max_num5,can_deleteTrue
)# 自定义内联表单集
class BaseBookInlineFormSet(forms.BaseInlineFormSet):def clean(self):super().clean()total_price 0for form in self.forms:if form.cleaned_data and not form.cleaned_data.get(DELETE, False):price form.cleaned_data.get(price, 0)total_price priceif total_price 1000:raise forms.ValidationError(所有书籍总价不能超过1000)# 使用自定义内联表单集
BookInlineFormSet inlineformset_factory(Author,Book,formBookForm,formsetBaseBookInlineFormSet,extra2
)2. 视图实现
# views.py
from django.views.generic.edit import UpdateView
from .forms import BookInlineFormSetclass AuthorBooksUpdateView(UpdateView):model Authorform_class AuthorFormtemplate_name books/author_books_form.htmldef get_context_data(self, **kwargs):context super().get_context_data(**kwargs)if self.request.POST:context[book_formset] BookInlineFormSet(self.request.POST,instanceself.object)else:context[book_formset] BookInlineFormSet(instanceself.object)return contextdef form_valid(self, form):context self.get_context_data()book_formset context[book_formset]if book_formset.is_valid():self.object form.save()book_formset.instance self.objectbook_formset.save()return redirect(author_detail, pkself.object.pk)return self.render_to_response(self.get_context_data(formform))五、表单集模板实现
!-- templates/books/author_books_form.html --
{% extends base.html %}
{% load static %}{% block content %}
div classcontainerh1编辑作者及其书籍/h1form methodpost{% csrf_token %}div classauthor-formh2作者信息/h2{{ form.as_p }}/divdiv classbooks-formseth2书籍信息/h2{{ book_formset.management_form }}div idbook-forms{% for book_form in book_formset %}div classbook-form{{ book_form.non_field_errors }}div classform-rowdiv classform-group{{ book_form.title.label_tag }}{{ book_form.title }}{{ book_form.title.errors }}/divdiv classform-group{{ book_form.isbn.label_tag }}{{ book_form.isbn }}{{ book_form.isbn.errors }}/divdiv classform-group{{ book_form.price.label_tag }}{{ book_form.price }}{{ book_form.price.errors }}/div{% if book_form.instance.pk %}{{ book_form.DELETE }}{% endif %}/div/div{% endfor %}/divbutton typebutton idadd-book classbtn btn-secondary添加书籍/button/divbutton typesubmit classbtn btn-primary mt-3保存/button/form
/div{% block extra_js %}
script
$(document).ready(function() {// 获取表单总数const totalForms $(#id_book_set-TOTAL_FORMS);// 添加新书籍表单$(#add-book).click(function() {const formCount parseInt(totalForms.val());const newForm $(#book-forms .book-form:first).clone(true);// 更新表单索引newForm.find(:input).each(function() {const name $(this).attr(name).replace(-0-, - formCount -);const id id_ name;$(this).attr({name: name, id: id}).val();});// 更新标签的for属性newForm.find(label).each(function() {const newFor $(this).attr(for).replace(-0-, - formCount -);$(this).attr(for, newFor);});// 添加新表单到DOM$(#book-forms).append(newForm);totalForms.val(formCount 1);});
});
/script
{% endblock %}
{% endblock %}六、表单集处理流程图 七、高级用法示例
1. 工厂函数自定义
def get_book_formset(extra1, max_numNone):return modelformset_factory(Book,formBookForm,extraextra,max_nummax_num,validate_maxTrue,can_deleteTrue,widgets{title: forms.TextInput(attrs{class: form-control}),isbn: forms.TextInput(attrs{class: form-control}),price: forms.NumberInput(attrs{class: form-control})})# 在视图中使用
def manage_books_dynamic(request):BookFormSet get_book_formset(extra2,max_num10)if request.method POST:formset BookFormSet(request.POST)if formset.is_valid():formset.save()return redirect(book_list)else:formset BookFormSet()return render(request, books/manage_books.html, {formset: formset})2. 条件验证
class BaseBookFormSet(forms.BaseModelFormSet):def clean(self):super().clean()# 检查ISBN唯一性isbns []for form in self.forms:if form.cleaned_data and not form.cleaned_data.get(DELETE, False):isbn form.cleaned_data.get(isbn)if isbn in isbns:raise forms.ValidationError(ISBN必须唯一)isbns.append(isbn)# 检查总价格total_price sum(form.cleaned_data.get(price, 0)for form in self.formsif form.cleaned_data and not form.cleaned_data.get(DELETE, False))if total_price 1000:raise forms.ValidationError(所有书籍总价不能超过1000)3. 动态表单处理
# views.py
from django.http import JsonResponseclass DynamicBookFormView(View):def post(self, request):if request.is_ajax():formset BookFormSet(request.POST)if formset.is_valid():instances formset.save()return JsonResponse({status: success,message: f成功保存{len(instances)}本书籍})else:errors []for form in formset:for field, error in form.errors.items():errors.append(f{field}: {error})return JsonResponse({status: error,errors: errors})return JsonResponse({status: error, message: 非法请求})这就是关于Django表单集的详细内容。通过学习这些内容你将能够理解和使用Django的表单集系统实现复杂的表单处理逻辑。如果有任何问题欢迎随时提出 怎么样今天的内容还满意吗再次感谢朋友们的观看关注GZH凡人的AI工具箱回复666送您价值199的AI大礼包。最后祝您早日实现财务自由还请给个赞谢谢