Django - ModelForm

一、原生form

https://www.cnblogs.com/yuanchenqi/articles/7614921.html

案例:

步骤:

1.models.py ...
makemigrations
migrate
from django.db import models

# Create your models here.

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)  # 999999.99
    date = models.DateField()
    publish = models.ForeignKey("Publish",on_delete=models.CASCADE)
    authors = models.ManyToManyField("Author")

    def __str__(self):
        return self.title

class Publish(models.Model):
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name
models.py

2.admin.py
from django.contrib import admin

# Register your models here.

from .models import *

admin.site.register(Book)
admin.site.register(Publish)
admin.site.register(Author)
admin.py

3.createsuperuser
yuan yuan1234

1.addbook:(getlist)
...
publish_id = request.POST.get('publish_id')
auhtor_pk_list = request.POST.getlist('auhtor_pk_list') # ['1', '2']
book_obj = Book.objects.create(title=title,price=price,date=date,publish_id=publish_id)
book_obj.authors.add(*auhtor_pk_list)

2.editbook:(set)
...
<p>价格 <input type="text" name="price" value="{{ edit_book.price }}"></p>
{% if author in edit_book.authors.all %}
<option selected value="{{ author.pk }}">{{ author.name }}</option>
{% else %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endif %}

...
ret = Book.objects.filter(pk=edit_book_id).update(title=title, price=price, date=date, publish_id=publish_id)
print('ret---', ret) # 1

book_obj = Book.objects.filter(pk=edit_book_id).first()
print('book_obj---', book_obj) # 对象

book_obj.authors.set(auhtor_pk_list)

4.code
from django.contrib import admin
from django.urls import path,re_path

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),

    path('books/', views.books),
    path('book/add/', views.addbook),
    re_path('book/edit/(\d+)', views.editbook),

]
urls.py
from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

from .models import *

def books(request):
    book_list = Book.objects.all()

    return render(request,'books.html',locals())

def addbook(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        price = request.POST.get('price')
        date = request.POST.get('date')
        publish_id = request.POST.get('publish_id')
        auhtor_pk_list = request.POST.getlist('auhtor_pk_list')  # ['1', '2']

        print(auhtor_pk_list)

        book_obj = Book.objects.create(title=title,price=price,date=date,publish_id=publish_id)
        book_obj.authors.add(*auhtor_pk_list)

        return redirect('/books/')

    publish_list = Publish.objects.all()
    author_list= Author.objects.all()

    return render(request,'add.html',locals())


def editbook(request, edit_book_id):
    if request.method == 'POST':
        title = request.POST.get('title')
        price = request.POST.get('price')
        date = request.POST.get('date')
        publish_id = request.POST.get('publish_id')
        auhtor_pk_list = request.POST.getlist('auhtor_pk_list')  # ['1', '2']

        print(auhtor_pk_list)

        ret = Book.objects.filter(pk=edit_book_id).update(title=title, price=price, date=date, publish_id=publish_id)
        print('ret---', ret)  # 1

        book_obj = Book.objects.filter(pk=edit_book_id).first()
        print('book_obj---', book_obj)  # 对象

        book_obj.authors.set(auhtor_pk_list)

        return redirect('/books/')

    edit_book = Book.objects.filter(pk=edit_book_id).first()
    publish_list = Publish.objects.all()
    author_list = Author.objects.all()

    return render(request, 'edit.html', locals())
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>books</title>
</head>
<body>

<a href="/book/add/"><button>添加书籍</button></a>
<hr>

<table border="1">
    {% for book in book_list %}
        <tr>
            <td>{{ book.title }}</td>
            <td>{{ book.price }}</td>
            <td>{{ book.date|date:'Y-m-d' }}</td>
            <td>{{ book.publish.name}}</td>
            <td>
                {% for author in book.authors.all %}
                {{ author.name }}
                {% endfor %}

            </td>
            <td><a href="/book/edit/{{ book.pk }}">编辑</a></td>


        </tr>
    {% endfor %}

</table>


</body>
</html>
books.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>添加页面</h3>

<form action="" method="post">
    {% csrf_token %}
    <p>书籍名称 <input type="text" name="title"></p>
    <p>价格 <input type="text" name="price"></p>
    <p>日期 <input type="date" name="date"></p>
    <p>出版社
        <select name="publish_id" id="">
            {% for publish in publish_list %}
                <option value="{{ publish.pk }}">{{ publish.name }}</option>
            {% endfor %}
        </select>
    </p>
    <p>作者
        <select name="auhtor_pk_list" id="" multiple>
            {% for author in author_list %}
                <option value="{{ author.pk }}">{{ author.name }}</option>
            {% endfor %}
        </select>
    </p>
    <input type="submit">
</form>

</body>
</html>
add.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>编辑页面</h3>

<form action="" method="post">
    {% csrf_token %}
    <p>书籍名称 <input type="text" name="title" value="{{ edit_book.title}}"></p>
    <p>价格 <input type="text" name="price" value="{{ edit_book.price }}"></p>
    <p>日期 <input type="date" name="date" value="{{ edit_book.date|date:'Y-m-d' }}"></p>
    <p>出版社
        <select name="publish_id" id="">
            {% for publish in publish_list %}

                {% if edit_book.publish == publish %}
                    <option selected value="{{ publish.pk }}">{{ publish.name }}</option>
                {% else %}
                    <option value="{{ publish.pk }}">{{ publish.name }}</option>
                {% endif %}

            {% endfor %}
        </select>
    </p>
    <p>作者
        <select name="auhtor_pk_list" id="" multiple>
            {% for author in author_list %}

                {% if author in edit_book.authors.all %}
                    <option selected value="{{ author.pk }}">{{ author.name }}</option>
                {% else %}
                    <option value="{{ author.pk }}">{{ author.name }}</option>
                {% endif %}

            {% endfor %}
        </select>
    </p>
    <input type="submit">
</form>

</body>
</html>
edit.html

二、form组件

https://www.cnblogs.com/yuanchenqi/articles/7614921.html
https://www.cnblogs.com/wupeiqi/articles/6144178.html


针对form表单设计form组件
  ChoiceField(Field)
  ModelChoiceField(ChoiceField)
  ModelMultipleChoiceField(ModelChoiceField)

添加,编辑,用form组件!

from django import forms
from django.forms import widgets

class BookForm(forms.Form):
title = forms.CharField(max_length=32,label='书籍名称',
error_messages={'required':'不能为空'},
)
price = forms.DecimalField(max_digits=8,decimal_places=2,label='价格')
date = forms.DateField(label='日期',
widget=widgets.TextInput(attrs={'type':'date'})
)
# gender = forms.ChoiceField(choices=((1,'男'),(2,'女'),(3,'其他'))) # 与sql没关系
# publish = forms.ChoiceField(choices=Publish.objects.all().values_list('pk','name'))
publish = forms.ModelChoiceField(queryset=Publish.objects.all(),label='出版社')
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all(),label='作者')
    

 

