一, form 组件 - 图书管理系统
图书管理系统: 点我 https://www.cnblogs.com/glh-ty/articles/9427976.html
- urls.py
- from django.conf.urls import url
- from django.contrib import admin
- from app01 import views
- urlpatterns = [ url(r'^admin/', admin.site.urls),
- url(r'^book_list', views.book_list),
- url(r'^add_book', views.add_book),
- url(r'^edit_book/(\d+)', views.edit_book)
- ]
- models.py
- from django.db import models
- # Create your models here.
- class Publish(models.Model):
- name = models.CharField(max_length=32, null=False)
- addr = models.CharField(max_length=64)
- def __str__(self):
- return self.name
- class Author(models.Model):
- name = models.CharField(max_length=32, verbose_name="姓名")
- gender = models.SmallIntegerField(
- choices=((0, "男"), (1, "女"), (2, "不明"))
- )
- age = models.IntegerField()
- def __str__(self):
- return self.name
- class Book(models.Model):
- title = models.CharField(max_length=32, verbose_name="书名")
- price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="价格")
- publish_date = models.DateField(verbose_name="出版日期")
- publisher = models.ForeignKey(to="Publish", on_delete=models.CASCADE)
- authors = models.ManyToManyField(to="Author")
- def __str__(self):
- return self.title
- models.py
- my_forms.py
- from django import forms
- from app01 import models
- class BookForm(forms.Form):
- title = forms.CharField(max_length=32, label="书名")
- price = forms.DecimalField(max_digits=5, decimal_places=2)
- publish_date = forms.DateField(
- widget=forms.widgets.TextInput(
- attrs={"type": "date"}
- )
- )
- # 这样写可以实现添加书籍, 不能实现编辑书籍, 因为编辑书籍需要显示要编辑的这本数的原来的出版社和作者
- # 即需要默认值, 无法操作
- # publisher = forms.ChoiceField(
- # choices=models.Publish.objects.all().values_list("id", "name"),
- # widget=forms.widgets.Select()
- # )
- # authors = forms.ChoiceField(
- # choices=models.Author.objects.all().values_list("id", "name"),
- # widget=forms.widgets.SelectMultiple()
- # )
- # 解决上述不能实现编辑书籍的问题
- publisher = forms.ModelChoiceField(
- queryset=models.Publish.objects.all()
- )
- authors = forms.ModelMultipleChoiceField(
- queryset=models.Author.objects.all()
- )
- views.py
- from django.shortcuts import render, redirect
- from app01 import models
- from app01.myforms import BookForm
- from django.forms.models import model_to_dict
- # Create your views here.
- # 日志操作
- import logging
- logger = logging.getLogger(__name__) # 生成一个以当前文件名为名字的日志实例对象
- collect_logger = logging.getLogger("collect") # 生成一个名字是 collect 的日志实例对象
- def book_list(request):
- book_list_obj = models.Book.objects.all()
- return render(request, "book_list.html", {"book_list_obj": book_list_obj})
- # 使用一般的 form 组件
- def add_book(request):
- form_obj = BookForm()
- # publisher = models.Publish.objects.all() # 使用 form 组件不需要传了
- # authors = models.Author.objects.all() # # 使用 form 组件不需要传了
- if request.method == "POST":
- form_obj = BookForm(request.POST)
- if form_obj.is_valid():
- authors = form_obj.cleaned_data.pop("authors")
- book_obj = models.Book.objects.create(**form_obj.cleaned_data)
- # book_obj.authors.add(*authors) # 二者都可以
- book_obj.authors.set(authors) # 既可以是对象列表, 又可以是 id 列表
- return redirect("/book_list/")
- return render(request, "add_book.html", {"form_obj": form_obj})
- def edit_book(request, pk):
- book_obj = models.Book.objects.filter(id=pk).first()
- dic_obj = model_to_dict(book_obj) # 把一个对象转换为字典的格式
- print(dic_obj)
- form_obj = BookForm(initial=dic_obj) # 注意这里的 initial, 传入的是一个字典的形式, 指定默认值(编辑书籍需要有默认值)
- if request.method == "POST":
- form_obj = BookForm(request.POST)
- if form_obj.is_valid():
- # form 组件写的 只能一个一个写, 不过变成从 form_obj.cleaned_data 中取值
- title = form_obj.cleaned_data.get("title")
- price = form_obj.cleaned_data.get("price")
- publish_date = form_obj.cleaned_data.get("publish_date")
- publisher = form_obj.cleaned_data.get("publisher")
- authors = form_obj.cleaned_data.get("authors")
- book_obj.title = title
- book_obj.price = price
- book_obj.publish_date = publish_date
- book_obj.publisher_id = publisher
- book_obj.save()
- book_obj.authors.set(authors) # 可以是对象列表, 又可以是 id 列表
- return redirect("/book_list/")
- return render(request, "edit_book.html", {"form_obj": form_obj})
- templates
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <table border="1">
- <a href="/add_book/">添加书籍</a>
- <thead>
- <tr>
- <th > 序号</th>
- <th>id</th>
- <th > 书名</th>
- <th > 作者</th>
- <th > 出版社</th>
- <th > 出版日期</th>
- <th > 操作</th>
- </tr>
- </thead>
- <tbody>
- {% for book_obj in book_list_obj %}
- <tr>
- <td>{{ forloop.counter }}</td>
- <td>{{ book_obj.id }}</td>
- <td>{{ book_obj.title }}</td>
- <td>
- {% for author in book_obj.authors.all %}
- {{ author.name }}
- {% endfor %}
- </td>
- <td>{{ book_obj.publisher.name }}</td>
- <td>{{ book_obj.publish_date|date:"Y-m-d" }}</td>
- <td>
- <a href="/edit_book/{{ book_obj.id }}">编辑</a>
- <a href="/del_book/{{ book_obj.id }}">删除</a>
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </body>
- </html>
- book_list.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <form action=""method="post">
- {% csrf_token %}
- <!-- 原本这样写
- <label for="{{ form_obj.publish_date.id_for_label }}">{{ form_obj.publish_date.label}}</label>
- {{ form_obj.publish_date }}
- {{ form_obj.publish_date.errors.0 }}
- <hr>
- {{ form_obj.publish_date.label }}
- {{ form_obj.publish_date }}
- <hr>
- -->
- <!-- for 循环写法和上面一样 -->
- {% for filed in form_obj %}
- <p>
- {{ filed.label}}
- {{ filed }}
- </p>
- {{ filed.errors }}
- {% endfor %}
- <p>
- <input type="submit">
- </p>
- </form>
- </body>
- </html>
- add_book.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <form action=""method="post">
- {% csrf_token %}
- {% for filed in form_obj %}
- <p>
- {{ filed.label}}
- {{ filed }}
- </p>
- {{ filed.errors }}
- {% endfor %}
- <p>
- <input type="submit">
- </p>
- </form>
- </body>
- </html>
- edit_book.html
二, ModelForm - 图书管理系统
- my_forms.py
- from django import forms
- from app01 import models
- class BookModelForm(forms.ModelForm):
- class Meta:
- # 告诉 Django 这个 form 类和那个 model 类对应
- model = models.Book
- # 告诉 Django 这个 form 类里面有哪些字段
- fields = "__all__" # 所有字段
- # fields = ["title", "price"]
- # exclude = ["authors"] # 不要 authors
- widgets = {
- "publish_date": forms.widgets.DateInput(
- attrs={"type": "date", "class": "form-control"} # 也可以加 bootstrap 样式
- )
- }
- labels = {
- "title": "书名",
- "price": "价格",
- "publish_date": "出版日期"
- }
- error_messages = {
- "title": {
- "required": "书名不能为空"
- }
- }
- views.py
- from django.shortcuts import render, redirect
- from app01 import models
- # Create your views here.
- from app01.myforms import BookModelForm
- import logging
- logger = logging.getLogger(__name__) # 生成一个以当前文件名为名字的日志实例对象
- collect_logger = logging.getLogger("collect") # 生成一个名字是 collect 的日志实例对象
- def book_list(request):
- book_list_obj = models.Book.objects.all()
- return render(request, "book_list.html", {"book_list_obj": book_list_obj})
- # 使用 modelform 解决上面编辑时代码重复写
- def add_book(request):
- form_obj = BookModelForm()
- # publisher = models.Publish.objects.all() # 使用 form 组件不需要传了
- # authors = models.Author.objects.all() # # 使用 form 组件不需要传了
- if request.method == "POST":
- form_obj = BookModelForm(request.POST)
- if form_obj.is_valid():
- # 使用 BookModelForm, 下面的都不需要, 只需 save()
- # authors = form_obj.cleaned_data.pop("authors")
- # book_obj = models.Book.objects.create(**form_obj.cleaned_data)
- # # book_obj.authors.add(*authors) # 二者都可以
- # book_obj.authors.set(authors) # 既可以是对象列表, 又可以是 id 列表
- form_obj.save()
- return redirect("/book_list/")
- return render(request, "add_book.html", {"form_obj": form_obj})
- def edit_book(request, pk):
- # 日志打印练习
- logger.debug('又要编辑 id 值是 {} 的书籍了...'.format(pk))
- logger.info('又要编辑 id 值是 {} 的书籍了...'.format(pk))
- collect_logger.warning("id 是 {} 的书籍又被人编辑了...".format(pk))
- book_obj = models.Book.objects.filter(id=pk).first()
- form_obj = BookModelForm(instance=book_obj) # 不需要转化为字典了, 直接传对象
- if request.method == "POST":
- form_obj = BookModelForm(request.POST, instance=book_obj)
- if form_obj.is_valid():
- form_obj.save()
- return redirect("/book_list/")
- return render(request, "edit_book.html", {"form_obj": form_obj})
三, 关于 ModelForm
form 与 model 的终极结合.
class Meta: 下常用参数:
- model = models.Student # 对应的 Model 中的类
- fields = "__all__" # 字段, 如果是__all__, 就是表示列出所有的字段
- exclude = None # 排除的字段
- labels = None # 提示信息
- help_texts = None # 帮助提示信息
- widgets = None # 自定义插件
- error_messages = None # 自定义错误信息
来源: http://www.bubuko.com/infodetail-2743666.html