zoukankan      html  css  js  c++  java
  • Django之modelform组件

    modelform来源:

      构建一个数据库驱动的应用,那么你可能会有与Django的模型紧密映射的表单。比如,你有个Student模型,并且你还想创建一个表单让大家提交评论到这个模型中。在这种情况下,写一个forms.Form类,然后在表单类中定义字段,这种一般创建表单的做法是冗余的,因为你已经在ORM模型model中定义了字段的属性和功能,完全没必要重新写一遍字段。

    一、核心用法

    基于这个原因,Django提供一个辅助类帮助我们利用Django的ORM模型model创建Form。

    用法的核心是:
    
    1.首先从django.forms导入ModelForm;
    2.编写一个自己的类,继承ModelForm;
    3.在新类里,设置元类Meta;
    4.在Meta中,设置model属性为你要关联的ORM模型,这里是Article;
    5.在Meta中,设置fields属性为你要在表单中使用的字段列表;
    6.列表里的值,应该是ORM模型model中的字段名。
    
    上面的例子中,因为model和form比较简单,字段数量少,看不出这么做的威力和效率。但如果是那种大型项目,每个模型的字段数量几十上百,这么做的收益将非常巨大,而且后面还有一招提高效率的大杀器,也就是一步保存数据的操作。

    Django在设计model字段和表单字段时存在大量的相似和重复之处。

    特别注意:ManyToManyField和 ForeignKey字段类型属于特殊情况:

    • ForeignKey被映射成为表单类的django.forms.ModelChoiceField,它的选项是一个模型的QuerySet,也就是可以选择的对象的列表,但是只能选择一个。

    • ManyToManyField被映射成为表单类的django.forms.ModelMultipleChoiceField,它的选项也是一个模型的QuerySet,也就是可以选择的对象的列表,但是可以同时选择多个,多对多嘛。

    同时,在表单属性设置上,还有下面的映射关系:

    如果模型字段设置blank=True,那么表单字段的required设置为False。 否则,required=True。
    表单字段的label属性根据模型字段的verbose_name属性设置,并将第一个字母大写。
    如果模型的某个字段设置了editable=False属性,那么它表单类中将不会出现该字段。道理很简单,都不能编辑了,还放在表单里提交什么?
    表单字段的help_text设置为模型字段的help_text。
    如果模型字段设置了choices参数,那么表单字段的widget属性将设置成Select框,其选项来自模型字段的choices。
    选单中通常会包含一个空选项,并且作为默认选择。如果该字段是必选的,它会强制用户选择一个选项。 如果模型字段具有default参数,则不会添加空选项到选单中。

    以下是使用modelform的示例,详细看代码:

    models:

    from django.db import models
    
    # Create your models here.
    class Book(models.Model):
        id = models.AutoField(primary_key=True) #可不填,Django会自动帮你写
        title = models.CharField(max_length=32,)
        price = models.DecimalField(max_digits=5, decimal_places=2,)
        pub_date = models.DateField()
        #与Publish(id)建立一对多的外键关系
        publish = models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE)
        # 不会添加外键,会另外创建表格
        authors = models.ManyToManyField(to="Author")
        def __str__(self):
            return self.title
    
        class Meta:
            verbose_name="书籍"
    
    class Publish(models.Model):
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
        email = models.EmailField()
        def __str__(self):
            return self.name
    
        class Meta:
            verbose_name="出版社"
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        authorDetail = models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)
        def __str__(self):
            return self.name
        class Meta:
            verbose_name = "作者"
    
    class AuthorDetail(models.Model):
        birthday = models.DateField()
        phone = models.BigIntegerField()
        addr = models.CharField(max_length=64)
        def __str__(self):
            return self.addr
    
        class Meta:
            verbose_name = "作者详情"
    
    class user_info(models.Model):
        name = models.CharField(max_length=64)
        password = models.CharField(max_length=64)
        def __str__(self):
            return self.name
    View Code

    views:

    from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
    from django.forms import widgets as wid
    from django import forms
    
    
    class BookModelForm(forms.ModelForm):
        class Meta:
            model = models.Book  #绑定对应的模型
            # fields=["title","price"]
            # exclude = ["title"]
            fields = "__all__"  #自定义要展示的字段
    
            widgets = {   #自定义字段的样式
                "title": wid.TextInput(attrs={"class": "form-control"}),
                "price": wid.TextInput(attrs={"class": "form-control"}),
                "pub_date":wid.TextInput(attrs={"class": "form-control"}),
                "publish": wid.Select(attrs={"class": "form-control"}),
                "authors": wid.SelectMultiple(attrs={"class": "form-control"}),
    
            }
    
            error_messages = {
                "title": {"required": "该字段不能为空"}  #自定义错误信息
            }
            labels = {
                "title": "书籍名称"                  #自定义字段名称,展示起来比较素福
            }
        #
        def clean_title(self):
            val = self.cleaned_data.get("title")
            if val.startswith("a"):
                return val
            else:
                raise ValidationError("必须以a开头!")
    
    
    def addbook(request):
        if request.method == "POST":
            form = BookModelForm(request.POST)
            if form.is_valid():
                form.save()
                return redirect("/books/")
            else:
                return render(request, 'addbook.html', locals())
        else:
            form = BookModelForm()  # modelforms组件
            return render(request, 'addbook.html', locals())
    View Code

     html:

    <div class="row">
        <div class="col-md-4 col-md-offset-3">
            <form action="" method="post" novalidate>
                {% csrf_token %}
                {% for field in form %}
                    <div class="form-group">
                        <label for="title">{{ field.label }}</label>
                        {{ field }} <span>{{ field.errors.0 }}</span>
                    </div>
                 {% endfor %}
    
                <input type="submit"value="submit" class="btn btn-default pull-right">
            </form>
        </div>
    </div>
    View Code

    详细可参考:http://www.liujiangblog.com/course/django/156

    或有关BaseModelform的相关参数可参考:https://blog.csdn.net/russell_tao/article/details/52777302

  • 相关阅读:
    关于“每日代码系列”以及后续计划
    每日代码系列(22)
    每日代码系列(21)
    mvcc
    父进程是1号进程产生大量的僵尸进程的解决方案
    nginx学习之路
    Zookeeper Curator 分布式锁
    jvm垃圾收集器汇总
    MySql分库分表以及相关问题
    Https交互原理
  • 原文地址:https://www.cnblogs.com/Mixtea/p/10492752.html
Copyright © 2011-2022 走看看