注意点:

1.
  book_obj = Book.objects.create(title=title,price=price,date=date,publish=publish)
  book_obj.authors.add(*authors)

2.
  edit_book = Book.objects.filter(pk=edit_book_id).first()
  form = BookForm(initial={"title":edit_book.title,"price":edit_book.price,
  "date":edit_book.date,"publish":edit_book.publish,
   'authors':edit_book.authors.all()})
3.
  Book.objects.filter(pk=edit_book_id).update(title=title, price=price, date=date, publish=publish)
  book_obj = Book.objects.filter(pk=edit_book_id).first()
  book_obj.authors.set(authors)

4.
  <form action="" method="post" novalidate>
  {% csrf_token %}
   {% for field in form %}
   <div>
   {{ field.label }}
   {{ field }}
   {{ field.errors.0 }}
   </div>
  {% endfor %}

  <input type="submit">
  </form>

form组件能做的事情:

1.能渲染页面
2.能做校验用
3.拿到错误信息显示
from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

from .models import *

from django import forms
from django.forms import widgets

class BookForm(forms.Form):
    title = forms.CharField(max_length=32,label='书籍名称',
        error_messages={'required':'不能为空'},
    )
    price = forms.DecimalField(max_digits=8,decimal_places=2,label='价格')
    date = forms.DateField(label='日期',
        widget=widgets.TextInput(attrs={'type':'date'})
    )
    # gender = forms.ChoiceField(choices=((1,'男'),(2,'女'),(3,'其他')))
    # publish = forms.ChoiceField(choices=Publish.objects.all().values_list('pk','name'))
    publish = forms.ModelChoiceField(queryset=Publish.objects.all(),label='出版社')
    authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all(),label='作者')


def books(request):
    book_list = Book.objects.all()

    return render(request,'books.html',locals())

def addbook(request):
    form = BookForm()
    if request.method == 'POST':
        form = BookForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data)
            """
            clean_date: {'title': '书1', 'price': Decimal('1111'),
                 'date': datetime.date(2018, 6, 7), 
                 'publish': <Publish: 香蕉出版社>,   # 对象 
                  'authors': <QuerySet [<Author: alex>, <Author: egon>]>}

            """
            title = form.cleaned_data.get('title')
            price = form.cleaned_data.get('price')
            date = form.cleaned_data.get('date')
            publish = form.cleaned_data.get('publish')
            authors = form.cleaned_data.get('authors')

            book_obj = Book.objects.create(title=title,price=price,date=date,publish=publish)
            book_obj.authors.add(*authors)

            return redirect('/books/')

    return render(request,'add.html',locals())


