本篇文章为大家展示了表单Form对象的使用及如何构建复杂的QuerySet,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

员工经过长期磨合与沉淀,具备了协作精神,得以通过团队的力量开发出优质的产品。创新互联坚持“专注、创新、易用”的产品理念,因为“专注所以专业、创新互联网站所以易用所以简单”。公司专注于为企业提供成都网站设计、成都网站建设、微信公众号开发、电商网站开发,小程序设计,软件按需定制网站等一站式互联网企业服务。
一、利用Django创建表单
Django包含两个基类可构建表单,如下所示:
Form可构建标准的表单
ModelForm可构建与模型实例相关联的表单
1. 标准表单Form
首先在应用程序目录中创建 forms.py 文件,代码如下:
from django import forms class EmailPostForm(forms.Form): name = forms.CharField(max_length=25) email = forms.EmailField() to = forms.EmailField() comments = forms.CharField(required=False, widget=forms.Textarea)
CharField该字段类型显示为widget为字段所使用的插件,在comments字段中使用了Textarea插件EmailField需要使用有效的电子邮件地址;否则,字段验证将抛出forms.ValidationError异常required表示该字段是否必填项
有效的表单字段列表请参照:点击此处
接下来在 views.py 中使用 Form表单对象
from .forms import EmailPostForm
def post_share(request, post_id):
post = get_object_or_404(Post, id=post_id, status='published')
if request.method == 'POST':
form = EmailPostForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
# ...
else:
form = EmailPostForm()
return render(request, 'blog/post/share.html', {'post': post, 'form': form})上述视图工作方式如下:
定义了
post_share视图,并接收request对象和post_id变量作为参数采用
get_object_or_404快捷方式,并通过 ID 检索帖子,以确保检索的状态为published根据
request.method == 'POST'方法区分POST请求还是GET请求
表单处理流程如下:
当视图为 GET请求时,创建一个新的
form实例,并用于显示模板中的空表单:form = EmailPostForm()当为 POST请求时,通过包含于
request.POST中的提交数据生成一个表单实例:form = EmailPostForm(request.POST)利用表单
is_valid()方法验证所提交的数据。如果作一字段包含了无效数据,将返回False。通过访问form.errors可查看验证错误列表若表单正确,通过访问
form.cleaned_data将对验证后的数据进行检索。该属性表示为表单字段及其对应值的字典。
最后在HTML模板中使用 Form 对象:
{% extends "blog/base.html" %}
{% block title %}Share a post{% endblock %}
{% block content %}
{% if sent %}
E-mail successfully sent
"{{ post.title }}" was successfully sent to {{ form.cleaned_data.to }}.
{% else %}
Share "{{ post.title }}" by e-mail
{% endif %}
{% endblock %}此处通知Django利用 as_p 方法将字段显示为 中的字段。除此之外,还可利用 as_ul 作为无序列表显示表单;或者利用 as_table 作为表予以显示。如果需要显示每个字段,可遍历相关字段,如下所示:
{% for field in form%}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% endfor %}2. 模型表单ModelForm
首先创建用于评论帖子的模型:
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
class Meta:
ordering = ('created',)
def __str__(self):
return 'Comment by {} on {}'.format(self.name, self.post)ForeignKey以外键关联帖子related_name可对对应关系表进行跨表查询。定义完毕后,可通过comment.post检索评论对象的帖子,也可采用post.comments.all()检索某个帖子的全部评论;如果没有定义该值,Django将使用模型名称_set(如 comment_set )这一形式命名相关的对象管理器
关于多对一关系,可点击此处了解更多内容
接着创建模型中的表单,编辑 应用程序 目录下的 forms.py 文件,添加如下代码:
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'email', 'body')model指定使用哪一个模型创建表单fields显式地通知当前框架希望在表单中包含哪些字段;或者采用exclude定义希望排除的字段。
然后在视图View中使用ModelForms,修改 views.py 文件的 post_detail() 方法如下:
from .models import Post, Comment
from .forms import EmailPostForm, CommentForm
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post, status='published', publish__year=year, publish__month=month,
publish__day=day)
# 通过post对象查找关联的comment对象
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.save()
else:
comment_form = CommentForm()
return render(request, 'blog/post/detail.html',
{'post': post, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form})comments = post.comments.filter(active=True)使用了 post_detail 视图显示帖子及其评论内容,并针对该帖子加入了QuerySet以过滤检索评论new_comment = comment_form.save(commit=False)创建表单所链接的模型实例。如果采用commit=False则会创建模型实例,但不会将其保存至数据库中new_comment.post = post修改ModelForms的属性值new_comment.save()保存至数据库中
最后在HTML模板中显示:
{% with comments.count as total_comments %}
{{ total_comments }} comment{{ total_comments|pluralize }}
{% endwith %}
{% for comment in comments %}
Comment {{ forloop.counter }} by {{ comment.name }}
{{ comment.created }}
{{ comment.body|linebreaks }}
{% empty %}
There are no comments yet.
{% endfor %}
{% if new_comment %}
Your comment has been added.
{% else %}
Add a new comment
{% endif %}{% with %}标签可将某个值赋予可用的新变量中,直到遇到{% endwith %}标签。pluralize过滤器将返回包含字母 s 的复数字符串形式。
二、使用 django-taggit 添加标签功能
Django-taggit 源码地址
1. 安装django-taggit
pip/pipenv install django_taggit
2. 在 settings.py 文件中注册 taggia
INSTALLED_APPS = [ ... 'taggit', ]
3. 将 djnago-taggit 提供的 TaggableManager 管理器添加到需要使用 tag 的模型中
from taggit.managers import TaggableManager class Post(models.Model): ... tags = TaggableManager()
4. 生成数据库迁移
python manage.py makemigrations blog(应用名称) python manage.py migrate
迁移完成后,运行服务器,可以 Django管理页面中管理所有 标签(tags)
5. 在shell中考察如何使用tags管理器
>>> from blog.models import Post
>>> post = Post.objects.get(id=1)
>>> post.tags.add('music', 'jazz', 'django')
>>> post.tags.all()
, , ]>
>>> post.tags.remove('django')
>>> post.tags.all()
, ]> 6. 在HTML模板中显示 Tags
Tags: {{ post.tags.all|join:", " }}
join模板过滤器类似于字符串的join()方法,并添加包含指定字符串到相关元素中。
7. 在视图Views中使用 Tags
修改 应用程序目录的 views.py 文件,代码如下:
from taggit.models import Tag
def post_list(request, tag_slug=None):
object_list = Post.published.all()
tag = None
if tag_slug:
tag = get_object_or_404(Tag, slug=tag_slug)
object_list = object_list.filter(tags__in=[tag])
paginator = Paginator(object_list, 3) # 每页3条记录
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
# 如为无效页码则跳转到第1页
posts = paginator.page(1)
except EmptyPage:
# 如果页数超出范围则跳转到最后一页
posts = paginator.page(paginator.num_pages)
return render(request, 'blog/post/list.html', {'posts': posts, 'page': page, 'tag': tag})post_list接收可选的tag_slug参数,默认值为None并包含于URL中在构建初始的QuerySet、检索发布的全部帖子,如果存在标签slug,将通过
get_object_or_404()获得 Tag 对象随后,通过slug过滤帖子列表。
最后调整视图下方的
render()函数,将tag变量会至HTML模板中。
添加额外的URL路径,通过标签列出帖子:
path('tag//', views.post_list, name='post_list_by_tag'), 前端面HTML模板代码修改如下:
{% extends "blog/base.html" %}
{% block title %}My Blog{% endblock %}
{% block content %}
My Blog
{% if tag %}
Posts tagged with "{{ tag.name }}"
{% endif %}
{% for post in posts %}
{{ post.title }}
Tags:
{% for tag in post.tags.all %}
{{ tag.name }}
{% if not forloop.last %}, {% endif %}
{% endfor %}
Published {{ post.publish }} by {{ post.author }}
{{ post.body|truncatewords:30|linebreaks }}
{% include 'pagination.html' with page=posts %}
{% endfor %}
{% endblock %}{% url "blog:post_list_by_tag" tag.slug %}使URL名称以及slug标签作为其参数
三、构建复杂的QuerySet
我们将在 post_detail 视图中构建复杂的QuerySet,修改 应用程序目录下的 views.py 文件,添加如下代码:
from django.db.models import Count
Count为Django ORM中的Count聚合函数,其它聚合函数可访问如下地址
在 render() 之前,在 post_detail 视图中添加下列代码:
post_tag_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tag_ids).exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags', '-publish')[:4]
return render(request, 'blog/post/detail.html',
{'post': post, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form,
'similar_posts': similar_posts})上述代码执行下列操作:
针对当前帖子的标签,标签Python ID列表。
values_list()返回包含指定字段的元组。将flat=True传入,可获得形如[1,2,3,...]的列表。获取包含此类标签的全部帖子,并排除当前帖子本身。
使用
Count函数生成一个计算后的字段,即same_tags。该字段包含了与所有查询标签所共有的标签号通过标签号和发布日期对结果进行排序。此处仅检索前4个帖子。
将
similar_posts放入上下文字典中。
最后,在HTML模板中显示:
Similar posts
{% for post in similar_posts %} {% empty %} There are no similar posts yet. {% endfor %}
至此,可向用户推荐标签相似的帖子的功能。
上述内容就是表单Form对象的使用及如何构建复杂的QuerySet,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注创新互联行业资讯频道。
分享名称:表单Form对象的使用及如何构建复杂的QuerySet
文章路径:http://www.jxjierui.cn/article/gcohed.html


咨询
建站咨询
