python
3
Python/Django/DJango——模板层复习.md
Normal file
@@ -0,0 +1,3 @@
|
||||
这个模板层大致又复习了一遍之前没找到的东西又发现了
|
||||
|
||||
在模板层中有的内奸标签API真的很有用,还有很多有用的其他东西。
|
||||
198
Python/Django/Django-Manage管理工具.md
Normal file
@@ -0,0 +1,198 @@
|
||||
django-admin.py全局管理工具
|
||||
|
||||
django-admin.py 基本命令 [参数列表]
|
||||
|
||||
- check
|
||||
|
||||
- compilemessages
|
||||
|
||||
- createcachetable
|
||||
|
||||
-
|
||||
|
||||
- diffsettings
|
||||
|
||||
- dumpdata
|
||||
|
||||
- flush
|
||||
|
||||
- inspectdb
|
||||
|
||||
- loaddata
|
||||
|
||||
- makemessages
|
||||
|
||||
**[migrate]:数据库命令**
|
||||
|
||||
- makemigrations
|
||||
|
||||
让django工程记录数据模型的迁移内容。知道那一部分需要迁移,模型有哪些变化,但是不进行操作数据库。
|
||||
|
||||
- migrate
|
||||
|
||||
真正的数据模型迁移工作,对应数据模型创建相应的数据表内容。
|
||||
|
||||
- showmigrations
|
||||
|
||||
显示数据库迁移内容
|
||||
|
||||
[sqldata]:数据库操作命令
|
||||
|
||||
- flush
|
||||
|
||||
清空全部数据
|
||||
|
||||
- dumpdata appname \> app.json
|
||||
|
||||
导出json格式的数据
|
||||
|
||||
- loaddata
|
||||
|
||||
导入json格式的数据
|
||||
|
||||
- dbshell
|
||||
|
||||
项目数据库的终端环境,进入数据库的命令行
|
||||
|
||||
- sendtestmail
|
||||
|
||||
- shell
|
||||
|
||||
**[sql]:数据库控制命令**
|
||||
|
||||
- sqlflush
|
||||
|
||||
- sqlsequencereset
|
||||
|
||||
- squashmigrations
|
||||
|
||||
**[start]:创建命令**
|
||||
|
||||
- startapp
|
||||
|
||||
创建Django的数据模型,主要是MVC中的model部分。
|
||||
|
||||
- startproject HelloWorld
|
||||
|
||||
创建一个名为HelloWorld的项目
|
||||
|
||||
**[test]:测试命令**
|
||||
|
||||
- test
|
||||
|
||||
- testserver
|
||||
|
||||
manage.py项目管理工具
|
||||
|
||||
manage.py 基本命令 参数列表
|
||||
|
||||
**[auth]:用户操作命令**
|
||||
|
||||
- changepassword
|
||||
|
||||
修改用户密码
|
||||
|
||||
- createsuperuser
|
||||
|
||||
创建超级管理员
|
||||
|
||||
**[contenttypes]**
|
||||
|
||||
- remove_stale_contenttypes
|
||||
|
||||
**[django]**
|
||||
|
||||
- check
|
||||
|
||||
- compilemessages
|
||||
|
||||
- createcachetable
|
||||
|
||||
- dbshell
|
||||
|
||||
- diffsettings
|
||||
|
||||
- dumpdata
|
||||
|
||||
- flush
|
||||
|
||||
- inspectdb
|
||||
|
||||
- loaddata
|
||||
|
||||
- makemessages
|
||||
|
||||
- makemigrations
|
||||
|
||||
- migrate
|
||||
|
||||
- sendtestemail
|
||||
|
||||
- shell
|
||||
|
||||
- showmigrations
|
||||
|
||||
- sqlflush
|
||||
|
||||
- sqlmigrate
|
||||
|
||||
- sqlsequencereset
|
||||
|
||||
- squashmigrations
|
||||
|
||||
- startapp
|
||||
|
||||
- startproject
|
||||
|
||||
- test
|
||||
|
||||
- testserver
|
||||
|
||||
**[sessions]**
|
||||
|
||||
- clearsessions
|
||||
|
||||
**[staticfiles]**
|
||||
|
||||
- collectstatic
|
||||
|
||||
- findstatic
|
||||
|
||||
- runserver
|
||||
|
||||
启动Django自带的服务器接口,对工程进行部署
|
||||
|
||||
python manage.py createssuperuser
|
||||
|
||||
用来创建超级用户,通过admin管理工具,实现对数据库的管理。
|
||||
|
||||
Django通过模型管理数据库的方法:
|
||||
|
||||
from django.contrib import adminfrom TestModel.models import Test\# Register
|
||||
your models here.admin.site.register(Test)
|
||||
|
||||
自定义表单
|
||||
|
||||
内联显示
|
||||
|
||||
列表显示
|
||||
|
||||
可以通过一大堆操作来自定义表单的格式,实现后台管理页面。
|
||||
|
||||
准确的说,这个东西是可以用来管理数据的,但是不能用来做前端,毕竟太丑。
|
||||
|
||||
也就是说,如果我用Django做完了一个后台管理数据的页面,最多也就新奇的说,能够进行管理了,还要按照Django的模式,来设计前端、对数据进行渲染、然后呈现出来。
|
||||
|
||||
也就是说,接下来要用Django做三件事情:
|
||||
|
||||
1\. 实现后台的数据管理
|
||||
|
||||
2\. 写完具有相应功能的bootstrap前端
|
||||
|
||||
3\. 实现后端相应的交互功能。
|
||||
|
||||
存在的弊端:
|
||||
|
||||
Django是一种重量级的框架,很多东西都封装到内部了,可能搭建一个优美的网站十分简单,但是最后如果要处理Android客户端的请求,返回json格式的数据,还是需要纯python的编程来实现。也就是说要跳出到框架之外。
|
||||
|
||||
看情况吧,如果真的需要的话,还是要学习这些新的东西。
|
||||
51
Python/Django/Django-Object-Class相关类和对象的使用方法.md
Normal file
@@ -0,0 +1,51 @@
|
||||
**Request对象包含的信息**
|
||||
|
||||
| **属性** | **描述** |
|
||||
|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| path | 请求页面的全路径,不包括域名—例如, "/hello/"。 |
|
||||
| method | 请求中使用的HTTP方法的字符串表示。全大写表示。例如: if request.method == 'GET': do\_something() elif request.method == 'POST': do_something\_else() |
|
||||
| GET | 包含所有HTTP GET参数的类字典对象。参见QueryDict 文档。 |
|
||||
| POST | 包含所有HTTP POST参数的类字典对象。参见QueryDict 文档。 服务器收到空的POST请求的情况也是有可能发生的。也就是说,表单form通过HTTP POST方法提交请求,但是表单中可以没有数据。因此,不能使用语句if request.POST来判断是否使用HTTP POST方法;应该使用if request.method == "POST" (参见本表的method属性)。 注意: POST不包括file-upload信息。参见FILES属性。 |
|
||||
| REQUEST | 为了方便,该属性是POST和GET属性的集合体,但是有特殊性,先查找POST属性,然后再查找GET属性。借鉴PHP's \$_REQUEST。 例如,如果GET = {"name": "john"} 和POST = {"age": '34'},则 REQUEST["name"] 的值是"john", REQUEST["age"]的值是"34". 强烈建议使用GET and POST,因为这两个属性更加显式化,写出的代码也更易理解。 |
|
||||
| COOKIES | 包含所有cookies的标准Python字典对象。Keys和values都是字符串。参见第12章,有关于cookies更详细的讲解。 |
|
||||
| FILES | 包含所有上传文件的类字典对象。FILES中的每个Key都是\<input type="file" name="" /\>标签中name属性的值. FILES中的每个value 同时也是一个标准Python字典对象,包含下面三个Keys: filename: 上传文件名,用Python字符串表示 content-type: 上传文件的Content type content: 上传文件的原始内容 注意:只有在请求方法是POST,并且请求页面中\<form\>有enctype="multipart/form-data"属性时FILES才拥有数据。否则,FILES 是一个空字典。 |
|
||||
| META | 包含所有可用HTTP头部信息的字典。 例如: CONTENT_LENGTH CONTENT_TYPE QUERY_STRING: 未解析的原始查询字符串 REMOTE_ADDR: 客户端IP地址 REMOTE_HOST: 客户端主机名 SERVER_NAME: 服务器主机名 SERVER_PORT: 服务器端口 META 中这些头加上前缀HTTP\_最为Key, 例如: HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE HTTP_HOST: 客户发送的HTTP主机头信息 HTTP_REFERER: referring页 HTTP_USER_AGENT: 客户端的user-agent字符串 HTTP_X_BENDER: X-Bender头信息 |
|
||||
| user | 是一个django.contrib.auth.models.User 对象,代表当前登录的用户。 如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。 你可以通过user的is_authenticated()方法来辨别用户是否登录: if request.user.is\_authenticated(): \# Do something for logged-in users. else: \# Do something for anonymous users. 只有激活Django中的AuthenticationMiddleware时该属性才可用 |
|
||||
| session | 唯一可读写的属性,代表当前会话的字典对象。只有激活Django中的session支持时该属性才可用。 参见第12章。 |
|
||||
| raw_post_data | 原始HTTP POST数据,未解析过。 高级处理时会有用处。 |
|
||||
|
||||
http.request对象中的方法
|
||||
|
||||
| has\_key() | 检查request.GET or request.POST中是否包含参数指定的Key。 |
|
||||
|------------------|-----------------------------------------------------------------------------|
|
||||
| get_full\_path() | 返回包含查询字符串的请求路径。例如, "/music/bands/the_beatles/?print=true" |
|
||||
| is\_secure() | 如果请求是安全的,返回True,就是说,发出的是HTTPS请求。 |
|
||||
|
||||
**QueryDict对象**
|
||||
|
||||
在HttpRequest对象中, GET和POST属性是django.http.QueryDict类的实例。
|
||||
|
||||
QueryDict类似字典的自定义类,用来处理单键对应多值的情况。
|
||||
|
||||
QueryDict实现所有标准的词典方法。还包括一些特有的方法:
|
||||
|
||||
| **方法** | **描述** |
|
||||
|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| \_\_getitem\_\_ | 和标准字典的处理有一点不同,就是,如果Key对应多个Value,\_\_getitem\__()返回最后一个value。 |
|
||||
| \_\_setitem\_\_ | 设置参数指定key的value列表(一个Python list)。注意:它只能在一个mutable QueryDict 对象上被调用(就是通过copy()产生的一个QueryDict对象的拷贝). |
|
||||
| get() | 如果key对应多个value,get()返回最后一个value。 |
|
||||
| update() | 参数可以是QueryDict,也可以是标准字典。和标准字典的update方法不同,该方法添加字典 items,而不是替换它们: \>\>\> q = QueryDict('a=1') \>\>\> q = q.copy() \# to make it mutable \>\>\> q.update({'a': '2'}) \>\>\> q.getlist('a') ['1', '2'] \>\>\> q['a'] \# returns the last ['2'] |
|
||||
| items() | 和标准字典的items()方法有一点不同,该方法使用单值逻辑的\_\_getitem\__(): \>\>\> q = QueryDict('a=1&a=2&a=3') \>\>\> q.items() [('a', '3')] |
|
||||
| values() | 和标准字典的values()方法有一点不同,该方法使用单值逻辑的\_\_getitem\__(): |
|
||||
|
||||
此外, QueryDict也有一些方法,如下表:
|
||||
|
||||
| **方法** | **描述** |
|
||||
|--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| copy() | 返回对象的拷贝,内部实现是用Python标准库的copy.deepcopy()。该拷贝是mutable(可更改的) — 就是说,可以更改该拷贝的值。 |
|
||||
| getlist(key) | 返回和参数key对应的所有值,作为一个Python list返回。如果key不存在,则返回空list。 It's guaranteed to return a list of some sort.. |
|
||||
| setlist(key,list\_) | 设置key的值为list\_ (unlike \_\_setitem\__()). |
|
||||
| appendlist(key,item) | 添加item到和key关联的内部list. |
|
||||
| setlistdefault(key,list) | 和setdefault有一点不同,它接受list而不是单个value作为参数。 |
|
||||
| lists() | 和items()有一点不同, 它会返回key的所有值,作为一个list, 例如: \>\>\> q = QueryDict('a=1&a=2&a=3') \>\>\> q.lists() [('a', ['1', '2', '3'])] |
|
||||
| urlencode() | 返回一个以查询字符串格式进行格式化后的字符串(e.g., "a=2&b=3&b=5"). |
|
||||
185
Python/Django/Django-QuerySet数据库查询.md
Normal file
@@ -0,0 +1,185 @@
|
||||
**模型的内容**
|
||||
|
||||
**from** django.db **import** models
|
||||
|
||||
**class** Blog(models.Model):
|
||||
|
||||
name **=** models.CharField(max_length**=**100)
|
||||
|
||||
tagline **=** models.TextField()
|
||||
|
||||
**def** \_\_unicode\__(self): \# \__str_\_ on Python 3
|
||||
|
||||
**return** self.name
|
||||
|
||||
**class** Author(models.Model):
|
||||
|
||||
name **=** models.CharField(max_length**=**50)
|
||||
|
||||
email **=** models.EmailField()
|
||||
|
||||
**def** \_\_unicode\__(self): \# \__str_\_ on Python 3
|
||||
|
||||
**return** self.name
|
||||
|
||||
**class** Entry(models.Model):
|
||||
|
||||
blog **=** models.ForeignKey(Blog)
|
||||
|
||||
headline **=** models.CharField(max_length**=**255)
|
||||
|
||||
body_text **=** models.TextField()
|
||||
|
||||
pub_date **=** models.DateField()
|
||||
|
||||
mod_date **=** models.DateField()
|
||||
|
||||
authors **=** models.ManyToManyField(Author)
|
||||
|
||||
n_comments **=** models.IntegerField()
|
||||
|
||||
n_pingbacks **=** models.IntegerField()
|
||||
|
||||
rating **=** models.IntegerField()
|
||||
|
||||
**def** \_\_unicode\__(self): \# \__str_\_ on Python 3
|
||||
|
||||
**return** self.headline
|
||||
|
||||
**使用QuerySet创建对象的方法**
|
||||
|
||||
类名字的静态变量objects,就是与值相关的QuerySet对象
|
||||
|
||||
\>\>\> **from** blog.models **import** Blog
|
||||
|
||||
\>\>\> b **=** Blog(name**=**'Beatles Blog', tagline**=**'All the latest Beatles
|
||||
news.')
|
||||
|
||||
\>\>\> b.save()
|
||||
|
||||
总之,一共有四种方法
|
||||
|
||||
\# 方法 1
|
||||
|
||||
Author.objects.create(name**=**"WeizhongTu", email**=**"tuweizhong@163.com")
|
||||
|
||||
\# 方法 2
|
||||
|
||||
twz **=** Author(name**=**"WeizhongTu", email**=**"tuweizhong@163.com")
|
||||
|
||||
twz.save()
|
||||
|
||||
\# 方法 3
|
||||
|
||||
twz **=** Author()
|
||||
|
||||
twz.name**=**"WeizhongTu"
|
||||
|
||||
twz.email**=**"tuweizhong@163.com"
|
||||
|
||||
twz.save()
|
||||
|
||||
\# 方法 4,首先尝试获取,不存在就创建,可以防止重复
|
||||
|
||||
Author.objects.get_or\_create(name**=**"WeizhongTu",
|
||||
email**=**"tuweizhong@163.com")
|
||||
|
||||
\# 返回值(object, True/False)
|
||||
|
||||
**查找对象的方法**
|
||||
|
||||
Person.objects.all() \# 查询所有
|
||||
|
||||
Person.objects.all()[:10]
|
||||
切片操作,获取10个人,不支持负索引,切片可以节约内存,不支持负索引,后面有相应解决办法,第7条
|
||||
|
||||
Person.objects.get(name**=**"WeizhongTu") \# 名称为 WeizhongTu
|
||||
的一条,多条会报错
|
||||
|
||||
get是用来获取一个对象的,如果需要获取满足条件的一些人,就要用到filter
|
||||
|
||||
Person.objects.filter(name**=**"abc") \#
|
||||
等于Person.objects.filter(name__exact="abc") 名称严格等于 "abc" 的人
|
||||
|
||||
Person.objects.filter(name_\_iexact**=**"abc") \# 名称为 abc
|
||||
但是不区分大小写,可以找到 ABC, Abc, aBC,这些都符合条件
|
||||
|
||||
Person.objects.filter(name__contains**=**"abc") \# 名称中包含 "abc"的人
|
||||
|
||||
Person.objects.filter(name_\_icontains**=**"abc") \#名称中包含
|
||||
"abc",且abc不区分大小写
|
||||
|
||||
Person.objects.filter(name__regex**=**"\^abc") \# 正则表达式查询
|
||||
|
||||
Person.objects.filter(name_\_iregex**=**"\^abc")\# 正则表达式不区分大小写
|
||||
|
||||
\# filter是找出满足条件的,当然也有排除符合某条件的
|
||||
|
||||
Person.objects.exclude(name__contains**=**"WZ") \# 排除包含 WZ 的Person对象
|
||||
|
||||
Person.objects.filter(name__contains**=**"abc").exclude(age**=**23) \#
|
||||
找出名称含有abc, 但是排除年龄是23岁的
|
||||
|
||||
**删除对象的方法**
|
||||
|
||||
Person.objects.filter(name__contains**=**"abc").delete() \# 删除 名称中包含
|
||||
"abc"的人
|
||||
|
||||
如果写成
|
||||
|
||||
people **=** Person.objects.filter(name__contains**=**"abc")
|
||||
|
||||
people.delete()
|
||||
|
||||
效果也是一样的,Django实际只执行一条 SQL 语句。
|
||||
|
||||
**更新某个内容的方法**
|
||||
|
||||
(1) 批量更新,适用于 .all() .filter() .exclude() 等后面
|
||||
(危险操作,正式场合操作务必谨慎)
|
||||
|
||||
Person.objects.filter(name__contains**=**"abc").update(name**=**'xxx') \#
|
||||
名称中包含 "abc"的人 都改成 xxx
|
||||
|
||||
Person.objects.all().delete() \# 删除所有 Person 记录
|
||||
|
||||
(2) 单个 object 更新,适合于 .get(), get_or_create(), update_or_create()
|
||||
等得到的 obj,和新建很类似。
|
||||
|
||||
twz **=** Author.objects.get(name**=**"WeizhongTu")
|
||||
|
||||
twz.name**=**"WeizhongTu"
|
||||
|
||||
twz.email**=**"tuweizhong@163.com"
|
||||
|
||||
twz.save() \# 最后不要忘了保存!!!
|
||||
|
||||
**QuerySet中可迭代对象**
|
||||
|
||||
(1). 如果只是检查 Entry 中是否有对象,应该用 Entry.objects.all().exists()
|
||||
|
||||
(2). QuerySet 支持切片 Entry.objects.all()[:10] 取出10条,可以节省内存
|
||||
|
||||
(3). 用 len(es) 可以得到Entry的数量,但是推荐用
|
||||
Entry.objects.count()来查询数量,后者用的是SQL:SELECT COUNT(\*)
|
||||
|
||||
(4). list(es) 可以强行将 QuerySet 变成 列表
|
||||
|
||||
**QuerySet排序结果**
|
||||
|
||||
Author.objects.all().order\_by('name')
|
||||
|
||||
Author.objects.all().order_by('-name') \# 在 column name
|
||||
前加一个负号,可以实现倒序
|
||||
|
||||
**QuerySet支持链式查询**
|
||||
|
||||
Author.objects.filter(name__contains**=**"WeizhongTu").filter(email**=**"tuweizhong@163.com")
|
||||
|
||||
Author.objects.filter(name__contains**=**"Wei").exclude(email**=**"tuweizhong@163.com")
|
||||
|
||||
\# 找出名称含有abc, 但是排除年龄是23岁的
|
||||
|
||||
Person.objects.filter(name__contains**=**"abc").exclude(age**=**23)
|
||||
|
||||
**QuerySet 重复的问题,使用 .distinct() 去重**
|
||||
27
Python/Django/Django-admin后台管理.md
Normal file
@@ -0,0 +1,27 @@
|
||||
与yii框架相似,通过脚手架的方式直接生成对原始数据的管理,并且可以通过对数据的简单控制实现管理的基础功能。
|
||||
|
||||
class ContactAdmin(admin.ModelAdmin):
|
||||
|
||||
list_display = ('name', 'age', 'email')
|
||||
|
||||
search_fields = ('name', 'age')
|
||||
|
||||
inlines = [TagInline, ]
|
||||
|
||||
fieldsets = (
|
||||
|
||||
['Main',{
|
||||
|
||||
'fields':('name','email'),
|
||||
|
||||
}],
|
||||
|
||||
['Advance',{
|
||||
|
||||
'classes': ('collapse',), \# CSS
|
||||
|
||||
'fields': ('age',),
|
||||
|
||||
}]
|
||||
|
||||
)
|
||||
98
Python/Django/Django-cache缓存系统.md
Normal file
@@ -0,0 +1,98 @@
|
||||
**Django settings 中 cache 默认为**
|
||||
|
||||
{
|
||||
|
||||
'default': {
|
||||
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
也就是默认利用**本地的内存**来当缓存,速度很快。当然可能出来内存不够用的情况,其它的一些内建可用的
|
||||
Backends 有
|
||||
|
||||
'django.core.cache.backends.db.DatabaseCache'
|
||||
|
||||
'django.core.cache.backends.dummy.DummyCache'
|
||||
|
||||
'django.core.cache.backends.filebased.FileBasedCache'
|
||||
|
||||
'django.core.cache.backends.locmem.LocMemCache'
|
||||
|
||||
'django.core.cache.backends.memcached.MemcachedCache'
|
||||
|
||||
'django.core.cache.backends.memcached.PyLibMCCache'
|
||||
|
||||
**利用文件系统来缓存:**
|
||||
|
||||
CACHES **=** {
|
||||
|
||||
'default': {
|
||||
|
||||
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
|
||||
|
||||
'LOCATION': '/var/tmp/django_cache',
|
||||
|
||||
'TIMEOUT': 600,
|
||||
|
||||
'OPTIONS': {
|
||||
|
||||
'MAX_ENTRIES': 1000
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
**利用数据库来缓存,利用命令创建相应的表:python manage.py createcachetable
|
||||
cache_table_name**
|
||||
|
||||
CACHES **=** {
|
||||
|
||||
'default': {
|
||||
|
||||
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
|
||||
|
||||
'LOCATION': 'cache_table_name',
|
||||
|
||||
'TIMEOUT': 600,
|
||||
|
||||
'OPTIONS': {
|
||||
|
||||
'MAX_ENTRIES': 2000
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
**一般来说我们用 Django 来搭建一个网站,要用到数据库等。**
|
||||
|
||||
**from** django.shortcuts **import** render
|
||||
|
||||
**def** index(request):
|
||||
|
||||
\# 读取数据库等 并渲染到网页
|
||||
|
||||
\# 数据库获取的结果保存到 queryset 中
|
||||
|
||||
**return** render(request, 'index.html', {'queryset':queryset})
|
||||
|
||||
**像这样每次访问都要读取数据库,一般的小网站没什么问题,当访问量非常大的时候,就会有很多次的数据库查询,肯定会造成访问速度变慢,服务器资源占用较多等问题。**
|
||||
|
||||
**from** django.shortcuts **import** render
|
||||
|
||||
**from** django.views.decorators.cache **import** cache_page
|
||||
|
||||
@cache_page(60 **\*** 15) \# 秒数,这里指缓存 15
|
||||
分钟,不直接写900是为了提高可读性
|
||||
|
||||
**def** index(request):
|
||||
|
||||
\# 读取数据库等 并渲染到网页
|
||||
|
||||
**return** render(request, 'index.html', {'queryset':queryset})
|
||||
61
Python/Django/Django-cookie-session实现.md
Normal file
@@ -0,0 +1,61 @@
|
||||
**启用session**
|
||||
|
||||
**在视图中使用session**
|
||||
|
||||
\# 创建或修改 session:
|
||||
|
||||
request.session[key] **=** value
|
||||
|
||||
\# 获取 session:
|
||||
|
||||
request.session.get(key,default**=**None)
|
||||
|
||||
\# 删除 session
|
||||
|
||||
**del** request.session[key] \# 不存在时报错
|
||||
|
||||
例子:让用户不能评论两次的应用(原来要用session实现不重复点赞)
|
||||
|
||||
**from** django.http **import** HttpResponse
|
||||
|
||||
**def** post_comment(request, new_comment):
|
||||
|
||||
**if** request.session.get('has_commented', False):
|
||||
|
||||
**return** HttpResponse("You've already commented.")
|
||||
|
||||
c **=** comments.Comment(comment**=**new_comment)
|
||||
|
||||
c.save()
|
||||
|
||||
request.session['has_commented'] **=** True
|
||||
|
||||
**return** HttpResponse('Thanks for your comment!')
|
||||
|
||||
**一个简化的登陆认证:**
|
||||
|
||||
**def** login(request):
|
||||
|
||||
m **=** Member.objects.get(username**=**request.POST['username'])
|
||||
|
||||
**if** m.password **==** request.POST['password']:
|
||||
|
||||
request.session['member_id'] **=** m.id
|
||||
|
||||
**return** HttpResponse("You're logged in.")
|
||||
|
||||
**else**:
|
||||
|
||||
**return** HttpResponse("Your username and password didn't match.")
|
||||
|
||||
**def** logout(request):
|
||||
|
||||
**try**:
|
||||
|
||||
**del** request.session['member_id']
|
||||
|
||||
**except** KeyError:
|
||||
|
||||
**pass**
|
||||
|
||||
**return** HttpResponse("You're logged out.")
|
||||
17
Python/Django/Django-form表单.md
Normal file
@@ -0,0 +1,17 @@
|
||||
使用GET方法接受表单
|
||||
|
||||
\<form action="/search" method="get"\> \<input type="text" name="q"\> \<input
|
||||
type="submit" value="搜索"\>\</form\>
|
||||
|
||||
\# 接收请求数据def search(request): request.encoding='utf-8' if 'q' in
|
||||
request.GET: message = '你搜索的内容为: ' + request.GET['q'] else: message =
|
||||
'你提交了空表单' return HttpResponse(message)
|
||||
|
||||
使用post方法对表单进行操作
|
||||
|
||||
\<form action="/search-post" method="post"\> {% csrf_token %} \<input
|
||||
type="text" name="q"\> \<input type="submit" value="Submit"\> \</form\> \<p\>{{
|
||||
rlt }}\</p\>
|
||||
|
||||
\# 接收POST请求数据def search_post(request): ctx ={} if request.POST: ctx['rlt']
|
||||
= request.POST['q'] return render(request, "post.html", ctx)
|
||||
64
Python/Django/Django-model.md
Normal file
@@ -0,0 +1,64 @@
|
||||
MVC模型中model部分,提供对数据库的操作支持。
|
||||
|
||||
**配置文件settings.py**
|
||||
|
||||
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', \# 或者使用
|
||||
mysql.connector.django 'NAME': 'test', 'USER': 'test', 'PASSWORD': 'test123',
|
||||
'HOST':'localhost', 'PORT':'3306', } }
|
||||
|
||||
**django-admin.py startapp TestModel**
|
||||
|
||||
创建模型,目录结构如下
|
||||
|
||||
HelloWorld\|-- TestModel\| \|-- \__init_\_.py\| \|-- admin.py
|
||||
在管理界面中修改应用程序的模型\| \|-- models.py 存储所有的应用程序的模型\| \|--
|
||||
tests.py 单元测试\| \|-- views.p 应用程序的视图
|
||||
|
||||
**对models.py的理解**
|
||||
|
||||
\# models.pyfrom django.db import modelsclass Test(models.Model): name =
|
||||
models.CharField(max_length=20)
|
||||
|
||||
是模型定义的地方,提供了与数据库对应的类方法
|
||||
|
||||
**配置INSTALLED_APPS这一项**
|
||||
|
||||
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth',
|
||||
'django.contrib.contenttypes', 'django.contrib.sessions',
|
||||
'django.contrib.messages', 'django.contrib.staticfiles', 'TestModel', \#
|
||||
添加此项)
|
||||
|
||||
**实现数据库迁移工作**
|
||||
|
||||
- **python manage.py makemigrations TestModel**
|
||||
|
||||
创建特定的.py
|
||||
文件,用来让Django记录模型的特点,和对数据库的操作(但实际上没有操作数据库。)
|
||||
|
||||
- **python manage.py migrate TestModel**
|
||||
|
||||
将模型和数据库链接。对应模型,在数据库中创建指定的表格。如果已经建好数据库,应该不用执这两个命令。
|
||||
|
||||
数据库的相关操作def testdb(request): \# 初始化 response = "" response1 = "" \#
|
||||
通过objects这个模型管理器的all()获得所有数据行,相当于SQL中的SELECT \* FROM list
|
||||
= Test.objects.all() \# filter相当于SQL中的WHERE,可设置条件过滤结果 response2 =
|
||||
Test.objects.filter(id=1) \# 获取单个对象 response3 = Test.objects.get(id=1) \#
|
||||
限制返回的数据 相当于 SQL 中的 OFFSET 0 LIMIT 2;
|
||||
Test.objects.order_by('name')[0:2] \#数据排序 Test.objects.order_by("id") \#
|
||||
上面的方法可以连锁使用 Test.objects.filter(name="runoob").order_by("id") \#
|
||||
输出所有数据 for var in list: response1 += var.name + " " response = response1
|
||||
return HttpResponse("\<p\>" + response + "\</p\>")
|
||||
|
||||
**Python可以使用自带的shell实现数据库的操作(真他妈的简洁优雅)**
|
||||
|
||||
- 数据库存储
|
||||
|
||||
p = Person(name = "WZ", age = 23)
|
||||
|
||||
p.save()
|
||||
|
||||
- all()用来获取对象列表
|
||||
|
||||
- get()用来获取一个对象
|
||||
|
||||
- filter()用来获取满足条件的一系列对象,允许使用Python这则表达式进行查询。
|
||||
117
Python/Django/Django-template.md
Normal file
@@ -0,0 +1,117 @@
|
||||
template模板的具体使用
|
||||
|
||||
创建模板,目录结构如下:
|
||||
|
||||
\|-- HelloWorld\|-- manage.py \`-- templates \`-- hello.html
|
||||
|
||||
修改配置文件当中TEMPLATES的基础路径
|
||||
|
||||
...TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [BASE_DIR+"/templates",], \# 修改位置 'APP_DIRS': True, 'OPTIONS': {
|
||||
'context_processors': [ 'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages', ], }, },]...
|
||||
|
||||
使用模板如下(view.py):
|
||||
|
||||
使用render函数+数据+渲染内容实现结果输出
|
||||
|
||||
from django.shortcuts import renderdef hello(request): context = {}
|
||||
context['hello'] = 'Hello World!' return render(request, 'hello.html', context)
|
||||
|
||||
Django templates模板标签
|
||||
|
||||
**if-elif-endif标签**
|
||||
|
||||
{% if condition %}
|
||||
|
||||
display 1
|
||||
|
||||
{% elif condition2 %}
|
||||
|
||||
display 2
|
||||
|
||||
{% else %}
|
||||
|
||||
display 3
|
||||
|
||||
{% endif %}
|
||||
|
||||
**for-endfor标签**
|
||||
|
||||
{% for athlete in athlete_list %}
|
||||
|
||||
\<li\>{{ athlete.name}}\</li\>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
循环中的默认变量
|
||||
|
||||
{**%** **for** item **in** List **%**}
|
||||
|
||||
{{ item }}{**%** **if** **not** forloop.last **%**},{**%** endif **%**}
|
||||
|
||||
{**%** endfor **%**}
|
||||
|
||||
\<**ul**\>
|
||||
|
||||
{% for athlete in athlete_list %}
|
||||
|
||||
\<**li**\>{{ athlete.name }}\</**li**\>
|
||||
|
||||
{% empty %}
|
||||
|
||||
\<**li**\>抱歉,列表为空\</**li**\>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
\</**ul**\>
|
||||
|
||||
| 变量 | 描述 |
|
||||
|-------------------------|-------------------------------------------------------|
|
||||
| **forloop.counter** | 索引从 1 开始算 |
|
||||
| **forloop.counter0** | 索引从 0 开始算 |
|
||||
| **forloop.revcounter** | 索引从最大长度到 1 |
|
||||
| **forloop.revcounter0** | 索引从最大长度到 0 |
|
||||
| **forloop.first** | 当遍历的元素为第一项时为真 |
|
||||
| **forloop.last** | 当遍历的元素为最后一项时为真 |
|
||||
| **forloop.parentloop** | 用在嵌套的 for 循环中, 获取上一层 for 循环的 forloop |
|
||||
|
||||
**ifequal/ifnotequal 标签**
|
||||
|
||||
{% ifequal user currentuser %}
|
||||
|
||||
\<h1\>Welcome!\</h1\>
|
||||
|
||||
{% endifequal %}
|
||||
|
||||
**注释标签**
|
||||
|
||||
{\# 这是一个注释 \#}
|
||||
|
||||
**过滤器标签**
|
||||
|
||||
lower是一个过滤管道,允许被套接
|
||||
|
||||
{{ name\|lower }}
|
||||
|
||||
常见的过滤管道
|
||||
|
||||
{{...\|first\|upper\|lower\|truncatewords:"30"\|date:"F j ,Y"}}
|
||||
|
||||
**include标签**
|
||||
|
||||
{% include "nav.html" %}
|
||||
|
||||
Django模板的继承
|
||||
|
||||
模板通过继承实现代码的复用,下面是父文件
|
||||
|
||||
\<body\> \<h1\>Hello World!\</h1\> \<p\>菜鸟教程 Django 测试。\</p\> {% block
|
||||
mainbody %} \<p\>original\</p\>{% endblock %}\</body\>
|
||||
|
||||
下面是子文件,可以替换block部分
|
||||
|
||||
{% extends "base.html" %} {% block mainbody %}\<p\>继承了 base.html 文件\</p\>{%
|
||||
endblock %}
|
||||
69
Python/Django/Django-view.md
Normal file
@@ -0,0 +1,69 @@
|
||||
Django工程创建
|
||||
|
||||
**django-admin.py startproject HelloWorld**
|
||||
|
||||
创建Django项目。其目录结构为:\|-- HelloWorld //项目的容器,内有view控制中心\|
|
||||
\|-- \__init_\_.py //包声明文件\| \|-- settings.py //该Django项目的配置文件\|
|
||||
\|-- urls.py //Django项目的URL声明\| \`-- wsgi.py
|
||||
//该Django项目的WSGI兼容的web服务器入口(python内置服务器程序) \`-- manage.py
|
||||
//与项目相关的命令行工具,实现与Django的交互。
|
||||
|
||||
**python manage.py runserver 0.0.0.0:8000**
|
||||
|
||||
启动服务器,并将该项目部署到服务器当中。
|
||||
|
||||
**HelloWorld/view.py**
|
||||
|
||||
from django.http import HttpResponsedef hello(request): return
|
||||
HttpResponse("Hello world ! ")
|
||||
|
||||
view文件的标准函数。负责接收request,并将request进行处理,返回response,提供给用户。
|
||||
|
||||
**Helloworld/urls.py**
|
||||
|
||||
from django.conf.urls import urlfrom . import viewurlpatterns = [ url(r'\^\$',
|
||||
view.hello),]
|
||||
|
||||
urls文件的标准格式,哦调羹说配置URL和view方法之间的对应关系,建立URL和view方法之间的映射。其中urlpatterns变量的配置函数如下:
|
||||
|
||||
url(regex, view, kwargs, name)
|
||||
|
||||
regex: 正则表达式,匹配相应的url
|
||||
|
||||
view: view方法,用来吹与正则表达式匹配的url
|
||||
|
||||
kwargs:view使用的字典类型的参数。
|
||||
|
||||
name:用来反向获取URL
|
||||
|
||||
**关于url name的详细说明。**
|
||||
|
||||
- 为了在视图渲染过程中获取真正的请求网址。大致理解了一些,url可以通过正则表达式匹配到urlpattern中的一个函数,但是有的时候这个网址会变化,导致原来的匹配不再生效。那么就提供了一种通过名字来匹配具体url的方式。当网址变化时,名字已久能帮助原来的url定位到新的网址。
|
||||
|
||||
- 在原网址链接的地方使用名字+参数的方式,可以自动渲染成最新的url格式。
|
||||
|
||||
原来的匹配项
|
||||
|
||||
url(r'\^add/(\\d+)/(\\d+)/\$', calc\_views.add2, name**=**'add2'),
|
||||
|
||||
现在的匹配项
|
||||
|
||||
url(r'\^new_add/(\\d+)/(\\d+)/\$', calc\_views.add2, name**=**'add2'),
|
||||
|
||||
原来的链接将不能访问
|
||||
|
||||
\<**a** href="/add/4/5/"\>link\</**a**\>
|
||||
|
||||
但是通过名字的链接会自动渲染成当前的url匹配模式
|
||||
|
||||
\<**a** href="{% url 'add2' 4 5 %}"\>link\</**a**\>
|
||||
|
||||
渲染成→\<**a** href="/add/4/5/"\>link\</**a**\>
|
||||
|
||||
渲染成→\<**a** href="/new_add/4/5/"\>link\</**a**\>
|
||||
|
||||
具体渲染的方式为,下面的方式会生成对应的urlpattern。
|
||||
|
||||
**from** django.core.urlresolvers **import** reverse
|
||||
|
||||
reverse('add2', args**=**(a, b))
|
||||
124
Python/Django/Django——三个最关键的对象.md
Normal file
@@ -0,0 +1,124 @@
|
||||
其中有一节专门讲了File对象如何上传,然而上一次为这个文件上传苦恼了很久。
|
||||
|
||||
**重新复习了两个关键对象**
|
||||
|
||||
**HttpRequest对象**
|
||||
|
||||
.scheme 表示请求的方案http或者https
|
||||
|
||||
.body
|
||||
原始HTTP请求的正文。包括GET请求的参数,POST请求的表单,媒体对象的二进制文件。
|
||||
|
||||
.path 表示请求页面的完整路径,不包含域名,可以用来点赞或者喜欢之后刷新原来的网页
|
||||
|
||||
.method HTTP请求的方法GET或者POST
|
||||
|
||||
.encoding 请求的编码
|
||||
|
||||
.GET 一个字典对象,包含HTTP GET的参数
|
||||
|
||||
.POST 一个类字典对象,包含了表单数据的请求。
|
||||
|
||||
.FILES 一个字段对象,包含所上传的文件。
|
||||
|
||||
.COOKIES 标准的python字典,包含所有的cookie。键和值都是字符串
|
||||
|
||||
.META 一个python字典,包含HTTP头部信息。
|
||||
|
||||
.user 一个用户对象。
|
||||
|
||||
.session 一个可以读写的session字典对象。
|
||||
|
||||
方法:
|
||||
|
||||
get\_host()
|
||||
|
||||
获取主机名**127.0.0.1:8000**
|
||||
|
||||
get_full\_path()
|
||||
|
||||
返回path和查询字符串**/music/bands/the_beatles/?print=true**
|
||||
|
||||
**QueryDict对象**
|
||||
|
||||
首先实现了字典所有的标准方法。
|
||||
|
||||
\_\_getitem\__(key)
|
||||
|
||||
\_\_setitem\__(key,value)
|
||||
|
||||
\__contains__(key)
|
||||
|
||||
get(key,default)不存在时返回默认值
|
||||
|
||||
setdefault(key,default)
|
||||
|
||||
update(other_dict),将新的值添加到后边
|
||||
|
||||
items()返回字典的一个列表[('a', '3')]
|
||||
|
||||
iteritems()
|
||||
|
||||
iterlists()
|
||||
|
||||
values() 返回值的一个列表['3']
|
||||
|
||||
itervalues() 返回一个迭代器
|
||||
|
||||
copy()调用python库中的deepcopy()进行神复制
|
||||
|
||||
getlist(key,default)以列表返回所有请求的键
|
||||
|
||||
appendlist(key,item)
|
||||
|
||||
setlistdefault(key,default\_list)
|
||||
|
||||
lists()
|
||||
|
||||
pop(key)弹出
|
||||
|
||||
popitem()随机弹出
|
||||
|
||||
dict()返回dict对象
|
||||
|
||||
**httpResponse对象**
|
||||
|
||||
.content 一个字节字符
|
||||
|
||||
.charset response编码的字符串
|
||||
|
||||
.status_code HTTP相应状态码
|
||||
|
||||
.reason_phrase HTTP原因短语
|
||||
|
||||
.streaming 总是false
|
||||
|
||||
.closed 响应是否关闭
|
||||
|
||||
.\_\_setitem\__(header,value)设定报文首部。
|
||||
|
||||
.\_\_delitem\__(header)
|
||||
|
||||
.\_\_getitem\__(header)
|
||||
|
||||
.has\_header(header)
|
||||
|
||||
.set\_cookie()
|
||||
|
||||
.set_signed_cookie() 设置cookie,并用秘钥签名
|
||||
|
||||
.delete_cookie() 删除cookie
|
||||
|
||||
.write()
|
||||
|
||||
.flush()
|
||||
|
||||
.tell()
|
||||
|
||||
**其子类包括以下**
|
||||
|
||||
HttpResponseRedirect对象
|
||||
|
||||
HttpResponseNotModified
|
||||
|
||||
HttpResponsePermanentRedirect
|
||||
162
Python/Django/Django——关于URL分组匹配问题.md
Normal file
@@ -0,0 +1,162 @@
|
||||
**基本原则说明:**
|
||||
|
||||
- Django会一次匹配列表中的每个URL模式,在遇到第一个请求的URL相匹配的模式时停下来
|
||||
|
||||
- 分组传参包括以下内容:
|
||||
|
||||
- 一个HttpRequest实例。
|
||||
|
||||
- 如果正则表达式是无名组,那么正则表达式所匹配的内容将作为位置参数提供给视图。
|
||||
|
||||
- 如果正则表达式是命名组,那么正则表达式所匹配的内容将作为关键参数提供给视图。
|
||||
|
||||
- 对于GET、POST请求本身的参数不进行匹配。作为扩展参数kwargs提供给视图。
|
||||
|
||||
- 如果请求的URL没有匹配到任何一个正则表达式,或者匹配过程中抛出异常,会进行相应的错误处理。
|
||||
|
||||
分组参数
|
||||
|
||||
关键参数
|
||||
|
||||
**匹配分组算法说明:**
|
||||
|
||||
\> 分组对应参数,是如何传递参数的过程;匹配分组算法,是如何匹配字符串的过程。
|
||||
|
||||
- 如果有命名参数,则使用命名参数,忽略非命名参数。
|
||||
|
||||
- 否则,将以位置参数传递所有的非命名参数。
|
||||
|
||||
- 所有的匹配结果都是字符串
|
||||
|
||||
能够通过url函数额外传递多个参数。
|
||||
|
||||
终于他妈的明白这种关键参数和位置参数的意思了:
|
||||
|
||||
关键参数是为了匹配具体的字符串,位置参数是按照先后位置匹配字符串。他妈的,果然看不天不如写两行试试。谨记,这里的匹配原则。和之前的分组传递参数原则。如此简单,是自己最近变愚钝了吗,好久没做数学题了吗,思路一点都不够灵活,而且好像由于电子屏幕的原因,记忆力下降好快。
|
||||
|
||||
**URL反向解析说明:**
|
||||
|
||||
- 在视图中使用标签进行反向解析
|
||||
|
||||
**\<a** href="**{%** **url** 'news-year-archive' yearvar **%}**"**\>{{** yearvar
|
||||
**}}** Archive**\</a\>**
|
||||
|
||||
- 在代码中使用reverse函数进行反向解析
|
||||
|
||||
reverse('news-year-archive', args**=**(year,))
|
||||
|
||||
**模板标签URL反向解析**
|
||||
|
||||
- 通过url标签、名称、位置参数直接反转
|
||||
|
||||
**{%** **url** 'some-url-name' v1 v2 **%}**
|
||||
|
||||
- 通过url标签、名称、关键参数直接反转。没有成功验证过这种关键参数长什么模样。
|
||||
|
||||
**{%** **url** 'some-url-name' arg1**=**v1 arg2**=**v2 **%}**
|
||||
|
||||
\> 位置参数和关键参数不能混用
|
||||
|
||||
**1,定义:**
|
||||
|
||||
> 随着功能的增加会出现更多的视图,可能之前配置的正则表达式不够准确,于是就要修改正则表达式,但是正则表达式一旦修改了,之前所有对应的超链接都要修改,真是一件麻烦的事情,而且可能还会漏掉一些超链接忘记修改,有办法让链接根据正则表达式动态生成吗?
|
||||
> 就是用反向解析的办法。
|
||||
|
||||
**2,应用范围:**
|
||||
|
||||
- 模板中的超链接
|
||||
|
||||
- 视图中的重定向
|
||||
|
||||
**3,使用方法:**
|
||||
|
||||
- 定义url时,需要为include定义namespace属性,为url定义name属性
|
||||
|
||||
- 使用时,在模板中使用url标签,在视图中使用reverse函数,根据正则表达式动态生成地址,减轻后期维护成本。
|
||||
|
||||
**4,模板中超链接步骤:**
|
||||
|
||||
1)在项目urls.py中为include定义namespace属性。
|
||||
|
||||
> url(r’\^’,include(‘booktest.urls’,namespace=’booktest’)),
|
||||
|
||||
2)在应用的urls.py中为url定义name属性,并修改为fan2。
|
||||
|
||||
> url(r’\^fan2/\$’, views.fan2,name=’fan2’),
|
||||
|
||||
3)在模板中使用url标签做超链接,此处为templates/booktest/fan1.html文件。
|
||||
|
||||
\<html\>\<head\> \<title\>反向解析\</title\>\</head\>\<body\>普通链接:\<a
|
||||
href="/fan2/"\>普通fan2\</a\>\<hr\>反向解析:\<a href="{%url
|
||||
'booktest:fan2'%}"\>反向解析fan2\</a\>\</body\>\</html\>
|
||||
|
||||
4)回到浏览器中,后退,刷新,查看源文件,两个链接地址一样。
|
||||
|
||||

|
||||
|
||||
这里写图片描述
|
||||
|
||||
5)在应用的urls.py中,将fan2修改为fan_show。
|
||||
|
||||
> url(r’\^fan_show/\$’, views.fan2,name=’fan2’),
|
||||
|
||||
6)回到浏览器中,刷新,查看源文件,两个链接地址不一样。
|
||||
|
||||

|
||||
|
||||
这里写图片描述
|
||||
|
||||
**4,视图中的重定向:**
|
||||
|
||||
from django.shortcuts import redirect from django.core.urlresolvers import
|
||||
reverse return redirect(reverse('booktest:fan2'))
|
||||
|
||||
**5,反向解析中URL的参数**
|
||||
|
||||
**位置参数**
|
||||
|
||||
1)在booktest/urls.py中,修改fan2如下:
|
||||
|
||||
> url(r’\^fan(\\d+)\_(\\d+)/\$’, views.fan2,name=’fan2’),
|
||||
|
||||
2)修改templates/booktest/fan1.html文件如下:
|
||||
|
||||
\<html\>\<head\> \<title\>反向解析\</title\>\</head\>\<body\>普通链接:\<a
|
||||
href="/fan2_3/"\>fan2\</a\>\<hr\>反向解析:\<a href="{%url 'booktest:fan2' 2
|
||||
3%}"\>fan2\</a\>\</body\>\</html\>
|
||||
|
||||
3)回到浏览器中,刷新,查看源文件如下图:
|
||||
|
||||

|
||||
|
||||
这里写图片描述
|
||||
|
||||
- 使用重定向传递位置参数格式如下:
|
||||
|
||||
return redirect(reverse(‘booktest:fan’, args=(2,3)))
|
||||
|
||||
**关键字参数**
|
||||
|
||||
1)在booktest/urls.py中,修改fan2如下:
|
||||
|
||||
url(r'\^fan(?P\<id\>\\d+)\_(?P\<age\>\\d+)/\$', views.fan2,name='fan2'),
|
||||
|
||||
- 1
|
||||
|
||||
2)修改templates/booktest/fan1.html文件如下:
|
||||
|
||||
\<html\>\<head\> \<title\>反向解析\</title\>\</head\>\<body\>普通链接:\<a
|
||||
href="/fan100_18/"\>fan2\</a\>\<hr\>反向解析:\<a href="{%url 'booktest:fan2'
|
||||
id=100 age=18%}"\>fan2\</a\>\</body\>\</html\>
|
||||
|
||||
3)回到浏览器中,刷新,查看源文件如下图:
|
||||
|
||||

|
||||
|
||||
这里写图片描述
|
||||
|
||||
- 使用重定向传递关键字参数格式如下:
|
||||
|
||||
return redirect(reverse(‘booktest:fan2’, kwargs={‘id’:110,’age’:26}))
|
||||
|
||||
真他妈的日了够了,老子居然又因为拼写错误浪费了这么多时间。
|
||||
58
Python/Django/Django——基本理解.md
Normal file
@@ -0,0 +1,58 @@
|
||||
**http请求处理的MVC结构**
|
||||
|
||||

|
||||
|
||||
**HTTP处理的中间件结构**
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
记住几个重要的预处理函数
|
||||
|
||||
**process\_request(self, request)**
|
||||
|
||||
request预处理函数
|
||||
|
||||
在**Django接收到request**之后,但仍未解析URL以确定应当运行的view之前。调用
|
||||
|
||||
返回 None(Django将继续处理这个request,执行后续的中间件,
|
||||
然后调用相应的view,“我对继续处理这个request没意见”)
|
||||
|
||||
或者返回 HttpResponse 对象(Django
|
||||
将不再执行任何其它的中间件(无视其种类)以及相应的view。 Django将立即返回该
|
||||
HttpResponse,“我不想其他代码处理这个request,我要提早返回” ).
|
||||
|
||||
process\_view(self, request, callback, callback_args, callback_kwargs)
|
||||
|
||||
view预处理函数
|
||||
|
||||
在Django执行完request预处理函数并确定待执行的view之后,但在view函数实际执行之前。
|
||||
|
||||
process\_response(self, request, response)
|
||||
|
||||
Response后处理函数
|
||||
|
||||
在\*\*\*\*Django\*\*\*\*执行view\*\*\*\*函数\*\*\*\*并生成\*\*\*\*response\*\*\*\*之后
|
||||
|
||||
该处理器能修改response\*\*\*\*的内容
|
||||
|
||||
**记住一些琐碎的知识**
|
||||
|
||||
- 一个工程可以有很多model,一个model就代表一个一个app,他有自己的数据(关联到相应的数据库)和自己的控制器视图views用来实现对model的操作和访问。现在的疑问可能就是每一部分是负责做什么的,到底该怎样组织整个工程。
|
||||
|
||||
- url支持的各种匹配。可以通过正则表达式来实现不同url的配置。request中的对GET与POST对象都是queryDict的实例,是普通Dict的扩展,兼容了普通Dict的一些基本方法。
|
||||
|
||||
**django的组成结构**
|
||||
|
||||
管理工具(Management):主要通过管理工具的命令来实现对整个工程的控制。一整套内置的创建站点、迁移数据、维护静态文件的命令。
|
||||
|
||||
模型(model):提供数据访问的接口和模块。
|
||||
|
||||
视图(view):封装了HTTP request和response的一系列操作和数据流,函数、类视图
|
||||
|
||||
模板(template):一整套Django自己的页面渲染语言。若干内置的tags和filters
|
||||
|
||||
表单(form):通过内置的数据类型控制表单和控件生成HTML表单。已经差不多了
|
||||
|
||||
管理站(Admin):通过生命管理Model,快速生成后台数据管理网站。
|
||||
6
Python/Django/Django——快捷视图函数.md
Normal file
@@ -0,0 +1,6 @@
|
||||
render 使用模板进行渲染
|
||||
|
||||
redirect
|
||||
重定向到一个新的url,也就是说我当前没有渲染的视图,我交给另外一个动作来处理,我提供动作必要的参数。所以传递参数到视图的过程绝对不应该用redirect,而是render。
|
||||
|
||||
redirect有多种形式。可以是绝对路径、相对路径、动作(视图)名称 + 必要的参数
|
||||
754
Python/Django/Django——数据库操作复习.md
Normal file
@@ -0,0 +1,754 @@
|
||||
这个是当前最终要的一部分知识,因为接下来的工作包括太多的数据库操作了,必须得详细了解一下。
|
||||
|
||||
\---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
关于模型的说明
|
||||
|
||||
**字段选项**
|
||||
|
||||
定义字段过程中对字段的性质进行控制
|
||||
|
||||
- null
|
||||
|
||||
- blank
|
||||
|
||||
- choices
|
||||
|
||||
- db_column
|
||||
|
||||
- db_index
|
||||
|
||||
- db_tablespace
|
||||
|
||||
- default
|
||||
|
||||
- auto_to_now
|
||||
|
||||
- error_messages
|
||||
|
||||
- help_text
|
||||
|
||||
- primary_key(主键)
|
||||
|
||||
- unique(唯一性)
|
||||
|
||||
- unique_for_date
|
||||
|
||||
- unique_for_month
|
||||
|
||||
- unique_for_year
|
||||
|
||||
- verbose_name
|
||||
|
||||
- 验证器
|
||||
|
||||
- 注册和获取查询
|
||||
|
||||
**字段类型**
|
||||
|
||||
定义字段的类型
|
||||
|
||||
- AutoField自增字段
|
||||
|
||||
- BigIntegerField
|
||||
|
||||
- 二进制字段
|
||||
|
||||
- BooleanField
|
||||
|
||||
- For
|
||||
|
||||
- CommaSeparatedIntegerField
|
||||
|
||||
- rendering
|
||||
|
||||
- DateField
|
||||
|
||||
- DecimalField
|
||||
|
||||
- DurationField
|
||||
|
||||
- EmailField
|
||||
|
||||
- FileField
|
||||
|
||||
FileField和FieldFile
|
||||
|
||||
- FilePathField
|
||||
|
||||
- FloatField
|
||||
|
||||
- forms
|
||||
|
||||
- IntegerField
|
||||
|
||||
- IPAddressField
|
||||
|
||||
- GenericIPAddressField
|
||||
|
||||
- NullBooleanField
|
||||
|
||||
- PositiveIntegerField
|
||||
|
||||
- PositiveSmallIntegerField
|
||||
|
||||
- SlugField
|
||||
|
||||
- SmallIntegerField
|
||||
|
||||
- TextField(文本域)
|
||||
|
||||
- TimeField
|
||||
|
||||
- URLField
|
||||
|
||||
- UUIDField
|
||||
|
||||
**字段关系**
|
||||
|
||||
- ForeignField
|
||||
|
||||
- ManyToManyField
|
||||
|
||||
- OneToOneField
|
||||
|
||||
\--------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
关于对象的操作
|
||||
|
||||
**创建对象**
|
||||
|
||||
直接创建
|
||||
|
||||
b **=** Blog(name**=**'Beatles Blog', tagline**=**'All the latest Beatles
|
||||
news.')
|
||||
|
||||
可以使用objects管理器的create方法
|
||||
|
||||
joe **=** Author**.**objects**.**create(name**=**"Joe")
|
||||
|
||||
**保存对象**
|
||||
|
||||
可以保存对象的更新,也可以添加新的对象。
|
||||
|
||||
save()
|
||||
|
||||
**获取对象**
|
||||
|
||||
(管理器方法,执行sql语句)
|
||||
|
||||
有很多方法QuerySet API,单独说明
|
||||
|
||||
**---------------------------------------------------------**
|
||||
|
||||
**查询集求值方法**
|
||||
|
||||
因为Django采取了惰性查询的方法,只要不是用,就不会执行查询语句求值。以下方法,会导致sql语句被执行。
|
||||
|
||||
**迭代**
|
||||
|
||||
**切片(step参数为true)**
|
||||
|
||||
**序列化缓存**
|
||||
|
||||
**repr()**
|
||||
|
||||
**len()**返回查询集的长度,并对查询集进行求值(COUNT 函数是不求值得)
|
||||
|
||||
**list()**对查询集进行强制求值,从queryset变为普通列表
|
||||
|
||||
entry_list **=** list(Entry**.**objects**.**all())
|
||||
|
||||
**bool()**判断查询集是否存在
|
||||
|
||||
**if** Entry**.**objects**.**filter(headline**=**"Test"): **print**("There is at
|
||||
least one Entry with the headline Test")
|
||||
|
||||
**基本查询**
|
||||
|
||||
Entry**.**objects**.**all()
|
||||
|
||||
返回包含数据库中所有对象的一个**查询集**。
|
||||
|
||||
**filter(\*\*kwargs)**
|
||||
|
||||
返回一个新的**查询集**,它包含满足查询参数的对象。
|
||||
|
||||
**exclude(\*\*kwargs)**
|
||||
|
||||
返回一个新的**查询集**,它包含不满足查询参数的对象。
|
||||
|
||||
Entry**.**objects**.**get(**\*\*kwargs**)
|
||||
|
||||
直接返回该对象(返回查询到的第一个对象)
|
||||
|
||||
**extra**
|
||||
|
||||
**extra(**select=None**,** where=None**,** params=None**,** tables=None**,**
|
||||
order_by=None**,**
|
||||
select_params=None**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.extra)
|
||||
|
||||
有些情况下,Django的查询语法难以简单的表达复杂的 **WHERE** 子句,对于这种情况,
|
||||
Django 提供了 **extra()** **QuerySet** 修改机制 — 它能在
|
||||
**QuerySet**生成的SQL从句中注入新子句
|
||||
|
||||
功能太过强大应该用不到
|
||||
|
||||
**raw**
|
||||
|
||||
**raw(**raw_query**,** params=None**,** translations=None**)**
|
||||
|
||||
接收一个原始的SQL 查询,执行它并返回一个**django.db.models.query.RawQuerySet**
|
||||
实例。这个**RawQuerySet** 实例可以迭代以提供实例对象,就像普通的**QuerySet**
|
||||
一样。
|
||||
|
||||
**不返回查询集的查询**
|
||||
|
||||
**get**
|
||||
|
||||
**get(**\*\*kwargs**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.get)
|
||||
|
||||
返回按照查询参数匹配到的对象,参数的格式应该符合 [Field
|
||||
lookups](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#id4)的要求.
|
||||
|
||||
- 如果匹配到的对象个数不只一个的话,**get()**
|
||||
将会触发[**MultipleObjectsReturned**](http://python.usyiyi.cn/documents/django_182/ref/exceptions.html#django.core.exceptions.MultipleObjectsReturned)
|
||||
异常.
|
||||
[**MultipleObjectsReturned**](http://python.usyiyi.cn/documents/django_182/ref/exceptions.html#django.core.exceptions.MultipleObjectsReturned)
|
||||
异常是模型类的属性.
|
||||
|
||||
- 如果根据给出的参数匹配不到对象的话,**get()**
|
||||
将触发[**DoesNotExist**](http://python.usyiyi.cn/documents/django_182/ref/models/instances.html#django.db.models.Model.DoesNotExist)
|
||||
异常. 这个异常是模型类的属性.
|
||||
|
||||
Entry**.**objects**.**get(id**=**'foo') *\# raises Entry.DoesNotExist*
|
||||
|
||||
> 异常处理
|
||||
|
||||
> **from** **django.core.exceptions** **import** ObjectDoesNotExist **try**: e
|
||||
> **=** Entry**.**objects**.**get(id**=**3) b **=**
|
||||
> Blog**.**objects**.**get(id**=**1)**except** ObjectDoesNotExist:
|
||||
> **print**("Either the entry or blog doesn't exist.")
|
||||
|
||||
**create**
|
||||
|
||||
**create(**\*\*kwargs**)**
|
||||
|
||||
一个在一步操作中同时创建对象并且保存的便捷方法.
|
||||
|
||||
p **=** Person**.**objects**.**create(first_name**=**"Bruce",
|
||||
last_name**=**"Springsteen")
|
||||
|
||||
> 和:
|
||||
|
||||
> p **=** Person(first_name**=**"Bruce", last_name**=**"Springsteen")
|
||||
> p**.**save(force_insert**=**True)
|
||||
|
||||
> 是等同的.
|
||||
|
||||
**get_or_create**
|
||||
|
||||
**get_or\_create(**defaults=None**,**
|
||||
\*\*kwargs**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.get_or_create)
|
||||
|
||||
一个通过给出的**kwargs**
|
||||
来查询对象的便捷方法(如果你的模型中的所有字段都有默认值,可以为空),需要的话创建一个对象。
|
||||
|
||||
> **try**: obj **=** Person**.**objects**.**get(first_name**=**'John',
|
||||
> last_name**=**'Lennon')**except** Person**.**DoesNotExist: obj **=**
|
||||
> Person(first_name**=**'John', last_name**=**'Lennon',
|
||||
> birthday**=**date(1940, 10, 9)) obj**.**save()
|
||||
|
||||
> 等同于
|
||||
|
||||
> obj, created **=**
|
||||
> Person**.**objects**.**get_or\_create(first_name**=**'John',
|
||||
> last_name**=**'Lennon',defaults**=**{'birthday': date(1940, 10, 9)})
|
||||
|
||||
**update_or_create**
|
||||
|
||||
**update_or\_create(**defaults=None**,** \*\*kwargs**)**
|
||||
|
||||
一个通过给出的**kwargs** 来更新对象的便捷方法,
|
||||
如果需要的话创建一个新的对象。**defaults** 是一个由 (field, value)
|
||||
对组成的字典,用于更新对象。
|
||||
|
||||
**try**: obj **=** Person**.**objects**.**get(first_name**=**'John',
|
||||
last_name**=**'Lennon') **for** key, value **in**
|
||||
updated_values**.**iteritems(): setattr(obj, key, value)
|
||||
obj**.**save()**except** Person**.**DoesNotExist:
|
||||
updated_values**.**update({'first_name': 'John', 'last_name': 'Lennon'}) obj
|
||||
**=** Person(**\*\***updated_values) obj**.**save()
|
||||
|
||||
等同于
|
||||
|
||||
obj, created **=** Person**.**objects**.**update\_or_create(
|
||||
first_name**=**'John', last_name**=**'Lennon', defaults**=**updated_values)
|
||||
|
||||
**bulk_create**
|
||||
|
||||
**bulk\_create(**objs**,** batch_size=None**)**
|
||||
|
||||
此方法以有效的方式(通常只有1个查询,无论有多少对象)将提供的对象列表插入到数据库中:
|
||||
|
||||
**\>\>\>** Entry**.**objects**.**bulk\_create([**...**
|
||||
Entry(headline**=**"Django 1.0 Released"),**...** Entry(headline**=**"Django
|
||||
1.1 Announced"),**...** Entry(headline**=**"Breaking: Django is
|
||||
awesome")**...** ])
|
||||
|
||||
**count**
|
||||
|
||||
**count()**
|
||||
|
||||
返回在数据库中对应的 **QuerySet**.对象的个数。 **count()** 永远不会引发异常。
|
||||
|
||||
例:
|
||||
|
||||
*\# Returns the total number of entries in the
|
||||
database.*Entry**.**objects**.**count()*\# Returns the number of entries whose
|
||||
headline contains
|
||||
'Lennon'*Entry**.**objects**.**filter(headline__contains**=**'Lennon')**.**count()
|
||||
|
||||
**iterator**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#iterator)
|
||||
|
||||
**iterator()**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.iterator)
|
||||
|
||||
评估**QuerySet**(通过执行查询),并返回一个迭代器
|
||||
|
||||
**first**
|
||||
|
||||
**first()**
|
||||
|
||||
返回结果集的第一个对象, 当没有找到时返回**None**.如果 **QuerySet**
|
||||
没有设置排序,则将会自动按主键进行排序
|
||||
|
||||
例:
|
||||
|
||||
p **=** Article**.**objects**.**order\_by('title', 'pub_date')**.**first()
|
||||
|
||||
笔记:**first()** 是一个简便方法 下面这个例子和上面的代码效果是一样
|
||||
|
||||
**try**: p **=** Article**.**objects**.**order\_by('title',
|
||||
'pub_date')[0]**except** **IndexError**: p **=** None
|
||||
|
||||
**aggregate(聚合查询)**
|
||||
|
||||
**aggregate(**\*args**,** \*\*kwargs**)**
|
||||
|
||||
返回一个字典,包含根据**QuerySet**
|
||||
计算得到的聚合值(平均数、和等等)。**aggregate()**
|
||||
的每个参数指定返回的字典中将要包含的值。
|
||||
|
||||
**\>\>\> from** **django.db.models** **import** Count **\>\>\>** q **=**
|
||||
Blog**.**objects**.**aggregate(Count('entry')){'entry__count': 16}
|
||||
|
||||
通过使用关键字参数来指定聚合函数,你可以控制返回的聚合的值的名称:
|
||||
|
||||
**\>\>\>** q **=**
|
||||
Blog**.**objects**.**aggregate(number_of_entries**=**Count('entry')){'number_of_entries':
|
||||
16}
|
||||
|
||||
**exists**
|
||||
|
||||
**exists()**
|
||||
|
||||
如果[**QuerySet**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet)
|
||||
包含任何结果,则返回**True**,否则返回**False**。
|
||||
|
||||
entry **=** Entry**.**objects**.**get(pk**=**123)**if**
|
||||
some_queryset**.**filter(pk**=**entry**.**pk)**.**exists(): **print**("Entry
|
||||
contained in queryset")
|
||||
|
||||
**update**
|
||||
|
||||
**update(**\*\*kwargs**)**
|
||||
|
||||
对指定的字段执行SQL更新查询,并返回匹配的行数(如果某些行已具有新值,则可能不等于已更新的行数)。
|
||||
|
||||
例如,要对2010年发布的所有博客条目启用评论,您可以执行以下操作:
|
||||
|
||||
**\>\>\>**
|
||||
Entry**.**objects**.**filter(pub_date__year**=**2010)**.**update(comments_on**=**False)
|
||||
|
||||
**delete**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#delete)
|
||||
|
||||
**delete()**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.delete)
|
||||
|
||||
对[**QuerySet**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet)中的所有行执行SQL删除查询。立即应用**delete()**。您不能在[**QuerySet**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet)上调用**delete()**,该查询已采取切片或以其他方式无法过滤。
|
||||
|
||||
要删除特定博客中的所有条目:
|
||||
|
||||
**\>\>\>** b **=** Blog**.**objects**.**get(pk**=**1)\# Delete all the entries
|
||||
belonging to this Blog.**\>\>\>**
|
||||
Entry**.**objects**.**filter(blog**=**b)**.**delete()
|
||||
|
||||
**字段查询**
|
||||
|
||||
查询的关键字参数的基本形式是**field__lookuptype=value**。字段查询是指如何指定SQL
|
||||
**WHERE**子句的内容.
|
||||
它们通过**查询集**的[**filter()**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.filter),
|
||||
[**exclude()**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.exclude)
|
||||
and
|
||||
[**get()**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.get)的关键字参数指定.
|
||||
|
||||
**exact**
|
||||
|
||||
精确匹配。如果为比较提供的值为**None**,它将被解释为SQL **NULL**
|
||||
|
||||
Entry**.**objects**.**get(id__exact**=**14)
|
||||
Entry**.**objects**.**get(id__exact**=**None)
|
||||
|
||||
**iexact**
|
||||
|
||||
不区分大小写的精确匹配
|
||||
|
||||
Blog**.**objects**.**get(name_\_iexact**=**'beatles blog')
|
||||
Blog**.**objects**.**get(name_\_iexact**=**None)
|
||||
|
||||
**contains**
|
||||
|
||||
区分大小写的包含例子。
|
||||
|
||||
Entry**.**objects**.**get(headline__contains**=**'Lennon')
|
||||
|
||||
**icontains**
|
||||
|
||||
不区分大小写的包含
|
||||
|
||||
Entry**.**objects**.**get(headline_\_icontains**=**'Lennon')
|
||||
|
||||
**in**
|
||||
|
||||
在给定的列表。
|
||||
|
||||
Entry**.**objects**.**filter(id__in**=**[1, 3, 4])
|
||||
|
||||
在一次查询的结果集合中进行查询
|
||||
|
||||
inner_qs **=**
|
||||
Blog**.**objects**.**filter(name__contains**=**'Ch')**.**values('name') entries
|
||||
**=** Entry**.**objects**.**filter(blog__name__in**=**inner_qs)
|
||||
|
||||
**gt**
|
||||
|
||||
大于
|
||||
|
||||
Entry**.**objects**.**filter(id_\_gt**=**4)
|
||||
|
||||
**gte**
|
||||
|
||||
大于或等于
|
||||
|
||||
**lt**
|
||||
|
||||
小于
|
||||
|
||||
**lte**
|
||||
|
||||
小于或等于
|
||||
|
||||
**startswith**
|
||||
|
||||
区分大小写,开始位置匹配
|
||||
|
||||
Entry**.**objects**.**filter(headline_\_startswith**=**'Will')
|
||||
|
||||
**istartswith**
|
||||
|
||||
不区分大小写,开始位置匹配
|
||||
|
||||
Entry**.**objects**.**filter(headline_\_istartswith**=**'will')
|
||||
|
||||
**endswith**
|
||||
|
||||
区分大小写。
|
||||
|
||||
**iendswith**
|
||||
|
||||
不区分大小写。
|
||||
|
||||
**range**
|
||||
|
||||
范围测试(包含于之中,在时间相关的查询中尤为重要,如果你要获取这一周的内容的话,肯定要用到这一周的内容)。
|
||||
|
||||
**import** **datetime** start_date **=** datetime**.**date(2005, 1, 1) end_date
|
||||
**=** datetime**.**date(2005, 3, 31)
|
||||
Entry**.**objects**.**filter(pub_date__range**=**(start_date, end_date))
|
||||
|
||||
部分日期的关键字参数
|
||||
|
||||
year month day weekday hour minute second
|
||||
|
||||
**isnull**
|
||||
|
||||
值为 **True** 或 **False**
|
||||
|
||||
Entry**.**objects**.**filter(pub_date_\_isnull**=**True)
|
||||
|
||||
正则表达式
|
||||
|
||||
**regex**
|
||||
|
||||
区分大小写的正则表达式匹配。
|
||||
|
||||
Entry**.**objects**.**get(title__regex**=**r'\^(An?\|The) +')
|
||||
|
||||
**iregex**
|
||||
|
||||
不区分大小写的正则表达式匹配。
|
||||
|
||||
Entry**.**objects**.**get(title_\_iregex**=**r'\^(an?\|the) +')
|
||||
|
||||
**聚合函数**
|
||||
|
||||
在**QuerySet** 为空时,聚合函数函数将返回**None**。 例如,如果**QuerySet**
|
||||
中没有记录,**Sum** 聚合函数将返回**None** 而不是**0**。**Count**
|
||||
是一个例外,如果**QuerySet** 为空,它将返回**0**。
|
||||
|
||||
聚合函数的参数有以下三个
|
||||
|
||||
**expression**
|
||||
|
||||
引用模型字段的一个字符串,或者一个[查询表达式](http://python.usyiyi.cn/documents/django_182/ref/models/expressions.html)。
|
||||
|
||||
**output_field**
|
||||
|
||||
用来表示返回值的[模型字段](http://python.usyiyi.cn/documents/django_182/ref/models/fields.html),它是一个可选的参数。
|
||||
|
||||
**\*\*extra**
|
||||
|
||||
这些关键字参数可以给聚合函数生成的SQL 提供额外的信息。
|
||||
|
||||
具体的聚合函数:
|
||||
|
||||
**avg**
|
||||
|
||||
class **Avg(**expression**,** output_field=None**,**
|
||||
\*\*extra**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.Avg)
|
||||
|
||||
返回给定expression 的平均值,其中expression 必须为数值。
|
||||
|
||||
- 默认的别名:**\<field\>__avg**
|
||||
|
||||
- 返回类型:**float**
|
||||
|
||||
**Count**
|
||||
|
||||
class **Count(**expression**,** distinct=False**,**
|
||||
\*\*extra**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.Count)
|
||||
|
||||
返回与expression 相关的对象的个数。
|
||||
|
||||
- 默认的别名:**\<field\>__count**
|
||||
|
||||
- 返回类型:**int**
|
||||
|
||||
有一个可选的参数:
|
||||
|
||||
> **distinct**
|
||||
|
||||
> 如果**distinct=True**,Count 将只计算唯一的实例。它等同于**COUNT(DISTINCT
|
||||
> \<field\>)** SQL 语句。默认值为**False**。
|
||||
|
||||
**Max**
|
||||
|
||||
class **Max(**expression**,** output_field=None**,**
|
||||
\*\*extra**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.Max)
|
||||
|
||||
返回expression 的最大值。
|
||||
|
||||
- 默认的别名:**\<field\>__max**
|
||||
|
||||
- 返回类型:与输入字段的类型相同,如果提供则为 **output_field** 类型
|
||||
|
||||
**Min**
|
||||
|
||||
class **Min(**expression**,** output_field=None**,**
|
||||
\*\*extra**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.Min)
|
||||
|
||||
返回expression 的最小值。
|
||||
|
||||
- 默认的别名:**\<field\>__min**
|
||||
|
||||
- 返回的类型:与输入字段的类型相同,如果提供则为 **output_field** 类型
|
||||
|
||||
**StdDev**
|
||||
|
||||
class **StdDev(**expression**,** sample=False**,**
|
||||
\*\*extra**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.StdDev)
|
||||
|
||||
返回expression 的标准差。
|
||||
|
||||
- 默认的别名:**\<field\>_\_stddev**
|
||||
|
||||
- 返回类型:**float**
|
||||
|
||||
有一个可选的参数:
|
||||
|
||||
> **sample**
|
||||
|
||||
> 默认情况下,**StdDev**
|
||||
> 返回群体的标准差。但是,如果**sample=True**,返回的值将是样本的标准差。
|
||||
|
||||
**Sum**
|
||||
|
||||
class **Sum(**expression**,** output_field=None**,**
|
||||
\*\*extra**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.Sum)
|
||||
|
||||
计算expression 的所有值的和。
|
||||
|
||||
- 默认的别名:**\<field\>__sum**
|
||||
|
||||
- 返回类型:与输入的字段相同,如果提供则为**output_field** 的类型
|
||||
|
||||
**Variance**
|
||||
|
||||
class **Variance(**expression**,** sample=False**,**
|
||||
\*\*extra**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.Variance)
|
||||
|
||||
返回expression 的方差。
|
||||
|
||||
- 默认的别名:**\<field\>__variance**
|
||||
|
||||
- 返回的类型:**float**
|
||||
|
||||
有一个可选的参数:
|
||||
|
||||
> **sample**
|
||||
|
||||
> 默认情况下,**Variance**
|
||||
> 返回群体的方差。但是,如果**sample=True**,返回的值将是样本的方差。
|
||||
|
||||
**链式过滤**
|
||||
|
||||
查询集的筛选结果本身还是查询集,所以可以将筛选语句链接在一起。像这样:
|
||||
|
||||
**\>\>\>** Entry**.**objects**.**filter(**...**
|
||||
headline_\_startswith**=**'What'**...** )**.**exclude(**...**
|
||||
pub_date_\_gte**=**datetime**.**date**.**today()**...** )**.**filter(**...**
|
||||
pub_date_\_gte**=**datetime(2005, 1, 30)**...** )
|
||||
|
||||
**限制查询**
|
||||
|
||||
Entry**.**objects**.**all()[:5]
|
||||
|
||||
限制查询集记录的条数
|
||||
|
||||
**orderby**
|
||||
|
||||
Entry**.**objects**.**order\_by('headline')[0]
|
||||
|
||||
对查询集进行排序
|
||||
|
||||
Entry**.**objects**.**order\_by('blog__name')
|
||||
|
||||
通过关联字段进行排序
|
||||
|
||||
Entry**.**objects**.**order\_by(Coalesce('summary', 'headline')**.**desc())
|
||||
|
||||
通过Coalesce函数指定多个字段,通过desc()和asc()函数制定排序方向
|
||||
|
||||
**reverse()**
|
||||
|
||||
**reverse()** 方法反向排序QuerySet 中返回的元素。
|
||||
|
||||
**distinct([**\*fields**])**
|
||||
|
||||
返回一个在SQL 查询中使用**SELECT DISTINCT**
|
||||
的新**QuerySet**。它将去除查询结果中重复的行。
|
||||
|
||||
**values(**\*fields**)**
|
||||
|
||||
返回一个**ValuesQuerySet** —— **QuerySet**
|
||||
的一个子类,迭代时返回**字典SET**而不是模型实例**对象SET**。
|
||||
|
||||
每个字典表示一个对象,键对应于模型对象的属性名称。
|
||||
|
||||
**values\_list(**\*fields**,**
|
||||
flat=False**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.values_list)
|
||||
|
||||
与**values()**
|
||||
类似,只是在迭代时返回的是**元组SET**而不是**字典SET**。每个元组包含传递给**values_list()**
|
||||
调用的字段的值 —— 所以第一个元素为第一个字段,以此类推。
|
||||
|
||||
**关联查询**
|
||||
|
||||
通过关联对象的字段进行查询。可以跨越任意深度。
|
||||
|
||||
获取所有**Blog** 的**name** 为**'Beatles Blog'** 的**Entry** 对象:
|
||||
|
||||
Entry**.**objects**.**filter(blog__name**=**'Beatles Blog')
|
||||
|
||||
对于关联关系也可以反向查询
|
||||
|
||||
获取所有的**Blog** 对象,它们至少有一个**Entry** 的**headline** 包含**'Lennon'**
|
||||
|
||||
Blog**.**objects**.**filter(entry__headline__contains**=**'Lennon')
|
||||
|
||||
**select_related**
|
||||
|
||||
**select_related(**\*fields**)**
|
||||
|
||||
返回一个**QuerySet**,当执行它的查询时它沿着外键关系查询关联的对象的数据。它会生成一个复杂的查询并引起性能的损耗,但是在以后使用外键关系时将不需要数据库查询。
|
||||
|
||||
下面的例子解释了普通查询和**select\_related()**
|
||||
查询的区别。下面是一个标准的查询:
|
||||
|
||||
*\# Hits the database.* e **=** Entry**.**objects**.**get(id**=**5)*\# Hits the
|
||||
database again to get the related Blog object.* b **=** e**.**blog
|
||||
|
||||
下面是一个**select_related** 查询:
|
||||
|
||||
*\# Hits the database.* e **=**
|
||||
Entry**.**objects**.**select\_related('blog')**.**get(id**=**5)*\# Doesn't hit
|
||||
the database, because e.blog has been prepopulated\# in the previous query.* b
|
||||
**=** e**.**blog
|
||||
|
||||
**prefetch_related¶**
|
||||
|
||||
**prefetch_related(**\*lookups**)**[**¶**](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet.prefetch_related)
|
||||
|
||||
返回**QuerySet**,它将在单个批处理中自动检索每个指定查找的相关对象。
|
||||
|
||||
**\>\>\>** Pizza**.**objects**.**all()["Hawaiian (ham, pineapple)", "Seafood
|
||||
(prawns, smoked salmon)"...
|
||||
|
||||
问题是每次**Pizza .\_\_ str
|
||||
\__()**要求**self.toppings.all()**它必须查询数据库,因此**Pizza.objects
|
||||
.all()**将在Pizza **QuerySet**中的**每个**项目的Toppings表上运行查询。
|
||||
|
||||
我们可以使用**prefetch_related**减少为只有两个查询:
|
||||
|
||||
**\>\>\>** Pizza**.**objects**.**all()**.**prefetch\_related('toppings')
|
||||
|
||||
**模糊查询**
|
||||
|
||||
Entry**.**objects**.**get(headline__exact**=**"Man bites dog")
|
||||
|
||||
**exact** “精确”匹配。
|
||||
|
||||
Blog**.**objects**.**get(name_\_iexact**=**"beatles blog")
|
||||
|
||||
**iexact**大小写不敏感的匹配
|
||||
|
||||
Entry**.**objects**.**get(headline__contains**=**'Lennon')
|
||||
|
||||
**contains**大小写敏感的包含关系
|
||||
|
||||
Entry**.**objects**.**get(headline_\_icontains**=**'Lennon')
|
||||
|
||||
**icontains**大小写不敏感的包含关系。
|
||||
|
||||
**--------------------------------------------------------------**
|
||||
|
||||
关键概念说明:
|
||||
|
||||
管理器:对应数据库中的表。每个模型都有一个objects管理器,用来调用查询方法。管理器只能通过模型的类进行访问,不能通过模型的实例进行访问。
|
||||
|
||||
查询集:对应数据库中的记录。查询集 是惰性执行的 ——
|
||||
创建[查询集](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet)不会带来任何数据库的访问。你可以将过滤器保持一整天,直到[查询集](http://python.usyiyi.cn/documents/django_182/ref/models/querysets.html#django.db.models.query.QuerySet)
|
||||
需要求值时,Django 才会真正运行这个查询。所以可以放心大胆的查询。
|
||||
|
||||
二者关系:
|
||||
|
||||
管理器是查询集的主要来源。
|
||||
64
Python/Django/django进阶——Settings.md
Normal file
@@ -0,0 +1,64 @@
|
||||
MEIDIA_ROOT
|
||||
|
||||
保存用户上传的目录和系统绝对文件系统路径。
|
||||
|
||||
- 处理从MEDIA_ROOT提供的媒体的URL,用于管理存储的文件。
|
||||
如果设置为非空值,则它必须以斜杠结尾。
|
||||
您将需要将这些文件配置为在开发和生产环境中提供服务。
|
||||
|
||||
- 如果您想在模板中使用{{MEDIA_URL}},请在“模板”的“context_processors”选项中添加“django.template.context_processors.media”
|
||||
|
||||
MEDIA_URL
|
||||
|
||||
引用或者说访问MEIDIA_ROOT中的文件时使用的URL,即客户通过浏览器访问的路径。
|
||||
|
||||
STATIC_ROOT
|
||||
|
||||
用来保存静态文件(搭建网站的css库,scrip脚本,图片),默认值为none。收集静态文件进行部署的目录的绝对路径
|
||||
|
||||
STATIC_URL
|
||||
|
||||
引用STATIC_ROOT中静态文件时使用的URL
|
||||
|
||||
- 如果不是
|
||||
None,这将被用作资产定义(Media类)和staticfiles应用程序的基本路径。
|
||||
|
||||
- 如果设置为非空值,则它必须以斜杠结尾。您可能需要将这些文件配置为在开发中提供服务,并且在生产中肯定需要这样做。
|
||||
|
||||
- 能够构建静态文件相对路径的URL例如将静态文件存储在应用程序中的静态文件夹中。my_app
|
||||
/ static / my_app / example.jpg:
|
||||
|
||||
{% load static %} \<img src="{% static "my_app/example.jpg" %}" alt="My
|
||||
image"/\>
|
||||
|
||||
STATICFILES_DIRS
|
||||
|
||||
此设置定义如果FileSystemFinder查找器启用,staticfiles应用程序将遍历的其位置,例如
|
||||
如果您使用collectstatic或findstatic管理命令或使用静态文件服务视图。也就是说添加静态文件查找位置的绝对路径
|
||||
|
||||
> STATICFILES_DIRS = [ "/home/special.polls.com/polls/static",
|
||||
> "/home/polls.com/polls/static", "/opt/webfiles/common", ]
|
||||
|
||||
- 应将此设置为包含其他文件目录的完整路径的字符串列表
|
||||
|
||||
INSTALLED_APPS = (
|
||||
|
||||
'django.contrib.admin', \#用来提供数据库管理功能
|
||||
|
||||
'django.contrib.auth', \#用来提供用户管理功能,包好访问界面
|
||||
|
||||
'django.contrib.contenttypes', \#用来提供:
|
||||
|
||||
'django.contrib.sessions', \#用来提供session管理功能
|
||||
|
||||
'django.contrib.messages', \#
|
||||
|
||||
'django.contrib.staticfiles', \#用来提供静态文件的查找、访问和管理功能。
|
||||
|
||||
)
|
||||
|
||||
django中自带的app说明
|
||||
|
||||
每个APP应该有自己的model、view、templates。
|
||||
|
||||
总的APP有一个view和template,不需要model
|
||||
29
Python/Django/django进阶——models.md
Normal file
@@ -0,0 +1,29 @@
|
||||
文件上传字段FileField(upload_to=Node,max_length=100, \*\*options)[source]
|
||||
|
||||
- FileField.upload_to
|
||||
|
||||
此属性提供了一种设置上传目录和文件名的方式,可以通过两种方式进行设置。
|
||||
在这两种情况下,该值都将传递给Storage.save()方法。
|
||||
|
||||
- 如果您指定了一个字符串值,它可能包含strftime()格式,将由文件上传的日期/时间替换(以便上传的文件不填满给定的目录)。
|
||||
例如:
|
||||
|
||||
class MyModel(models.Model): \# 文件将会上传到 MEDIA_ROOT/uploads upload =
|
||||
models.FileField(upload_to='uploads/') \# or... \# 文件将会保存到
|
||||
MEDIA_ROOT/uploads/2015/01/30 upload =
|
||||
models.FileField(upload_to='uploads/%Y/%m/%d/')
|
||||
|
||||
- 如果使用默认的FileSystemStorage,则字符串值将被附加到MEDIA_ROOT路径上,以形成存储上传文件的本地文件系统上的位置。
|
||||
如果您正在使用其他存储空间,请检查该存储的文档,以查看它如何处理upload_to。
|
||||
|
||||
- upload_to也可以是可调用的,作为一个函数。
|
||||
这将被调用来获取上传路径,包括文件名。 此 可调用
|
||||
必须接受两个参数,并返回一个Unix样式的路径(带有斜杠),以传递到存储系统。
|
||||
两个参数是:
|
||||
|
||||

|
||||
|
||||
def user_directory\_path(instance, filename): \# file will be uploaded to
|
||||
MEDIA_ROOT/user_\<id\>/\<filename\> return
|
||||
'user_{0}/{1}'.format(instance.user.id, filename) class MyModel(models.Model):
|
||||
upload = models.FileField(upload_to=user_directory_path)
|
||||
178
Python/Django/django进阶——登录验证实现.md
Normal file
@@ -0,0 +1,178 @@
|
||||
**User对象字段**
|
||||
|
||||
- **username**
|
||||
|
||||
- password
|
||||
|
||||
- email
|
||||
|
||||
- first_name
|
||||
|
||||
- last_name
|
||||
|
||||
**创建User**
|
||||
|
||||
- User.objects.create\_user() user.save()
|
||||
|
||||
- manage.py createsuperuser
|
||||
|
||||
- manage.py changepassword username
|
||||
|
||||
**验证User的用户名密码**
|
||||
|
||||
- **authenticate(username, password)**
|
||||
|
||||
**from** **django.contrib.auth** **import** authenticate user **=**
|
||||
authenticate(username**=**'john', password**=**'secret')**if** user **is**
|
||||
**not** None: *\# the password verified for the user* **if** user**.**is_active:
|
||||
**print**("User is valid, active and authenticated") **else**: **print**("The
|
||||
password is valid, but the account has been disabled!")**else**: *\# the
|
||||
authentication system was unable to verify the username and password*
|
||||
**print**("The username and password were incorrect.")
|
||||
|
||||
**关于权限(User本身设置的两个权限已经够用,后台管理员和普通用户)**
|
||||
|
||||
**web请求中的认证**
|
||||
|
||||
- **Django**使用会话(session)和中间件来拦截request对象到认证系统当中。会在每一个请求上提供一个request.user属性,表示当前用户。若果当前用户没有登录,则该属性被设置为AnonymousmousUser的一个实例,否则是User的一个实例。
|
||||
|
||||
- 通过is_authenticated() 区分他们
|
||||
|
||||
**if** request**.**user**.**is\_authenticated(): *\# Do something for
|
||||
authenticated users.* **...else**: *\# Do something for anonymous users.*
|
||||
**...**
|
||||
|
||||
**登录一个用户**
|
||||
|
||||
- 从视图中登入一个用户,使用login函数,接受一个HttpRequest对象和一个User对象。
|
||||
|
||||
- login()使用Django的session框架保存用户的信息,作为服务器端和客户端记住登录状态的工具。
|
||||
|
||||
**from** **django.contrib.auth** **import** authenticate, login **def**
|
||||
**my_view**(request): username **=** request**.**POST['username'] password **=**
|
||||
request**.**POST['password'] user **=** authenticate(username**=**username,
|
||||
password**=**password) **if** user **is** **not** None: **if**
|
||||
user**.**is_active: login(request, user) *\# Redirect to a success page.*
|
||||
**else**: *\# Return a 'disabled account' error message* **...** **else**: *\#
|
||||
Return an 'invalid login' error message.* **...**
|
||||
|
||||
**登出一个用户**
|
||||
|
||||
- 使用logout()函数。接受一个HttpRequest对象并且没有返回值。即使没有用户登入也不会抛出错误。所有的会话session框架中的数据都将会被清除。
|
||||
|
||||
- 能够接受一个URL作为登出后跳转的URL
|
||||
|
||||
**只允许登录的用户访问**
|
||||
|
||||
- 原始方法使用request.user.is_authenticated()并进行重定向到一个登录页面。或者使用一个新的页面对错误信息进行渲染
|
||||
|
||||
**from** **django.conf** **import** settings **from** **django.shortcuts**
|
||||
**import** redirect **def** **my_view**(request): **if** **not**
|
||||
request**.**user**.**is_authenticated(): **return**
|
||||
redirect('**%s**?next=**%s**' **%** (settings**.**LOGIN_URL, request**.**path))
|
||||
*\# ...*
|
||||
|
||||
**from** **django.shortcuts** **import** render **def** **my_view**(request):
|
||||
**if** **not** request**.**user**.**is_authenticated(): **return**
|
||||
render(request, 'myapp/login_error.html') *\# ...*
|
||||
|
||||
- 使用login_required装饰器,比较快捷的方式
|
||||
|
||||
**login\_required([**redirect_field_name=REDIRECT_FIELD_NAME**,**
|
||||
login_url=None**])**
|
||||
|
||||
**from** **django.contrib.auth.decorators** **import** login_required
|
||||
@login\_required**def** **my_view**(request): **...**
|
||||
|
||||
主要完成了下面的事,如果用户没有登入,则重定向到setting.LOGIN_URL,并将当前访问的绝对路径传递到查询字符串中;如果用户已经登入,则正常执行视图。视图的代码可以安全地假设用户已经登入。
|
||||
|
||||
默认情况下,在成功认证后用户应该被重定向的路径存储在查询字符串的一个叫做**"next"**的参数中。如果对该参数你倾向使用一个不同的名字,[**login\_required()**](http://python.usyiyi.cn/documents/django_182/topics/auth/default.html#django.contrib.auth.decorators.login_required)带有一个可选的**redirect_field_name**参数
|
||||
|
||||
**from** **django.contrib.auth.decorators** **import** login_required
|
||||
@login_required(redirect_field_name**=**'my_redirect_field')**def**
|
||||
**my_view**(request):
|
||||
|
||||
可以添加一个login_url参数,用来作为认证失败后重定向的位置
|
||||
|
||||
**from** **django.contrib.auth.decorators** **import** login_required
|
||||
@login_required(login_url**=**'/accounts/login/')**def** **my_view**(request):
|
||||
**...**
|
||||
|
||||
**给已经登录的用户添加访问限制(两个装饰器估计用不到)**
|
||||
|
||||
- 原始方法,检查request.user的不同的字段
|
||||
|
||||
- **user_passes_test** 装饰器,进行重定向。
|
||||
|
||||
- permission_required装饰器,检查是否具有权限。
|
||||
|
||||
- 对基于类的普通视图进行权限控制,可以加装饰器view.dispatch
|
||||
|
||||
**密码更改后session会失效**
|
||||
|
||||
**用户登录认证的视图(方便快速的完成登录注册等操作)**
|
||||
|
||||
**这个真的没看懂怎么用,貌似就是一系列的默认视图,但是……不是很懂**
|
||||
|
||||
**扩展已有的用户模型**
|
||||
|
||||
你可以创建基于[**User**](http://python.usyiyi.cn/documents/django_182/ref/contrib/auth.html#django.contrib.auth.models.User)
|
||||
的[代理模型](http://python.usyiyi.cn/documents/django_182/topics/db/models.html#proxy-models)。代理模型提供的功能包括默认的排序、自定义管理器以及自定义模型方法。如果你想存储新字段到已有的**User**里,那么你可以选择[one-to-one
|
||||
relationship](http://python.usyiyi.cn/documents/django_182/ref/models/fields.html#ref-onetoone)来扩展用户信息。这种
|
||||
one-to-one 模型一般被称为资料模型(profile
|
||||
model),它通常被用来存储一些有关网站用户的非验证性( non-auth
|
||||
)资料。例如,你可以创建一个员工模型 (Employee model):
|
||||
|
||||
**from** **django.contrib.auth.models** **import** User **class**
|
||||
**Employee**(models**.**Model): user **=** models**.**OneToOneField(User)
|
||||
department **=** models**.**CharField(max_length**=**100)
|
||||
|
||||
在视图中的访问方式,可以直接查找代理中的其他数据类型
|
||||
|
||||
**\>\>\>** u **=** User**.**objects**.**get(username**=**'fsmith')**\>\>\>**
|
||||
freds_department **=** u**.**employee**.**department
|
||||
|
||||
要将个人资料模型的字段添加到管理后台的用户页面中,请在应用程序的**admin.py**定义一个[**InlineModelAdmin**](http://python.usyiyi.cn/documents/django_182/ref/contrib/admin/index.html#django.contrib.admin.InlineModelAdmin)(对于本示例,我们将使用[**StackedInline**](http://python.usyiyi.cn/documents/django_182/ref/contrib/admin/index.html#django.contrib.admin.StackedInline)
|
||||
)并将其添加到**UserAdmin**类并向[**User**](http://python.usyiyi.cn/documents/django_182/ref/contrib/auth.html#django.contrib.auth.models.User)类注册的:
|
||||
|
||||
**from** **django.contrib** **import** admin **from**
|
||||
**django.contrib.auth.admin** **import** UserAdmin **from**
|
||||
**django.contrib.auth.models** **import** User **from**
|
||||
**my_user_profile_app.models** **import** Employee *\# Define an inline admin
|
||||
descriptor for Employee model\# which acts a bit like a singleton***class**
|
||||
**EmployeeInline**(admin**.**StackedInline): model **=** Employee can_delete
|
||||
**=** False verbose_name_plural **=** 'employee'*\# Define a new User
|
||||
admin***class** **UserAdmin**(UserAdmin): inlines **=** (EmployeeInline, ) *\#
|
||||
Re-register UserAdmin*admin**.**site**.**unregister(User)
|
||||
admin**.**site**.**register(User, UserAdmin)
|
||||
|
||||
这些Profile models在任何方面都不特殊,它们就是和User
|
||||
model多了一个一对一链接的普通Django models。
|
||||
这种情形下,它们不会在一名用户创建时自动创建, 但是
|
||||
**django.db.models.signals.post_save** 可以在适当的时候用于创建或更新相关模型。
|
||||
|
||||
注意使用相关模型的成果需另外的查询或者联结来获取相关数据,基于你的需求替换用户模型并添加相关字段可能是你更好的选择。但是,在你项目应用程序中,指向默认用户模型的链接可能带来额外的数据库负载。
|
||||
|
||||
为了表明这个模型是对于那个给定的站点,我们还需要配置一个AUTH_PROFILE_MODULE,这是一个字符串,包含两部分信息,由点号相连
|
||||
|
||||
- app名:大小写敏感,一般是你使用manage.py startapp创建时用的名称
|
||||
|
||||
- 你自定义的模型名称,大小写不敏感
|
||||
|
||||
比如,app名为accounts,模型名为UserProfile
|
||||
|
||||
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
|
||||
|
||||
一旦一个用户档案模型(额外信息模型)被定义然后用上述方法指明,每一个user对象都会有一个方法--get_profile()--去返回跟该用户相关的额外信息
|
||||
|
||||
**因为新建的数据库还没有迁移,所以与用户相关的功能还不能实现。那么可以先实现用户登录香瓜的功能。**
|
||||
|
||||
**如用户的注册、登录、登出等功能的相关控制。然后在实现与用户相关的功能,并添加权限控制。**
|
||||
|
||||
**1. 通过代理的方式建立UserNoramal用户扩展类。**
|
||||
|
||||
**配置UserNormal为User表的内联表,在管理页面进行管理。**
|
||||
|
||||
**(由于没有迁移数据库,不能运行admin)**
|
||||
|
||||
**2. 从登录页面开始继续下去,已经完成了各个页面的配置工作。**
|
||||
BIN
Python/Django/media/017b5bc5cc1c5658c2e4b0d2c60d6a66.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
Python/Django/media/1ea5844cdeb119cea0014629f5a98677.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
Python/Django/media/31dee5e6af1761fcf709bd964dbae2e6.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
Python/Django/media/94ceeea49b0fbeef8256fd6c4c3e2e32.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
Python/Django/media/9670ce8128fc0e85e25497e4b5fa4d1c.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
Python/Django/media/d7386f1dbbc74996c289b2a429824bea.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
Python/Django/media/dce0ba0294ba5eabe258c5e8e57a3054.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Python/Django/media/df40d5376061534624358d06423cfa57.png
Normal file
|
After Width: | Height: | Size: 33 KiB |