经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Django » 查看文章
Django ModelForm组件使用方法详解
来源:jb51  时间:2019/7/23 13:12:53  对本文有异议

一、创建ModelForm

  1. from django.forms import ModelForm
  2. from appxx import models
  3. from django.forms import widgets as wdt # 因为重名,所以起个别名
  4. #定义一个类,比如BookForm,这个类要继承ModelForm,在这个类中再写一个原类Meta(规定写法,注意首字母是大写的)
  5. #在这个原类中,有以下属性(部分):
  6. class BookForm(ModelForm):
  7. class Meta:
  8. model = models.Book # 对应的Model中的类
  9. fields = "__all__" # 字段,如果是__all__,就表示列出所有的字段,或者使用列表列出想要的字段
  10. exclude = None # 排除的字段
  11. # error_messages用法
  12. error_messages = {
  13. "title": {"required": "书名不能为空"},
  14. "price": {"required": "售价不能为空"},
  15. }
  16. # widgets用法,比如把输入用户名的input框给为Textarea
  17. widgets = {
  18. "name": wdt.Textarea(attrs={"class": "c1"}) # 还可以自定义属性
  19. }
  20. #labels,自定义在前端显示的名字
  21. labels= {
  22. "title": "书名",
  23. "price": "售价",
  24. }

然后在 url 对应的视图函数中实例化这个类,把这个对象传给前端:

  1. def add_book(request):
  2. form = forms.BookForm()
  3. return render(request, "add_book.html", {"form": form})

然后在前端像Form组件那样渲染页面

二、添加数据

保存数据的时候,不用挨个取数据了,只需要 save 一下即可。

  1. from django.shortcuts import render,redirect
  2. from appxx import models
  3. from appxx import forms
  4.  
  5.  
  6. def add_book(request):
  7. if request.method == "POST":
  8. form = forms.BookForm(request.POST)
  9. if form.is_valid():
  10. form.save()
  11. return redirect("/book/")
  12. form = forms.BookForm()
  13. return render(request, "add_book.html", {"form": form})

三、编辑数据

如果不使用 ModelForm,编辑的时候得显示之前的数据,还得挨个取一遍值;如果使用 ModelForm,只需要加一个instance=obj(obj是要修改的数据库的一条数据的对象)就可以得到同样的效果。

保存的时候要注意,一定要注意有这个对象(instance=obj),否则不知道更新哪一个数据。

  1. from django.shortcuts import render,redirect
  2. from appxx import models
  3. from appxx import forms
  4.  
  5.  
  6. def edit_book(request, edit_book_id):
  7. edit_book= models.Book.objects.filter(id=edit_book_id).first()
  8. if request.method == "POST":
  9. form = forms.BookForm(request.POST, instance=edit_book)
  10. if form.is_valid():
  11. form.save()
  12. return redirect("/book/")
  13. form = forms.BookForm(instance=edit_book)
  14. return render(request, "edit_book.html", {"form": form})

总结: 从上边可以看到 ModelForm 用起来是非常方便的,比如增加修改之类的操作。但是也带来额外不好的地方,model和form之间耦合了。如果不耦合的话,form.save()方法也无法直接提交保存。 但是耦合的话使用场景通常局限用于小程序,写大程序就最好不用了。

四、完整示例代码

项目结构

urls.py

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3. from appxx import views
  4.  
  5.  
  6. urlpatterns = [
  7. url(r'^admin/', admin.site.urls),
  8. url(r"^book/$", views.book),
  9. url(r"^book/add/", views.add_book),
  10. url(r"^book/edit/(\d+)/", views.edit_book),
  11. ]

views.py

  1. from django.shortcuts import render,redirect
  2. from appxx import models
  3. from appxx import forms
  4.  
  5.  
  6. def book(request):
  7. book_list = models.Book.objects.all()
  8. return render(request, "book.html", {"book_list": book_list})
  9.  
  10.  
  11. def add_book(request):
  12. if request.method == "POST":
  13. form = forms.BookForm(request.POST)
  14. if form.is_valid():
  15. form.save()
  16. return redirect("/book/")
  17. form = forms.BookForm()
  18. return render(request, "add_book.html", {"form": form})
  19.  
  20.  
  21. def edit_book(request, edit_book_id):
  22. edit_book= models.Book.objects.filter(id=edit_book_id).first()
  23. if request.method == "POST":
  24. form = forms.BookForm(request.POST, instance=edit_book)
  25. if form.is_valid():
  26. form.save()
  27. return redirect("/book/")
  28. form = forms.BookForm(instance=edit_book)
  29. return render(request, "edit_book.html", {"form": form})

models.py

  1. from django.db import models
  2.  
  3.  
  4. class Book(models.Model):
  5. id = models.AutoField(primary_key=True)
  6. title = models.CharField(max_length=32)
  7. price = models.DecimalField(max_digits=5, decimal_places=2)
  8. publish_date = models.DateField()
  9. publisher = models.ForeignKey(to="Publisher")
  10. authors = models.ManyToManyField(to="Author")
  11.  
  12. def __str__(self):
  13. return self.title
  14.  
  15.  
  16. class Publisher(models.Model):
  17. id = models.AutoField(primary_key=True)
  18. name = models.CharField(max_length=32)
  19.  
  20. def __str__(self):
  21. return self.name
  22.  
  23.  
  24. class Author(models.Model):
  25. id = models.AutoField(primary_key=True)
  26. name = models.CharField(max_length=32)
  27.  
  28. def __str__(self):
  29. return self.name