def editbook(request, edit_book_id):
    edit_book = Book.objects.filter(pk=edit_book_id).first()
    form = BookForm(initial={"title":edit_book.title,"price":edit_book.price,
                             "date":edit_book.date,"publish":edit_book.publish,
                             'authors':edit_book.authors.all()})

    if request.method == 'POST':
        form = BookForm(request.POST)
        if form.is_valid():
            title = form.cleaned_data.get('title')
            price = form.cleaned_data.get('price')
            date = form.cleaned_data.get('date')
            publish = form.cleaned_data.get('publish')
            authors = form.cleaned_data.get('authors')

            Book.objects.filter(pk=edit_book_id).update(title=title, price=price, date=date, publish=publish)

            book_obj = Book.objects.filter(pk=edit_book_id).first()
            book_obj.authors.set(authors)

            return redirect('/books/')

    return render(request, 'edit.html', locals())
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>添加页面</h3>

<form action="" method="post" novalidate>
    {% csrf_token %}
    {% for field in form %}
        <div>
            {{ field.label }}
            {{ field }}
            {{ field.errors.0 }}
        </div>
    {% endfor %}

    <input type="submit">
</form>

</body>
</html>

-------------------------------------

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>编辑页面</h3>

<form action="" method="post" novalidate>
    {% csrf_token %}
    {% for field in form %}
        <div>
            {{ field.label  }}
            {{ field }}
            {{ field.errors.0 }}
        </div>
    {% endfor %}

    <input type="submit">
</form>

</body>
</html>
add.html / edit.html

三、modelform

 

https://www.cnblogs.com/yuanchenqi/articles/7614921.html
https://www.cnblogs.com/yuanchenqi/articles/8034442.html

注意点:
1.modelform 组件
中间转换的组件, 不用自己去写form组件。
将模型表转换成, 具体的form组件。

2.fields
class BookForm(ModelForm):
class Meta:
model = Book
fields = "__all__" # 对所有字段转换
# fields = ['title','price']

3.一对多,多对多,不用考虑!
form = BookForm(request.POST)
if form.is_valid():
form.save()
return redirect('/books/')

4.BookForm(instance=edit_book) # 接收一个对象
form = BookForm(request.POST,instance=edit_book)
if form.is_valid():
form.save()
return redirect('/books/')

5.create、update
form = BookForm(request.POST) # create
if form.is_valid():
form.save() # form.model.objects.create(request.POST)

form = BookForm(request.POST,instance=edit_book) # update
if form.is_valid():
form.save() # edit_book.update(request.POST)

6.{% include 'form.html' %}
form.html:
<form action="" method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.label }}
{{ field }}
<small><span class="pull-right text-danger has-error">{{ field.errors.0 }}</span></small>
</div>
{% endfor %}

<input type="submit">
</form>

7.models.py
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2) # 999999.99
date = models.DateField()
publish = models.ForeignKey("Publish",on_delete=models.CASCADE)
authors = models.ManyToManyField("Author")

models.CharFiled()
models.EmailField() # 为什么,不写charField? 因为在使用 modelForm 时,可以校验!!这时EmailField才有意义!
eg:
models.URLField
models.UUIDField

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

from .models import *

from django.forms import ModelForm
from django.forms import widgets as wid  # 因为重名,所以起个别名!

wid_text = wid.TextInput(attrs={'class':'form-control'})
required_msg = {'required':'不能为空'}
class BookForm(ModelForm):
    class Meta:
        model = Book
        fields = "__all__"  # 对所有字段转换
        # fields = ['title','price']

        labels = {"title":"书籍名称","price":"价格","date":"日期","publish":"出版社","authors":"作者"}
        widgets = {
            'title':wid_text,
            'price':wid_text,
            'date':wid.TextInput(attrs={'class':'form-control','type':'date'}),
            'publish':wid.Select(attrs={'class':'form-control'}),
            'authors':wid.SelectMultiple(attrs={'class':'form-control'})
        }
        error_messages = {
            'title':required_msg,
            'price':required_msg,
            'date':{'required':'不能为空','invalid':'格式错误'},
            'publish':required_msg,
            'authors':required_msg,
        }

def books(request):
    book_list = Book.objects.all()

    return render(request,'books.html',locals())

def addbook(request):
    form = BookForm()
    if request.method == 'POST':
        form = BookForm(request.POST)
        if form.is_valid():
            form.save()  # form.model.objects.create(request.POST)
            return redirect('/books/')

    return render(request,'add.html',locals())


