第四章 模板
1.标签
(1)if/else
{% if %} 标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系统会
显示在 {% if %} 和 {% endif %} 之间的任何内容,例如:
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% endif %}
{% else %} 标签是可选的:
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% else %} <p>Get back to work.</p> {% endif %}
{% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断 ,或者对变量取反( not )
(2)for
{% for %} 允许我们在一个序列上迭代。 与Python的 for 语句的情形类似,循环语法是 for X in Y ,Y是要迭代的序列而X是在每一个特定的循环中使用的变量名称。 每一次循环中,模板系统会渲染在 {% for %} 和
{% endfor %} 之间的所有内容。
例如,给定一个运动员列表 athlete_list 变量,我们可以使用下面的代码来显示这个列表:
<ul> {% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% endfor %} </ul>
给标签增加一个 reversed 使得该列表被反向迭代:
{% for athlete in athlete_list reversed %}
...
{% endfor %}
可以嵌套使用 {% for %} 标签:
{% for athlete in athlete_list %} <h1>{{ athlete.name }}</h1> <ul> {% for sport in athlete.sports_played %} <li>{{ sport }}</li> {% endfor %} </ul> {% endfor %}
Django不支持退出循环操作。 如果我们想退出循环,可以改变正在迭代的变量,让其仅仅包含需要迭代的项目。 同理,Django也不支持continue语句,我们无法让当前迭代操作跳回到循环头部。
在每个`` {% for %}``循环里有一个称为`` forloop`` 的模板变量。这个变量有一些提示循环进度信息的属性。
forloop.counter 总是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1。
例子:
def lists(request): lists = [1,2,3,4,5] return render(request,"lists.html",{'lists':lists})
{% for item in lists %} <p>{{ forloop.counter }}:{{ item }}</p> {% endfor %}
结果:
1:1
2:2
3:3
4:4
5:5
-->>forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。 第一次执行循环时这个变量会被设置为0。
-->>forloop.revcounter0 类似于 forloop.revcounter ,但它以0做为结束索引。 在第一次执行循环时,该变量会被置为序列的项的个数减1
forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为````
{% for item in lists %} {% if forloop.first %} <li style="color: red">{{ forloop.counter }}:{{ item }}</li> {% else %} <li>{{ forloop.counter }}:{{ item }}</li> {% endif %} {% endfor %}
结果:
forloop.last 是一个布尔值;在最后一次执行循环时被置为True。
forloop.parentloop 是一个指向当前循环的上一级循环的 forloop 对象的引用(在嵌套循环的情况下)。
2.注释
就像HTML或者Python,Django模板语言同样提供代码注释。 注释使用 {# #} :
{# This is a comment #}
如果要实现多行注释,可以使用`` {% comment %}`` 模板标签,就像这样:
{% comment %}
This is a
multi‐line comment.
{% endcomment %}
3.过滤器
模板过滤器是在变量被显示前修改它的值的一个简单方法。 过滤器使用管道字符,
{{ name|lower }} #它功能是转换文本为小写。
过滤管道可以被* 套接* ,既是说,一个过滤器管道的输出又可以作为下一个管道的输入,如此下去
{{ my_list|first|upper }} #查找列表的第一个元素并将其转化为大写。
4.locals() 技巧
如果你是个喜欢偷懒的程序员并想让代码看起来更加简明,可以利用 Python 的内建函数 locals() 。它返回的字典对所有局部变量的名称与值进行映射。 因此,前面的视图可以重写成下面这个样子:
def lists(request): lists = [1,2,3,4,5] return render(request,"lists.html",locals())
locals() 的值,它囊括了函数执行到该时间点时所定义的一切变量
5.模板继承
(1)定义基础模板base.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> </head> <body> <h1>My helpful timestamp site</h1> {% block content %}{% endblock %} {% block footer %} <hr> <p>Thanks for visiting my site</p> {% endblock %} </body> </html>
这个叫做 base.html 的模板定义了一个简单的 HTML 框架文档,我们将在所有页面中使用。 子模板的作用就是重载、添加或保留那些块的内容。
所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。 每个 {% block %} 标签所要做的是告诉模板引擎,该模板下的这一块内容将有可能被子模板覆盖。
(2)子模板current_time.html
{% extends 'base.html' %} {% block title %}The current time{% endblock%} {% block content %} <p>It is now {{ current_date }}</p> {% endblock %}
(3)views.py
from django.shortcuts import HttpResponse,render import datetime def current_datetime(request): current_date = datetime.datetime.now() return render(request,'cuttent_datetime.html',{'current_date':current_date})
以下是其工作方式:在加载 current_datetime.html 模板时,模板引擎发现了 {% extends %} 标签,模板引擎立即装载其父模板,即本例中的 base.html 。此时,模板引擎注意到 base.html 中的三个 {% block %} 标签,并用子模板的内容替换这些 block 。因此,引擎将会使用我们在 { block title %} 中定义的标题,对 {% block content %} 也是如此。 所以,网页标题一块将由 {% block title %} 替换,同样地,网页的内容一块将由 {% block content %} 替换。注意由于子模板并没有定义 footer 块,模板系统将使用在父模板中定义的值。 父模板 {% block %} 标签中的内容总是被当作一条退路。继承并不会影响到模板的上下文。 换句话说,任何处在继承树上的模板都可以访问到你传到模板中的每一个模板变量。
如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作 用。 一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因 此你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话 说,钩子越多越好。 如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。 如果你需要访问父模板中的块的内容,使用 {{ block.super }} 这个标签吧,这一个魔法变量将会表现出 父模板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。 不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双 向的。 也就是说,block 标签不仅挖了一个要填的坑,也定义了在 父 模板中这个坑所填充的内容。如果模 板中出现了两个相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。 {% extends %} 对所传入模板名称使用的加载方法和 get_template() 相同。 也就是说,会将模板名称被添 加到 TEMPLATE_DIRS 设置之后。 多数情况下, {% extends %} 的参数应该是字符串,但是如果直到运行时方能确定父模板名,这个参数也 可以是个变量。 这使得你能够实现一些很酷的动态功能。
第五章 模型
1.MTV and MVC
M:数据存取部分,由django数据库层处理,本章要讲述的内容。
由于 C 由框架自行处理,而 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),Django 也被称为MTV 框架。在 MTV 开发模式中:
M:代表模型(Model),即数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等
T:代表模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
V:代表视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你可以把它看作模型与模板之间的桥梁。
2.设置数据库为Mysql
在settings里面修改配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django', #数据库名字 'USER': 'root', #账号 'PASSWORD': '123456', #密码 'HOST': '127.0.0.1', #IP 'PORT': '3306', #端口 } }
在app的init.py里面导入pymysql模块
import pymysql pymysql.install_as_MySQLdb()
设置好后打开 python manage.py shell 来进行测试。输入一下命令,如果没有报错说明,说明数据库配置是正确的
>>> from django.db import connection >>> cursor = connection.cursor()
3.第一个模型
书籍/作者/出版商 数据库
一个作者有姓,有名及email地址。
from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() class Book(models.Model): title = models.CharField(max_length=100) publication_date = models.DateField() authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher,on_delete = models.CASCADE)
打开shell,添加publisher
当我们打印整个publisher列表时,我们没有得到想要的有用信息,只需要为Publisher对象添加一个__str__方法 ,就可以对Publisher对象更容易理解
from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() def __str__(self): return self.name class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() def __str__(self): return '%s%s'%(self.first_name,self.last_name) class Book(models.Model): title = models.CharField(max_length=100) publication_date = models.DateField() authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher,on_delete = models.CASCADE) def __str__(self): return self.title
4.数据过滤
可以使用`` filter()`` 方法对数据进行过滤:
也可以传入多个参数
Publisher.objects.filter(country="U.S.A.", state_province="CA")
魔术般的操作
Publisher.objects.filter(name__contains="Apr")
5.获取单个对象
如果查询没有返回结果也会抛出异常:
6.数据排序
我们可以对任意字段进行排序,如果需要以多个字段为标准进行排序(第二个字段会在第一个字段的值相同的情况下被使用到),使用多个参数就可以了,如下:
限制返回的数据
7.更新和删除对象
update()方法会返回一个整型数值,表示受影响的记录条数。 在上面的例子中,这个值是2
删除数据库中的对象只需调用该对象的delete()方法即可:
第六章 Django站点管理
1.创建admin用户
python manage.py createsuperuser
访问:http://127.0.0.1:8000/admin/,输入用户名,密码登录进入管理界面
可以看到只有Groutps和Users
要向让app book里面的models显示在这里面,只需把book注册到admin
book app下的admin.py
from django.contrib import admin from book import models # Register your models here. admin.site.register(models.Author) admin.site.register(models.Book) admin.site.register(models.Publisher)
然后就可以在管理界面看到
中文显示的方法:Meta
class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Meta: verbose_name_plural = "出版社" def __str__(self): return self.name
2.Admin工作原理
3.设置字段可选
你或许会发现管理工具有个限制:编辑表单需要你填写每一个字段,然而在有些情况下,你想要某些字段是可选的。 举个例子,我们想要Author模块中的email字段成为可选,即允许不填。 在现实世界中,你可能没有为每个作者登记邮箱地址。
class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(null=True,blank=True)
这些代码告诉Django,作者的邮箱地址允许输入一个空值
4.自定义字段标签
在编辑页面中,每个字段的标签都是从模块的字段名称生成的。规则很简单: 用空格替换下划线;首字母大写
举个例子,说明如何将Author.email的标签改为e-mail,中间有个横线。
class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(null=True,blank=True,verbose_name='e-mail')
改之前
改之后
5.自定义ModelAdmi类
迄今为止,我们做的blank=True、null=True和verbose_name修改其实是模块级别,而不是管理级别的。 也就是说,这些修改实质上是构成模块的一部分,并且正好被管理工具使用,而不是专门针对管理工具的。
(1)自定义列表
默认情况下,Author下面只显示每个作者的姓名
我们可以在这基础上改进,添加其它字段,从而改变列表的显示。比如说:在这个列表中可以看到作者的邮箱地址,为了达到这个目的,我们将为Author模块定义一个ModelAdmin类。 这个类是自定义管理工具的关键,其中最基本的一件事情是允许你指定列表中的字段。
修改admin.py
from django.contrib import admin from book import models class AuthorAdmin(admin.ModelAdmin): list_display = ('first_name','last_name','email') admin.site.register(models.Author,AuthorAdmin) admin.site.register(models.Book) admin.site.register(models.Publisher)
可以看到如下效果
解释一下代码:
我们修改了admin.site.register()调用,在Author后面添加了AuthorAdmin。你可以这样理解:用AuthorAdmin选项注册Author模块。
(2)添加快速查询栏
class AuthorAdmin(admin.ModelAdmin): list_display = ('first_name','last_name','email') search_fields = ('first_name','last_name')
在页面顶端看到一个查询栏
(3)添加过滤器
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) admin.site.register(models.Author,AuthorAdmin) admin.site.register(models.Book,BookAdmin) admin.site.register(models.Publisher)
可以看到右边有filter,Django为日期型字段提供了快捷过滤方式,它包含:今天、过往七天、当月和今年
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date'
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',)
(5)自定义编辑表单
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) fields = ('title', 'authors', 'publisher', 'publication_date')
改之前:
改之后:
通过fields这个选项,你可以排除一些不想被其他人编辑的fields 只要不选上不想被编辑的field(s)即可。
fields = ('title', 'authors', 'publisher')
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) filter_horizontal = ('authors',)
加之后,明显方便多了
filter_vertical = ('authors',)
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) filter_vertical = ('authors',) raw_id_fields = ('publisher',)
效果:
第七章 用户、用户组和权限
注释: