一、modelform的用处
ModelForm可以将Model与Form进行绑定,Form有自动生成表单的作用,但是每一个forms字段需要自己手动填写,而Model就是数据库表包含了所有的数据字段。所以ModelForm有着以下功能:
- Form所有的功能。
- 将Model字段自动转换成forms字段。
二、在界面上展示input标签。
1、新建forms.py文件,并键入以下代码:
from django import forms from .models import Question, Choice class ChoiceForm(forms.ModelForm): choice_text = forms.CharField( label="你的答案", # 自定义在前端显示的名字 max_length=200, # 指定输入长度 help_text='最大长度为200', # 提示帮助信息 widget=forms.TextInput( # 指定输入类型 attrs={ 'placeholder': "请说出你的答案", # 自定义input的属性 "class": 'form-control' } ) ) class Meta: model = Choice # model类 fields = ['choice_text'] # 字段名,如果是__all__,就是表示列出所有的字段
2、在view.py文件中引用
from .forms import ChoiceForm def reply(request, question_id): try: if request.method == "GET": form = ChoiceForm() return render(request, 'bbs/detail.html', { 'form': forms })
3、只需要在前端的页面把{{ form.as_p }} 进行引用即可
效果如下:
三、前后端交互,数据存储到后台。
此时,在界面上input框上键入值后点提交,后台还没能收到数据并存储,还需要以下的操作。
1、键入提交后的指定发送到那个函数上进行存储。
<form action="{% url 'bbs:reply' question.id %}" method="post"> # 指明提交到那个函数 {% csrf_token %} {{ form.as_p }} <input type="submit" value="提交"> </form>
2、编辑view.py reply函数。
if request.method == 'POST': form = ChoiceForm(request.POST) # 获取提交数据的对象 print('form:', form) if form.is_valid(): # 校对数据是否合法,比如是否为空之类的额 reply = form.save(commit=False) # 提交数据,该数据是写入input的值,但不写入数据库 print('reply: ', reply, type(reply)) reply.question = question # 绑定到一个问题,因为这里的表引用了外键question,因此需要绑定。 reply.save() # 写入数据库 return HttpResponseRedirect(reverse('bbs:detail', args=(question.id,)))
四、上传图片操作
编辑form.py文件,在原来的基础上新增上传文件的配置:
from django import forms from .models import Question, Choice class ChoiceForm(forms.ModelForm): choice_text = forms.CharField( label="你的答案", max_length=200, help_text='最大长度为200', widget=forms.TextInput( attrs={ 'placeholder': "请说出你的答案", "class": 'form-control' } ) ) picture = forms.FileField( # 指定输入信息的配型,上传文件为FileField,文本为CharField类型 label="添加图片(可选)", help_text='可以上传的格式: jpg, png', required = False, # 是否为必填选项,默认为True. widget=forms.FileInput( attrs={ "class": 'form-control' } ) ) class Meta: model = Choice # model类 fields = ['choice_text', 'picture'] # 字段名,如果是__all__,就是表示列出所有的字段
接下来的步骤和第二步骤的2、3步骤一样,{{ form.as_p }}会循环展示input标签,即你form里面设置了展示多少个标签,在界面上就会展示多个input输入框。
五、把图片存储到后台。
1、需要在项目的settings.py文件中添加图片的位置。
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
2、在项目的urls.py文件中指明media的url访问路径。
from django.contrib import admin from django.urls import path from django.urls import include from django.conf import settings # 导入以下两个模块 from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('polls/', include("polls.urls")), path('bbs/', include("bbs.urls")), ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # 把media路径添加进urlpattern路径中
3、修改上传文件并提交的指定函数:
if request.method == 'POST': form = ChoiceForm(request.POST, request.FILES) # equest.FILES 把文件传给ChoiceForm对象,由ChoiceForm进行处理 print('form:', form, request.FILES) if form.is_valid(): reply = form.save(commit=False) print('reply: ', reply, type(reply)) reply.question = question reply.save() return HttpResponseRedirect(reverse('bbs:detail', args=(question.id,)))
3、确保form标签含有enctype="multipart/form-data"属性,上传文件必须要带的属性,不然会上传失败。
六、让界面提交的函数在界面上展示。
需要在前端的页面引用这个picture字段:
{% if q.picture %} <img src="{{ obj.picture.url }}" alt="reply_img"> {% endif %}
七、修改前端input的样式。
如果需要修改input标签的要是,可以把input里面的标签都取出来,再通过css进行演示的修改。
{% for q in question.choice_set.all %} # 循环取出所有的input标签 <div class="media text-muted pt-3"> <p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray"> <strong class="d-block text-gray-dark">{{ q.author }}</strong> # 每个q对象里面包含了input的所有属性 {{ q.choice_text }} {% if c.picture %} <img src="{{ q.picture.url }}" alt="reply-image" class="reply-image"> {% endif %} </p> </div> {% endfor %}