forms.py

  1. from django.forms import ModelForm
  2. from appxx import models
  3. from django.forms import widgets as wdt
  4.  
  5.  
  6. class BookForm(ModelForm):
  7. class Meta:
  8. model = models.Book
  9. fields = "__all__"
  10. labels = {
  11. "title": "书名",
  12. "price": "售价",
  13. "publish_date": "出版日期",
  14. "publisher": "出版社",
  15. "authors": "作者"
  16. }
  17. widgets = {
  18. "title": wdt.TextInput(attrs={"class": "form-control"}),
  19. "price": wdt.TextInput(attrs={"class": "form-control"}),
  20. "publish_date": wdt.TextInput(attrs={"class": "form-control", "type": "date"}),
  21. "publisher": wdt.Select(attrs={"class": "form-control"}),
  22. "authors": wdt.SelectMultiple(attrs={"class": "form-control"}),
  23.  
  24. }
  25. error_messages = {
  26. "title": {"required": "书名不能为空"},
  27. "price": {"required": "售价不能为空"},
  28. "publish_date": {"required": "出版日期不能为空"},
  29. "publisher": {"required": "出版社不能为空"},
  30. "authors": {"required": "作者不能为空"},
  31. }

book.html

  1. <!DOCTYPE html>
  2. <html lang="zh-cn">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>展示书籍</title>
  6. <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" >
  7. </head>
  8. <body>
  9. <div class="container">
  10. <div class="row">
  11. <div class="col-md-6 col-md-offset-3">
  12. <span><a class="btn btn-primary" href="/book/add/" rel="external nofollow" >添加</a></span>
  13. <table class="table table-striped table-bordered">
  14. <thead>
  15. <tr>
  16. <th>序号</th>
  17. <th>书名</th>
  18. <th>售价</th>
  19. <th>出版日期</th>
  20. <th>出版社</th>
  21. <th>作者</th>
  22. <th>操作</th>
  23. </tr>
  24. </thead>
  25. <tbody>
  26. {% for book in book_list %}
  27. <tr>
  28. <td>{{ forloop.counter }}</td>
  29. <td>{{ book.title }}</td>
  30. <td>{{ book.price }}</td>
  31. <td>{{ book.publish_date }}</td>
  32. <td>{{ book.publisher.name }}</td>
  33. <td>
  34. {% for author in book.authors.all %}
  35. {{ author.name }}
  36. {% endfor %}
  37. </td>
  38. <td>
  39. <span><a class="btn btn-warning" href="/book/edit/{{ book.pk }}/" rel="external nofollow" >编辑</a></span>
  40. <span><a class="btn btn-danger" href="">删除</a></span>
  41. </td>
  42. </tr>
  43. {% endfor %}
  44. </tbody>
  45. </table>
  46. </div>
  47. </div>
  48. </div>
  49. </body>
  50. </html>

add_book.html和edit_book.html(两个页面代码一样)

  1. <!DOCTYPE html>
  2. <html lang="zh-cn">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>添加书籍</title>
  6. <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" >
  7. <style>
  8. .panel-title {
  9. font-weight: bolder;
  10. }
  11.  
  12. .panel {
  13. margin-top: 30px;
  14. }
  15. </style>
  16. </head>
  17. <body>
  18. <div class="container">
  19. <div class="row">
  20. {# panel开始 #}
  21. <div class="panel panel-danger col-sm-6 col-md-6 col-sm-offset-3 col-md-offset-3">
  22. <div class="panel-heading">
  23. <h3 class="panel-title">添加书籍</h3>
  24. </div>
  25. {# panel-body开始 #}
  26. <div class="panel-body">
  27. {# form开始 #}
  28. <form class="form-horizontal" action="" method="post" novalidate>
  29. {% csrf_token %}
  30. <div class="form-group">
  31. <label class="col-md-2 control-label"
  32. for="{{ form.title.id_for_label }}">{{ form.title.label }}</label>
  33. <div class="col-md-10">
  34. {{ form.title }}
  35. </div>
  36. </div>
  37. <div class="form-group">
  38. <label class="col-md-2 control-label"
  39. for="{{ form.price.id_for_label }}">{{ form.price.label }}</label>
  40. <div class="col-md-10">
  41. {{ form.price }}
  42. </div>
  43. </div>
  44. <div class="form-group">
  45. <label class="col-md-2 control-label"
  46. for="{{ form.publish_date.id_for_label }}">{{ form.publish_date.label }}</label>
  47. <div class="col-md-10">
  48. {{ form.publish_date }}
  49. </div>
  50. </div>
  51. <div class="form-group">
  52. <label class="col-md-2 control-label"
  53. for="{{ form.publisher.id_for_label }}">{{ form.publisher.label }}</label>
  54. <div class="col-md-10">
  55. {{ form.publisher }}
  56. </div>
  57. </div>
  58. <div class="form-group">
  59. <label class="col-md-2 control-label"
  60. for="{{ form.authors.id_for_label }}">{{ form.authors.label }}</label>
  61. <div class="col-md-10">
  62. {{ form.authors }}
  63. </div>
  64. </div>
  65. <div class="form-group">
  66. <div class="col-md-offset-2 col-md-10">
  67. <button type="submit" class="btn btn-success">提交</button>
  68. <a class="btn btn-warning pull-right" href="/book/" rel="external nofollow" >取消</a>
  69. </div>
  70. </div>
  71. </form>
  72. {# form结束 #}
  73. </div>
  74. {# panel-body结束 #}
  75. </div>
  76. {# panel结束 #}
  77. </div>
  78. </div>
  79. </body>
  80. </html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号