def editbook(request, edit_book_id):
    edit_book = Book.objects.filter(pk=edit_book_id).first()
    form = BookForm(instance=edit_book)

    if request.method == 'POST':
        form = BookForm(request.POST,instance=edit_book)
        if form.is_valid():
            form.save()   # edit_book.update(request.POST)
            return redirect('/books/')

    return render(request, 'edit.html', locals())

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
     <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

</head>
<body>
<h3>添加页面</h3>

<div class="row">
    <div class="col-md-4 col-md-offset-1">
        {% include 'form.html' %}
    </div>
</div>

</body>
</html>
add.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
     <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

</head>
<body>
<h3>编辑页面</h3>

<div class="row">
    <div class="col-md-4 col-md-offset-1">
        {% include 'form.html' %}
    </div>
</div>

</body>
</html>
edit.html

 

form.html

<form action="" method="post" novalidate>
    {% csrf_token %}
    {% for field in form %}
        <div class="form-group">
            {{ field.label }}
            {{ field }}
            <small><span class="pull-right text-danger has-error">{{ field.errors.0 }}</span></small>
        </div>
    {% endfor %}

    <input type="submit">
</form>

 

from django.shortcuts import render,HttpResponse,redirect
from django.forms import ModelForm
# Create your views here.
from app01 import models
def test(request):
    # model_form = models.Student
    model_form = models.Student.objects.all()
    return render(request,'test.html',{'model_form':model_form})

class StudentList(ModelForm):
    class Meta:
        model = models.Student #对应的Model中的类
        fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段
        exclude = None #排除的字段
        labels = None #提示信息
        help_texts = None #帮助提示信息
        widgets = None #自定义插件
        error_messages = None #自定义错误信息
        #error_messages用法:
        error_messages = {
        'name':{'required':"用户名不能为空",},
        'age':{'required':"年龄不能为空",},
        }
        #widgets用法,比如把输入用户名的input框给为Textarea
        #首先得导入模块
        from django.forms import widgets as wid #因为重名,所以起个别名
        widgets = {
        "name":wid.Textarea
        }
        #labels,自定义在前端显示的名字
        labels= {
        "name":"用户名"
        }
def student(request):
    if request.method == 'GET':
        student_list = StudentList()
        return render(request,'student.html',{'student_list':student_list})
    else:
        student_list = StudentList(request.POST)
        if student_list.is_valid():
            student_list.save()
            return render(request,'student.html',{'student_list':student_list})

def student_edit(request,pk):
    obj = models.Student.objects.filter(pk=pk).first()
    if not obj:
        return redirect('test')
    if request.method == "GET":
        student_list = StudentList(instance=obj)
        return render(request,'student_edit.html',{'student_list':student_list})
    else:
        student_list = StudentList(request.POST,instance=obj)
        if student_list.is_valid():
            student_list.save()
            return render(request,'student_edit.html',{'student_list':student_list})
扩展 modelform

https://www.cnblogs.com/yuanchenqi/articles/8034442.html

四、前端form表单,后台form组件

前端手写一个form表单,后台使用form组件,进行校验,也是可以的!!

注意: <p>名称 <input type="text" name="title"></p>  和   title = forms.CharField()

views.py

from django import forms

class BookForms(forms.Form):
    title = forms.CharField()
    price = forms.FloatField()


def addbook(request):
    form = BookForms()
    if request.method == 'POST':
        form = BookForms(request.POST)
        # form = BookForm({'title':'php','price':111,'xxx':'egon'})
        if form.is_valid():
            print('clean_data',form.cleaned_data)
            # clean_data {'title': '水浒传', 'price': 123.0}
        else:
            print('error',form.errors)

    return render(request,'addbook.html',locals())

 

addbook.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h3>添加书籍</h3>

<form action="" method="post" novalidate>
    {% csrf_token %}
    <p>名称 <input type="text" name="title"></p>
    <p>价格 <input type="text" name="price"></p>
    <p>xxx <input type="text" name="xxx"></p>

    <input type="submit">
</form>

<form action="" method="post" novalidate>
    {% csrf_token %}
    {{ form.as_p }}
    {{ form.as_table }}
    {{ form.as_ul }}
    <input type="submit">
</form>

</body>
</html>

五、补充 - 请求流程

 

说明:

django 请求流程图--流程最重要

http协议
请求协议:请求首行,请求头,请求体!
响应协议: 响应首行,响应头,响应体!

我们发给浏览器的响应体(html)是一堆 str 浏览器解析(html)才能看到数据!

render 对templates 模板渲染
没有模板 就 httpresponse 返回str
打开文件 捕获是否模板语法,嵌入{{}} 数据 返回 html(str) response

只要到了 中间件 交给浏览器的 一定已经是一些 html(str)
posted @ 2018-06-14 16:04  Alice的小屋  阅读(265)  评论(0编辑  收藏  举报