Form
Django 提供了两种不同的Form:
- ModelForm: 可以直接根据Model生成Form
- Form: 自定义Form
ModelForm
示例:1
2
3
4
5
6from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'email', 'body')
ModelForm在View中可以直接保存,不用经过转化为Model的步骤。1
2
3
4
5
6
7def post_detail(request):
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
form.save()
# comment = form.save(commit=False)
# comment.save()
Form
示例:1
2
3
4
5
6
7from 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)
每个Field都有一个默认的widget,CharField默认的render为<input type="text">
,comment
制定了Textarea,则会被render为textarea。
在view中用form接收post或get方法如下:1
2
3
4
5
6
7
8
9
10
11
12def post_share(request, post_id):
post = get_object_or_404(Post, id=post_id)
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})
发送邮件
发送邮件需要现在项目的settings.py里定义email的设置,以QQ邮箱的配置为例:1
2
3
4
5
6# Email
EMAIL_HOST = 'smtp.qq.com'
EMAIL_HOST_USER = 'yarving@qq.com'
EMAIL_HOST_PASSWORD = 'secret-key'
EMAIL_PORT = 465
EMAIL_USE_SSL = True
发送邮件的代码:1
2
3from django.core.mail import send_mail
send_mail('subject', 'email body', 'sender@email.com', ['reciver-address@email.com'], fail_silently=False)
拼凑完整URL
Django的request.build_absolute_uri()
方法可以拼凑出完整的url,包含http schema和hostname。
示例:1
2
3def post_share(request, post_id):
# ...
psot_url = request.build_absolute_uri(post.get_absolute_url())
在model中reverse url的示例:1
2
3
4
5
6
7from django.core.urlresolvers import reverse
from django.db import models
class Post(models.Model):
# ...
def get_absolute_url(self):
return reverse('blog:post_detail', args=[self.publish.year, self.publish.slug])
Template filters
pluralize
用法如下,在模板文件中:1
{{ total | pluralize }}
- 当total为1时,后面不加任何东西
- 当total为0或者比1大时,后面加一个s
forloop
forloop
要放在模板的for语句中,有下列函数可以使用
counter和empty
用法如下,在模板文件中:1
2
3
4
5{% for comment in comments %}
{{ forloop.counter }} by {{ comment.name }}
{% empty %}
<p>Display some content when no content in for loop</p>
{% endfor %}
forloop.counter
会显示循环的序号,从1开始empty
表示如果for语句中的comments
为空的时候,显示下面的内容
last
如:1
2
3{% for tag in post.tags.all %}
{% if not forloop.last %}, {% endif %}
{% endfor %}
join
示例1
{{ post.tags.all | join: ", "}}
将post的所有tag都用,
连接成字符串
Taggit
当要为django搭建的博客的博文创建tag时,可以用django-taggit来实现
- 安装:
pip install django-taggit
- 添加到settings.py的
INSTALLED_APPS
里
添加进model1
2
3
4
5from taggit.managers import TaggableManager
class Post(models.Model):
# ...
tags = TaggableManager()
可以进行如下操作:1
2
3post.tags.add('music', 'jazz', 'django')
post.tags.all()
post.tags.remove('music')
Queryset
values_list()
函数原型:values_list(*fields, flat=False, named=False)
可以将值传递为列表,示例用法如下:1
2psot_tags_ids = post.tags.values_list('id', flat=True)
# return flat list like [1, 2, 3, 4]
annotate
示例1
posts.annotate(same_tags=Count('tags')).order_by('-same_tags', '-publish')[:4]
用QuerySet查询集的方式一直比较低端,只会使用filter/Q函数/exclude等方式来查询,数据量比较小的时候还可以,但是如果数据量很大,而且查询比较复杂,那么如果还是使用多个filter进行查询效率就会很低。
提高查询数据库效率的方案有两种:
第一种,是使用原生的SQL语句来进行查询,这样的优点在于能够完全按照开发者的意图来执行,效率会很高,但是缺点也很明显:
- 开发者需要非常熟悉SQL语句,加大开发者的工作量,同时,夹杂着SQL的项目也不利于以后程序的维护,增大程序的耦合度。
- 若查询条件是动态变化的,则会使开发变得更加困难。
django为了解决这一难题,提供了aggregate(聚合函数)和annotate(在aggregate的基础上进行GROUP BY操作)。