一. 使用原生sql,了解即可
使用原生sql的目的:解决一些复杂的sql不能用ORM方式写出的问题
有三种方式如下
1. extra: 结果集修改器,一种提供额外查询参数的机制
2. raw:执行原始sql并返回模型实例
3. 直接执行自定义的SQL
前两种方式要依赖于model,第三种不依赖model
实例
使用extra来扩展查询条件
1. Book.objects.filter(publisher__name='广东人民出版社').extra(where=['price>50'])
也可以写成
Book.objects.filter(publisher__name='广东人民出版社',price__gt=50)
2. Book.objects.extra(select={'count':'select count(*) from hello_book'})
这里把select count(*) from hello_book做为一个整体,别名为count
使用raw方法来执行原始sql语句,最好用于查询
1. Book.objects.raw('select * from hello_book')
作用就是执行select * from hello_book,返回类型是RawQuerySet,可进行遍历
2. bbb=Book.objects.raw("insert into hello_author(name) value('lilei')")
直接执行自定义sql,这种方法最灵活
from django.db import connection
cursor = connection.cursor() #获得一个游标对象
插入操作
cursor.execute("insert into hello_author(name) value('阿里')")
更新
cursor.execute("update hello_author set name='韩寒' where name='郭敬明'")
删除
cursor.execute("delete from hello_author where name='韩寒'")
查询
cursor.execute('select * from hello_author')
raw=cursor.fetchone() #取出查询的结果,每次一个作者信息
cursor.fetchall() #取出所有的作者信息,以元组类型返回
需要注意的是当取到最后一条作者信息后,再用fetchall()取出的是空值,需要重新执行一下查询语句。
二. 常用模板标签及过滤器
1. 模板的组成:HTML代码+逻辑控制代码
2. 逻辑控制代码的组成
1)变量,使用大括号来引用变量,一般从views.py中传过来
{{ var_name }}
2)标签的使用
{% load staticfiles %}
3)过滤器(filter)的使用
{{ ship_date|date:"Fj,Y" }} ship_date变量传给date过滤器,date过滤器通过使用"Fj,Y"这几个参数来格式化日期数据。 “|”就是过滤符
3. 常用标签
{% with %} :在标签作用域中,用简单的变量名替代复杂变量名
{% url %}:引入路由配置的地址,如下
在urls.py中url(r' ^test/$', views.test, name='test')
在html文件中<form method='post' action="{% url 'test' %},其中的test为urls.py中的路由别名。模板中的url一般不写死
{% cycle %}:在循环时轮流使用给定的字符串列表中的值
{% load %}:加载标签库
{% csrf_token %}:生成csrf_token标签,用于防止跨站攻击验证,post表单中常用
{% autoescape %}:自动转义设置
{% now %}:获取当前时间
{% if %}:可以使用and, or, not 来组织逻辑,但不允许and,or同时出现在条件语句中,新版本中支持{% elif %}
{% for %}:用来循环一个list,还可以用reversed关键字进行倒序遍历,一般可以用if语句来判断一下列表是否为空,再进行遍历;还可以用empty关键字来进行为空时的跳转
<ul>
{% for athlete in athlete_list %}
<li>{{athlete}}</li>
{% empty %}
<li>sorry, no athlete </li>
{% endfor %}
</ul>
标签和过滤器完整介绍
4. 过滤器
我们一般都是通过变量来使用过滤器
{{ value1|uppper }} 把变量value1的字母大写
常用过滤器有
1. add:给变量加上相应值,进行加法运算{{ value2|add: "2" }}
2. addslashes:给变量中的引号前加上斜线
3. capfirst:首字母大写
4. cut:从字符串中删除指定的字符
5. date:格式化日期字符串
6. default: 如果值为False,就替换成设置的默认值,否则使用本来值
代表False的情况有空字符串,空列表,空字典,False字符串
7. default_if_none: 如果值为None,就替换成设置的默认值,否则使用本来值
8. escape:对字符串进行转义
9. filesizeformat: 格式化文件大小显示
10. first,last:返回列表的第一个,最后一个元素
11. length:返回列表长度
12. slice:切片操作,{{ some_list | slice:":2" }}
13. truncatechars: 按照字符截取字符串,后跟数字表示截取的长度
14. truncatewords:按照单词截取字符串,其实是按空格截取
15. striptags:过滤掉html标签,常用于安全处理
5. 模板的包含和继承
解决网页公用部分的冗余问题
1)包含
{% include %} 允许在模板中包含其他模板的内容
标签的参数可以是:模板名称,变量,字符串
{% include 'nav.html' %} #模板名称
{% include 'app/nav.html' %} #模板路径
{% include template_name %} #模板的变量,比较少用
比如在views.py中
from django.template import Template
def hello(request):
value9=Template("<a href='http://www.baidu.com' target='_blank'>百度</a>")
那么在html文件中就可以用变量来代替模板
{% include value9 %}
注意:
锚链接可以选用target属性控制点击链接时的行为,_blank是该属性可用值之一,点击链接时会告知浏览器打开一个新的窗口
可以在包含的时候传递变量,使用关键字with
比如在table.html中有如下代码
{% include 'app/nav.html' with hello='hello, Django' %}
然后在nav.html中写入如下代码即可
<p> {{ hello }} </p>
include标签官方说明
2)继承
模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点共用部分进行重载,主要用到2个相关标签 {% block %}, {% extends %}
定义块 ,就是共用部分
继承父模板
注意
1. 通常尽可能在父模板中用{% block %}来预留位置,子模板不必定义所有的父block,其实就是子块覆盖父块
2. 如果需要得到父模板的块内容,可用{{ block.super }}变量,当你需要给父块添加内容而不是取代它时,这个很有用
比如在父模板base.html中
<title>
{% block title %} my amazing site {% endblock %}
</title>
在子模板a.html中
{% extends "base.html" %}
{% block title %} {{ block.super }} - 我的第一个子网页{% endblock %}
这样子模板的标题输出为my amazing site - 我的第一个子网页
三. admin基本配置
django amdin是django自带的后台管理工具
1. ModelAdmin是管理界面的定制类,如需扩展特定的model界面需要从该类继承
2. 注册model类到admin的两种方法
1)使用register的方法
2)使用register的装饰器
3. 掌握一些常用的设置技巧
list_display:指定要显示的字段
search_fields:指定搜索的字段,后台会多一个搜索框
list_filter:指定列表过滤器, 后台页面右上边会多一部分FILTER内容
ordering:指定排序字段
fieldsexclude:指定编辑表单需要编辑不需要编辑的字段
fieldsets:设置分组表单
admin官方文档
例子:后台只会显示出版社的名字,如果想要显示出版社的其他信息,应该怎么做呢?
自定义一个类
from django.contrib import admin
from hello.models import *
@admin.register(Publisher) #使用装饰器来注册,效果和下面的register效果一样
class PublisherAdmin(admin.ModelAdmin):
list_display = ('name', 'address', 'city',)
search_fields = ('name', 'city',) #元组只有一个元素时,后面必须加逗号
list_filter = ('city',) #和search_fields效果相似,表现形式不同
orderding = ('-id',)
#fields = ('name', 'address',) #就是新增出版社时,能够编辑的属性
fieldsets = (
(None, {
'fields': ('name', 'address', )
}),
('Advanced options', {
'classes': ('collapse',),
'fields': ('city', 'website'),
}),
)
效果就是页面显示name, address可编辑,而city, website是属于高级选项,默认是隐藏的,需要自己点击show按钮才会展开显示
#admin.site.register(Publisher, PublisherAdmin) #使用register来注册model的方法
四. Django中的表单系统
django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm
表单系统主要分两种
1. 基于django.forms.Form: 所有表单类的父类
2. 基于django.forms.ModelForm: 可以和模型类绑定的Form
案例:实现添加出版社信息的功能
方法1. 用原生表单写
views.py中写
def add_publisher(request):
if request.method == 'POST':
name = request.POST['name']
address = request.POST.get('address') #这种方法和上面的等效
city= request.POST['city'] #中括号中的city为html文件中的name属性值
#使用create的方法写入数据库,其中等号右边是上面的变量,左边是数据库列名
Publisher.objects.create(
name = name,
address = address,
city = city,
)
return HttpResponse("添加出版社信息成功")
else:
return render(request, 'add_publisher.html', locals())
urls.py中
urlpattern = [
url(r' ^add_publisher/$', views.test, name='add_publisher'),
]
定义个模板add_publisher.html
<head>
<title>添加出版社信息</title>
</head>
<body>
<form action="{% url 'add_publisher' %}" method="post"> 其中add_publisher为url.py中的别名,使用了url标签
{% csrf_token %} 不加这个会报403错误
名称:<input type="text" name="name"><br>
地址:<input type="text" name="address"><br>
城市:<input type="text" name="city"><br>
<input type="submit" value="提交"><br>
</form>
方法2,使用django.forms.Form
1. 首先在app里新增一个forms.py文件
from django import forms
class PublisherForm(forms.Form)
name = forms.CharField(label="名称",error_message=("required":"这个项目必填") 用label定义属性后台显示信息,不加就显示为name
address = forms.CharField()
city = forms.CharField()
2. views.py中导入定义的forms文件
from hello.forms import PublisherForm
def add_publisher(request):
if request.method == 'POST':
publisher_form = PublisherForm(request, POST) #表单对象初始化,使对象里含有POST传入的值
if publisher_form.is_valid(): #验证表单数据是否合法,比如空数据
Publisher.objects.create(
name = publisher_form.cleaned_data['name'],
address = publisher_form.cleaned_data['address'],
city = publisher_form.cleaned_data['city'],
)
return HttpResponse("添加出版社信息成功")
else:
publisher_form = PublisherForm() 初始化一个表单对象,使模板能接收这个对象
return render(request, 'add_publisher.html', locals()) #验证没通过也需要渲染出来
3. add_publisher.html文件可改写为如下
<head>
<title>添加出版社信息</title>
</head>
<body>
<form action="{% url 'add_publisher' %}" method="post">
{% csrf_token %}
{{ publisher_form.as_p }} #可自动生成表单信息,as_p是每个表项标签为<p>
<input type="submit" value="提交"><br>
</form>
方法3,使用django.forms.ModelForm
1. forms.py
from django import forms
from hello.models import Publisher
class PublisherForm(forms.ModelForm)
class Meta:
model = Publisher #绑定Publisher类
exclude = ("id",) #排除id字段,其他都显示
2. views.py
from hello.forms import PublisherForm
def add_publisher(request):
if request.method == 'POST':
publisher_form = PublisherForm(request, POST)
if publisher_form.is_valid():
publisher_form.save() #插入数据用一条代码就搞定
return HttpResponse("添加出版社信息成功")
else:
publisher_form = PublisherForm()
return render(request, 'add_publisher.html', locals())
资料
五 .表单验证
Django提供了三种方式来验证表单
1. 表单字段的验证器
2. clean_filedname(filedname为字段名称),验证字段,针对某个字段进行验证
3. 表单clean方法,可针对整个表单进行验证
案例
自定义验证,不能插入重名的出版社名称
方法一. 表单字段验证器
forms.py文件中
from django import forms
from hello.models import Publisher
from django.core.exceptions import ValidationError
def validate_name(value): #这里的参数value相当于一个回调函数,放在哪个字段就给哪个字段值
try:
Publisher.objects.get(name=value)
raise ValidationError("%s的信息已经存在"%value)
except Publisher.DoesNotExist:
pass
class PublisherForm(forms.ModelForm)
#添加一个字段,如果和绑定的Publisher模块中的字段重名的话,就不会重复添加
name = forms.Charfield(lable="名称", validators=[validate_name])
class Meta:
model = Publisher #绑定Publisher类
exclude = ("id",) #排除id字段,其他都显示
方法二. 针对某个字段进行验证
forms.py文件中
from django import forms
from hello.models import Publisher
from django.core.exceptions import ValidationError
class PublisherForm(forms.ModelForm)
def clean_name(self):
value = self.cleaned_data.get('name') #定义个value值供下面的try语句中的value参数用
try:
Publisher.objects.get(name=value)
raise ValidationError("%s的信息已经存在"%value)
except Publisher.DoesNotExist:
pass
return value #在没有出错的情况下要返回value值,这是这种方法的特殊性
class Meta:
model = Publisher #绑定Publisher类
exclude = ("id",) #排除id字段,其他都显示
方法三. 表单clean方法,对整个表单进行验证
forms.py文件中
from django import forms
from hello.models import Publisher
from django.core.exceptions import ValidationError
class PublisherForm(forms.ModelForm)
def clean(self):
cleaned_data = super(PublisherForm, self).clean() #继承父类clean()
value = cleaned_data.get('name') #定义个value值供下面的try语句中的value参数用
try:
Publisher.objects.get(name=value)
self._errors['name']=self.error_class(["%s的信息已经存在"%value])
except Publisher.DoesNotExist:
pass
return cleaned_data #这里返回整个表
class Meta:
model = Publisher #绑定Publisher类
exclude = ("id",) #排除id字段,其他都显示