This commit is contained in:
yinkanglong_lab
2021-03-09 20:51:22 +08:00
parent 99855cd76c
commit a5132d34cc
126 changed files with 9999 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
这个模板层大致又复习了一遍之前没找到的东西又发现了
在模板层中有的内奸标签API真的很有用还有很多有用的其他东西。

View 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的编程来实现。也就是说要跳出到框架之外。
看情况吧,如果真的需要的话,还是要学习这些新的东西。

View 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对应多个valueget()返回最后一个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"). |

View 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()来查询数量后者用的是SQLSELECT 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() 去重**

View 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',),
}]
)

View 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})

View 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.")

View 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)

View 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这则表达式进行查询。

View 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 %}

View 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
kwargsview使用的字典类型的参数。
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))

View 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

View 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回到浏览器中后退刷新查看源文件两个链接地址一样。
![630170720665.png](media/dce0ba0294ba5eabe258c5e8e57a3054.png)
这里写图片描述
5在应用的urls.py中将fan2修改为fan_show。
> url(r\^fan_show/\$, views.fan2,name=fan2),
6回到浏览器中刷新查看源文件两个链接地址不一样。
![630170353712.png](media/df40d5376061534624358d06423cfa57.png)
这里写图片描述
**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回到浏览器中刷新查看源文件如下图
![630165632134.png](media/017b5bc5cc1c5658c2e4b0d2c60d6a66.png)
这里写图片描述
- 使用重定向传递位置参数格式如下:
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回到浏览器中刷新查看源文件如下图
![630165958760.png](media/31dee5e6af1761fcf709bd964dbae2e6.png)
这里写图片描述
- 使用重定向传递关键字参数格式如下:
return redirect(reverse(booktest:fan2, kwargs={id:110,age:26}))
真他妈的日了够了,老子居然又因为拼写错误浪费了这么多时间。

View File

@@ -0,0 +1,58 @@
**http请求处理的MVC结构**
![clipboard.png](media/9670ce8128fc0e85e25497e4b5fa4d1c.png)
**HTTP处理的中间件结构**
![clipboard.png](media/1ea5844cdeb119cea0014629f5a98677.png)
![clipboard.png](media/d7386f1dbbc74996c289b2a429824bea.png)
记住几个重要的预处理函数
**process\_request(self, request)**
request预处理函数
在**Django接收到request**之后但仍未解析URL以确定应当运行的view之前。调用
返回 NoneDjango将继续处理这个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快速生成后台数据管理网站。

View File

@@ -0,0 +1,6 @@
render 使用模板进行渲染
redirect
重定向到一个新的url也就是说我当前没有渲染的视图我交给另外一个动作来处理我提供动作必要的参数。所以传递参数到视图的过程绝对不应该用redirect而是render。
redirect有多种形式。可以是绝对路径、相对路径、动作视图名称 + 必要的参数

View 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 才会真正运行这个查询。所以可以放心大胆的查询。
二者关系:
管理器是查询集的主要来源。

View 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

View 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样式的路径带有斜杠以传递到存储系统。
两个参数是:
![clipboard.png](media/94ceeea49b0fbeef8256fd6c4c3e2e32.png)
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)

View 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. 从登录页面开始继续下去,已经完成了各个页面的配置工作。**

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -0,0 +1,20 @@
**ItemLoader是为了将获取文本进行分解装载到相应的ItemLoader当中。**
**具体方法:**
**def** **parse**(self, response): l **=** ItemLoader(item**=**Product(),
response**=**response) l**.**add_xpath('name', '//div[@class="product_name"]')
l**.**add_xpath('name', '//div[@class="product_title"]')
l**.**add_xpath('price', '//p[@id="price"]') l**.**add_css('stock', 'p\#stock]')
l**.**add_value('last_updated', 'today') *\# you can also use literal values*
**return** l**.**load_item()
ItemLoader在每个字段中包含了一个输入处理器和一个输出处理器。
输入处理器收到数据时理科提取数据通过add_xpath(),add_css(),add_value()方法
之后输入处理器的结果被手气起来并保存到ItemLoader内。
收集到所有的数据后调用ItemLoader.load_item()方法来填充并得到填充后的Item对象。
这是当输出处理器和之前手机到的数据被调用。数据的结果是被分配多啊Item的最终值。

View File

@@ -0,0 +1,6 @@
\>
准确的说scrapy主要就有两部分可以编辑一个使用来处理数据的scrapy.Items,另一个用来仓库
Item的操作包括创建、获取字段的值、设置字段的值、后去所欲的键、获取product列表、获取product字段、社赋值和浅复制、集成扩展item。
Item对象的操作 fields内置字段是item生命中使用到的field对象的名字是一个字典。

View File

@@ -0,0 +1,65 @@
全局命令\<不需要要项目,在命令行中直接运行\>
scrapy startproject myproject
\- 创建一个名为myproject的scrapy项目
scrapy genspider [-t template] \<name\> \<domain\>
\- 创建一个新的spider(-l 列出spider的模板-d 查看模板的内容 -t 使用这个模板)
scrapy -h
\- 查看所有可用的命令
scrapy crawl \<spider\>
\- 使用spider进行爬虫
scrapy check [l] \<spider\>
\- 运行contract检查
scrapy list
\- 列出所欲可能的spider
scrapy edit \<spider\>
\- 使用设定的编辑器编辑spider
scrapy fetch \<url\>
\- 使用scrapy下载器Downloader下载给定的URL并将获取到的内容标准输出
scrapy view \<url\>
\- 用来查看spider获取到的页面因为可能spider获取到的页面跟想要的不同。
scrapy shell [url]
\-scrapy 终端能够使用scrapy内部命令对url返回的内容进行操作。
scrapy parse \<url\> [options]
\- 获取给定的URL并使用相应的spider分析处理。
scrapy settings [options]
\- 获取scrapy的设定。
scrapy runspider \<spider_file.py\>
\- 在未创建项目的情况下运行在一个编写在python文件中的spider
scrapy -version [-v]
\- 输出scrapy版本
scrapy deploy []
\- 将仙姑部署到scrapyd服务。
scrapy bench
\- 运行benchmark测试。

View File

@@ -0,0 +1,44 @@
![scrapy_architecture.jpg](media/8c591d54457bb033812a2b0364011e9c.jpeg)
scrapy引擎
调度器
Spiders
下载器
Item Pipeline
itemloader用来装载item用来容纳itempipeline用来过滤。也负责了指明了存好数据的item的数据流动的方向。itemloader是活动在原始数据和item之间的桥梁。itempipeline是活动在item和具体存储数据的位置之间的桥梁。比如用来操纵数据库、用来写入文件用来提供下一次爬虫的相关信息。
下载器中间件
由调度器具体指挥能够根据引擎发送的request对象封装真正的request请求并且设置请求的响应参数。不同的下载器中间件能够完成不同的任务。
Spider中间件
引擎和Spider之间的钩子。用来处理Spider发送给引擎的request和Item和引擎发送给Spider的response。有点像网络的分层没一层都向发送数据中添加一点内容每一层都从接受数据中获得一点内容。有很多中间件可以在这里过滤掉一些错误。另外如果错误能够越提前的发现则越有利于提高效率。
扩展Extension和信号signal
框架提供了一个很好的扩展机制。在配置文件中声明如果想要在某个地方进行扩展可以通过这种方式在要扩展的地方产生一个独特的信号。然后在扩展类中接受这个信号。接下来对接受到的信号和数据进行处理。最后将执行权返回。通过配置文件中的EXTENSION架子啊和激活。
而且信号能够诶眼催处理,停止处理等。有点像事件驱动机制一样。当产生一个事件,监听器就能监听到,然后做出响应的反应。这种方法,的确有利于扩展。
Link Extractors
从response对象中抽取能够最脏你刚是被过量欧文链接的对象。
Feed exports
在存储数据数据之前对数据进行格式化。数据存储的方式序列化的方式主要通过一下几个类。JSON,JSON
LINES,CSV , XML ,
PICKLE,MARSHAL。同时也用来定义数据存储的方式可以是本地文件系统FTPS3标准输出等。通过URI类实现具体存储的方式。
异常Exception
内置了异常参看手册。主要的异常类有DropItem
有itempipeline跑出用来停止处理item。CloseSpider由Spider的回调函数抛出用来停止spider。IgnoreRequest
由调度器或者下载中间价抛出生命忽略该request。NotConfigured
由任何组件抛出声明其仍然保持关闭。NotSupported声明了一个不支持的特性。

View File

@@ -0,0 +1,43 @@
XPath使用路径表达式来选取XML文档中的节点或者节点集合。节点是通过path或者步来选取的。
1\. 通过已经有的表达式选取节点、元素、属性和内容
nodename 选取此节点的所有子节点
/ 从根节点开始选取
// 从匹配选择的当前节点选择文档中的节点
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
2\. 带有位于的路径表达式,使用[ ]来表示当前节点被选取的一些条件
/bookstor/book[price\>35]/title
3\. 通配符来选取未知的元素一般也用python的re表达式
\* 匹配任何元素的节点
@\* 匹配带有任何属性节点(没有属性的节点不行)
node() 匹配任何类型的接待你。
对于CSS来说选择器与HTML和CSS相关。
.class intro 查找类别下的元素
\#id \#firstname id=\*的所有用户
element p 选择所有的元素
elementelement 并列选择
element element 父子选择
element\>element 父元素选择
element element

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View File

@@ -0,0 +1,20 @@
爬取网站最常见的任务是从HTML源代码中提取数据。常用的库有BeautifulSoup。lxml库Xpath。
Selector 中Xpath和CSS的使用
标签是节点 ,可以有层级
属性使用@来调用
内容要用text()来调用
条件要在[ ]写明白也可以是contains[]
//表示获得所有的某一个标签
./表示下一级的方法
可以使用正则表达式最原始的过滤。
response**.**xpath('//a[contains(@href,
"image")]/text()')**.**re(r'Name:\\s\*(.\*)')

View File

@@ -0,0 +1,73 @@
Spider类定义了如何爬去某个网站包括爬去的动作、分析某个网页。
这个流程再清晰一下 发送请求-\>返回网页-\>分析处理生成数据-\>保存。
对爬虫过程的描述:
1. 初始的URL初始化Request设置回调函数。下载完成生成response并作为参数传给该回调函数。start_requests()来获取start_urls.
2. 在回调函数内分析返回的网页内容返回Item对象或者Request或者一个包括而止的可迭代的容器。放回的Response对象经过处理调用callback函数。
3. 在回调函数内可以使用选择器Xpath解析器等任何解析器来分析内容并根据分析生成数据item
4. 最后spider返回的item将被存到数据库中或者导入文件当中。
Spider crawl mysqpider -a category=electronics
传递spider的参数限定爬去网站的部分。
函数的调用流程
spider的构成
name 名字,作用域内唯一。
allowed_domains可选包含了spider爬取的域名domain列表list
start_urls 从该列表脏欧冠呢开始进行爬去。
start_requests()必须返回一个可迭代对象。该对象包含了spider用于爬去的第一个Request。make_reuest_from_url()将被调用来创建Request对象。
make_requests_from_url(url)该方法接受URL返回requests对象。将URL转换为Request对象。parse()作为回调函数。
parse(response)当response没有指定回调函数时该方法是scrapy处理下载的response的默认方法。parse负责处理response并返回处理的数据以及跟进的URL。所有的Request回调函数必须范式一个包含Request或Item的可迭代的对象。
log(mewwage[,level,component])日志记录
closed(reason)spider关闭时这个函数被调用。
Spider的样例
**import** scrapy**from** myproject.items **import** MyItem**class**
**MySpider**(scrapy**.**Spider): name **=** 'example.com' allowed_domains **=**
['example.com'] start_urls **=** [ 'http://www.example.com/1.html',
'http://www.example.com/2.html', 'http://www.example.com/3.html', ] **def**
**parse**(self, response): sel **=** scrapy**.**Selector(response) **for** h3
**in** response**.**xpath('//h3')**.**extract(): **yield** MyItem(title**=**h3)
**for** url **in** response**.**xpath('//a/@href')**.**extract(): **yield**
scrapy**.**Request(url, callback**=**self**.**parse)
CrawlSpider ( scrapy.contrib.spiders.CrawlSpider)
> rules 包含多个Rule对象的列表。
> parse_start_url(response)当start_url的请求返回时该方法被调用。
XMLFeedSpider
CSVFeedSpider
SitemapSpider
爬取规则(scrapy.contrib.spiders.Rule())
link_extractor 是一个LinkExtracto对象定义了如何从爬取到的页面提取链接。
callback当从link_extractor中获取到链接之后将会调用该函数。该回调函数接受一个response作为第一个参数并返回一个包含Item以及Request对象的列表。不要使用parse
cb_kwargs传递给回调函数的参数的字典。
follow是一个Boolean从response中提取的链接是否需要跟进。
process_links该方法用来过滤也是回调函数。
process_request该规则提取到的每个request队徽调用这个函数并且返回一个request或者None。

View File

@@ -0,0 +1,66 @@
spider 的使用说明:
继承scrapy.spider
name spider的名字
start_urls初始链接
request 发送请求并且捕获相应通过回调函数parse处理response相应
request函数能够发送请求request函数需要一个回调函数来接受请求。默认的request函数调用了parse但是在多次request中需要设置不同的parse函数来处理多次请求
python
回调函数的意思就是在一个函数的某个地方通过一个函数指针调用另外一个函数使得函数跳转。因为python是脚本所以在没有返回值的python函数执行时如果函数跳转到其他地方并不会返回一个值到原来的地方。
轮换useragent的目的
当你使用同一个浏览器的时候同一个useragent会因为过度浪费服务器资源而被禁掉。
scrapy的一些内置特性
scrapy内置的数据抽取其css/xpath/re
scrapy内置结果的输出csv,xml,json
自动处理编码
有丰富的内置扩展
cookies session 客户端和服务器端的缓存机制
Http featurescompressionauthenticationcaching
user-agent spoofing轮换useragent用户代理的意思浏览器的类型
robots.txt 网站中用来告诉爬虫那些资源时可以被访问的,哪些资源时不能被访问的。
crawl depth restriction 限制爬去的深度
itme Pipeline的作用
清洗HTML数据
验证抓取到的数据
检查是否存在重复
存储抓取到的数据到数据库中。
关于parse分析response后返回值的问题
如果parse的返回值是一个request将进行更深层侧的爬虫抓去。
如果parse的返回值是一个item则程序的执行权就会交个itempipeline然后pipeline负责处理返回的item对象。包括这些item对象是否合理。
一个简单爬虫的具体分析步骤:
创建工程
编写item用来结构化分析数据使用
编写spider用来爬去具体的网站
编写和配置pipeline主要实现对生成的item的处理
调试运行代码

View File

@@ -0,0 +1,13 @@
对框架的基本内容有所理解了:
上图:
刚刚发现只有xicidaili.com能够空头访问而微信和百度都不能空头访问。这说明代码运行不了的原因是没有加载头部信息。不不不。xicidaili.com也不饿能进行空头访问知识他在访问的时候自动加载了头部而其他网站都没有加载默认配置为毛子
1\. 增加并发,
通过这一次的运行知道两件事情:
问题一定出在最简单的地方,往往是你对一些习惯性的东西太不了解导致的。
阅读日志文档,了解基础知识真的很重要呀呀呀呀!!!!愚蠢的殷康龙

1
Python/Scrapy/注意.md Normal file
View File

@@ -0,0 +1 @@
以后逐步将手写笔记改为网络端。(节约时间、便于调整,有利于复习)

View File

@@ -0,0 +1,26 @@
**\>程序设计的基础知识**
\>\>程序的定义:为了完成某项任务解决某个问题,计算机及执行的一定的指令
\>\>计算机:实现程序的机器,Enia宾夕法尼亚大学-电子管-晶体管-集成电路
\>\>cup构成冯诺依曼的计算机结构输入设备-存储器-输出设备-控制器-计算器
**\>人与机器的沟通**
\>\>程序设计语言:汇编语言-低级语言-高级语言python-Java
\>\>分类编译型语言source code -compiler- object
CODe。解释性语言sourcecode-interpreter-output
\>\>创始人:吉多·范·罗苏姆蟒蛇
\>\>python解释性语言可移植性强执行效率低设计哲学优雅明确简单
**\>第一个程序hello world**
\>\>print python
\>\>命令行Linux系统下)优点:无需创建文件,立即看到裕运行的结果
脚本IDE编辑器适合编写大型程序更容易纠错更容易修改和执行

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

View File

@@ -0,0 +1,160 @@
当你创建了一个列表,你可以逐项地读取这个列表。这个过程就是迭代
**[python]** [view
plain](http://blog.csdn.net/a168861888m/article/details/78293251)
[copy](http://blog.csdn.net/a168861888m/article/details/78293251)
1. \<span style="font-family:'Times New Roman';font-size:14px;"\>\>\>\> mylist
= [1, 2, 3]
2. \>\>\> **for** i **in** mylist:
3. ... **print**(i)
4. 1
5. 2
6. 3\</span\>
mylist是一个可迭代对象。当你使用一个列表生成式的时候你创建了一个列表也就是一个可迭代对象
**[python]** [view
plain](http://blog.csdn.net/a168861888m/article/details/78293251)
[copy](http://blog.csdn.net/a168861888m/article/details/78293251)
1. \<span style="font-family:'Times New Roman';font-size:14px;"\>\>\>\> mylist
= [x\*x **for** x **in** range(3)]
2. \>\>\> **for** i **in** mylist:
3. ... **print**(i)
4. 0
5. 1
6. 4\</span\>
所有你可以使用 "for...in..."的都是可迭代对象:列表,字符串,文件等等
你经常使用它们因为你可以如你所愿的读取其中的元素,但是你把所有的数据都存贮在内存里,如果你有许多数据的话,这种做法不会是你想要的
生成器
生成器都是可以迭代的,但是你只可以迭代它们一次,因为他们并不是把所有的数据存贮在内存中,它是实时的生成数据
**[python]** [view
plain](http://blog.csdn.net/a168861888m/article/details/78293251)
[copy](http://blog.csdn.net/a168861888m/article/details/78293251)
1. \<span style="font-family:'Times New Roman';font-size:14px;"\>\>\>\>
mygenerator = (x\*x **for** x **in** range(3))
2. \>\>\> **for** i **in** mygenerator:
3. ... **print**(i)
4. 0
5. 1
6. 4\</span\>
看上去都是一样的,除了使用()而不是 []。但是你不可以再次使用 for i in
mygenerator
因为生成器只能被逆代一次他们先计算出0然后就丢掉了0然后再继续逐项计算1计算4
Yield
yield是一个类似 return的关键字不同的是这个函数返回的是一个生成器
**[python]** [view
plain](http://blog.csdn.net/a168861888m/article/details/78293251)
[copy](http://blog.csdn.net/a168861888m/article/details/78293251)
1. \<span style="font-family:'Times New Roman';font-size:14px;"\>\>\>\> **def**
createGenerator():
2. ... mylist = range(3)
3. ... **for** i **in** mylist:
4. ... **yield** i\*i
5. ...
6. \>\>\> mygenerator = createGenerator() \# create a generator
7. \>\>\> **print**(mygenerator) \# mygenerator is an object!
8. \<generator object createGenerator at 0xb7555c34\>
9. \>\>\> **for** i **in** mygenerator:
10. ... **print**(i)
11. 0
12. 1
13. 4\</span\>
这个例子没什么用途,但如果你的函数会返回一大批你只需要阅读一次的数据的时候,这是很方便的。
为了精通
yield你必须理解当你调用这个函数的时候函数里的代码是不会马上执行的。这个函数只是返回生成器对象这有点蹊跷不是吗
那么函数的代码什么时候开始执行呢使用for迭代的时候
现在到了比较的难的一部分:
第一次迭代的时候你的函数开始执行从开始到达yield关键字然后返回第一次迭代的值。然后每次执行这个函数都会继续执行你在函数内部定义的那个循环的下一次再返回那个值直到没有可以返回的值。如果生成器内部没有定义yield
关键词这个生成器被认为是空的。也有可能是因为循环已经结束或者没有满足“If/else”条件
\----------------------------------------------------------------------------------------------------------------------------------------(我是分割线)
更深入聊一下:什么时候使用 field 而不是 return
yield语句暂停函数的执行并向调用者发送一个值但保留足够的状态以使函数能够在其被关闭的位置恢复。
恢复后,该功能在最后一次产量运行后立即继续执行。
**这允许其代码随时间产生一系列值,而不是一次计算它们,并将其像列表一样发送回来。**
我们来看一个例子:
**[python]** [view
plain](http://blog.csdn.net/a168861888m/article/details/78293251)
[copy](http://blog.csdn.net/a168861888m/article/details/78293251)
1. \<span style="font-family:'Times New Roman';font-size:14px;"\>**def**
simpleGeneratorFun():
2. **yield** 1
3. **yield** 2
4. **yield** 3
5.
6. \# Driver code to check above generator function
7. **for** value **in** simpleGeneratorFun():
8. **print**(value)\</span\>
输出:
1 2 3
return返回一个指定的值给它的调用者而yield可以产生一个值序列。当要遍历一个序列但又不想将整个序列存储在内存中的时候我们应该使用yield
yield用于Python生成器中。
一个生成器函数被定义为一个正常的函数,但是只要它需要生成一个值,就应该使用 yield
关键字而不是return。 如果 def 的 body 包含 yield则该函数自动成为生成器函数。
写博客也参考了一些资料(学习一般都是看英文的):
1https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do?page=1&tab=votes\#tab-top
2http://www.geeksforgeeks.org/use-yield-keyword-instead-return-keyword-python/

65
Python/python2/函数.md Normal file
View File

@@ -0,0 +1,65 @@
**\>函数**
\>\>函数定义:完成特定功能的一个语句组,这组语句可以作为一个单位使用,并且给他求个名字,通过函数名执行
\>\>语法:
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51873452)
[copy](http://blog.csdn.net/estom_yin/article/details/51873452)
1. \<span style="font-size:18px;"\> **def** print\_sum(start, stop):
2. """ to calculate the sum from start to stop """
3. result = 0
4. **for** i **in** range(star, stop + 1):
5. result += i
6. **print** 'sum is', result\</span\>
> 第一行定义了一个函数,关键字 def ,函数名 print_sum函数参数start stop
\>\>函数调用
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51873452)
[copy](http://blog.csdn.net/estom_yin/article/details/51873452)
1. \<span style="font-size:18px;"\>print\_sum(a, b)\</span\>
\>\>参数说明
> 形式参数和实际参数
> 缺省参数,定义实参时,给参数赋值
\>\>返回值
> return 语句会终止当前的函数执行
> 返回一个变量
\>\>变量的作用域
> 局部变量:只能在程序特定部分起作用
> 全局变量:能在程序的全局起作用
> 名称的屏蔽作用
> global x 表明x是一个全局变量声明
> pass 语句可作为一个占位符,用于表示此处省略的大量语句
\>\>函数的作用:
> 可以将一个打的问题,分解成一个小的函数,有利于解决问题
> 可以进行信息的封装和隐藏
**\>琐碎的函数知识总结**
\>\>if month in(1, 3, 5, 7, 8, 9, 11, 12):函数in可以表示一个选择范围

View File

@@ -0,0 +1,279 @@
\>列表简介
\>\>是一种内建的数据结构,用来存储一系列的元素
\>\>同JS一样由于解释性语言不必声明数据类型所以数组的元素也可以很灵或的不相同。
\>列表的运算
> index索引运算[]
> 切片运算:[:]
> 拼接运算+
> 重复运算\*
> 成员运算in
> 长度运算len
> 循环for
\>列表方法:
> list.intex()可以返回任意的方法
> my_list[2] = a \#元素赋值
> my_list.append()\#末尾追加元素
> my_list.extend()\#末尾追加子表
> my_list.insert()\#任意位置插入元素
> my_list.pop()结尾删除元素
> my_lise.sort()\#排序
> my_list.remove()\#删除任意位置元素
> my_list.reverse()\#倒序
\>列表应用
\>\>内建函数sum()求和max求最大值min()求最小值
\>\>列表名本身就是一种指针和地址。所以在赋值是只是一个指针的指向赋值给另一个指针的指向
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51916941)
[copy](http://blog.csdn.net/estom_yin/article/details/51916941)
1. \<span style="font-size:14px;"\>程序一\</span\>
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51916941)
[copy](http://blog.csdn.net/estom_yin/article/details/51916941)
1. \<span style="font-size:14px;"\>a = [1, 2, 3, 4]
2. b = a
3. b[1] = 100
4. **print** a[1]
5. 程序二
6. a = [1, 2, 3, 4]
7. b = a[:]
8. b[1] = 100
9. **print** a[1]\</span\>
程序一的输出100因为a和b指向同一个位置
程序二的输出1因为a和b指向不同的位置。
\>\>交换列表中两个元素的值
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51916941)
[copy](http://blog.csdn.net/estom_yin/article/details/51916941)
1. \<span style="font-size:14px;"\>**def** swap(lst, a, b)
2. tmp = lst[a]
3. lst[a] = lst[b]
4. lst[b] = lst[a]
5. x = [10, 20, 30]
6. swap(x, 0, 1)\</span\>
\>\>查找并返回元素位置
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51916941)
[copy](http://blog.csdn.net/estom_yin/article/details/51916941)
1. \<span style="font-size:14px;"\>**def** search(lst, x):
2. **for** i **in** range(len(lst)):
3. **if** lst[i] == x:
4. **return** i
5. **return** -1\</span\>
也可以直接使用lst.index(待查找元素)直接进行查找
\>\>时间复杂度的计算
\>二分查找
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51916941)
[copy](http://blog.csdn.net/estom_yin/article/details/51916941)
1. \<span style="font-size:14px;"\>**def** bi\_search(lst, v):
2. low = 0
3. up = len(lst) - 1
4. **while** low \<= up
5. mid = (low + up) / 2
6. **if** lst[mid] \< v:
7. low = mid + 1
8. **elif** lst[mid] == v:
9. **return** mid
10. **else**:
11. up = mid - 1
12. **return** -1\</span\>
\>排序
\>\>选择排序
![715154122626.png](media/36645b2c7df50743cafd69bff4f6f00e.png)
\>\>冒泡排序
![715154128126.png](media/a524121dffc0de426130c95b7f05fbcf.png)
\>\>使用内置函数
> sortedlst
> lst.sort()
\>嵌套列表
students = [ ['zhang', 84], ['wang', 77], ['li', 100], ['zhao',53] ]
\>列表的解析
\>\>作用:一种有源列表创建新列表的方法
\>\>语法:[表达式for 变量 in 列表 if 条件]
生成函数-变化范围-约束条件
普通方法
> lst = []
> for x in range(1, 10)
> lst.append(x\*\*2)
> print lst
列表解析法:
> lst = [x\*\*2 for x in range(1,10) if x % 2 == 0]
> 生成函数x\*\*2生成范围1-10生成条件x%2==0
\>定义匿名函数lambda
g = lambda x: x \*\* 2
print f(8)
所以可以用一下程序实现嵌套列表的值排序
students = [ ['zhang', 84], ['wang', 77], ['li', 100], ['zhao',53] ]
students.sort(key = lambda x: x[1], reverse = true)
\>元组
\>\>注意事项
1、元组同字符串一样具有不可变性本质上是一个列表
2、append、extend、del等改变列表内容的函数不再适用其它函数可以用
3、用括号直接创建元组引号直接创建字符串方括号直接创建列表
4、元组的括号可以省略直接用逗号隔开相同元组里的不同项
\>\>使用元组赋值
使用元组交换两个值
a, b = b , a
name, domai = 'car@163.com'.split('@') //这样就直接将值赋给两个变量了。
\>\>函数和元组
使用元组可以返回多个函数值
![715160502150.png](media/d8ec8dcdb684175683aa827cdec3d19b.png)
\>\>DSU模式decorate,sort,undecorete修饰排序反修饰
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51916941)
[copy](http://blog.csdn.net/estom_yin/article/details/51916941)
1. \<span style="font-size:14px;"\>**def** sort_by_length(words):
2. \#decorate
3. t = []
4. **for** word **in** words:
5. t.append((len(word),word))
6. \#将元素和元素长度组成一个二元组
7. \#sort
8. t.sort(reverse = true)
9.
10. \#undecorate
11. res = []
12. **for** length, word **in** t:
13. res.append(word)
14. **return** res
15.
16. \</span\>
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51916941)
[copy](http://blog.csdn.net/estom_yin/article/details/51916941)
1. \<span style="font-size:14px;"\>
2.
3. words.sort(key = **lambda** x:len(x),reverse =true)\</span\>
//巧妙地利用了元组对应的灵活性完成了合成和分割

View File

@@ -0,0 +1,60 @@
\>基本的数据类型
\>\>字符串string 使用’或“
\>\>整数integer 21 025 0x15
\>\>浮点数1.48 2.1e2有精度损失
\>\>布尔型boolean True或者False
\>\>复数 1+4j
\>\>使用type函数查看数据类型type小明区分类型
\>运算符与表达式
\>\>算数运算5.0 / 9 \* 32-8隐式类型转换bool-\>int-\>float-\>complex
\>\>+ - \* / % \*\*(指数)
\>\>math模块实现更多算术运算
模块实现一定功能的python脚本的集合
方法import module_name
查看modeldir(math)
查看functionhelpname
\>\>关系运算== != \< \> \<= \>=结果True False
\>\>逻辑运算符 and or not
and
返回最后一次判定的值因为and只有全部判定结束后或者判定到假是才会停止判定所以其返回值可能是最后一个真值或者某个第一个假值
or返回第一个遇到的真值或者最后一个假值当or中有一个是真值是他就会返回这个值
\>\>运算顺序:括号具有最高优先级,由内到外结合。括号-一元运算-算数运算乘除取余//-算数运算加减-比较运算-逻辑非-逻辑与-逻辑或-赋值运算
规则一:自上而下括号最高逻辑最低。
规则二:自左向右依次结合统计运算自左向右
\>变量与简单的输入输出
\>\>变量的定义:用于引用绑定对象的标识符
\>\>语法:变量名=对象(数值、表达式)
\>\>普通的赋值运算符,增量赋值运算符
\>\>变量标识符的定义和C++相同,而且大小写敏感
\>\>raw_input(“输入的提示符”)读取键盘输入,将所输入作为字符看待,需要对输入的字符进行强制的类型转化
\>\>print
“输出提示符”将对象的值输出到控制台上;使用逗号分隔许多对象,输出后会自动添加空格;\\n
\\\\ \\t\\a \\'

View File

@@ -0,0 +1,105 @@
**\>字典结构**
\>\>键值对融合了PHP中的特点
\>\>创建字典,使用成对的花括号{ },使用冒号表示键值对
> 例如my_dict = {'John':879798,'Bob':8757,'mike':725466}
> 其他方法dict(zip([1,2,3],[4,5,6]))或dict([(1,4),(2,5),(3,6)])
\>\>访问字典:使用方括号[ ] ,使用键作为索引
> 例如print my_dict print my_dict['tom']
\>\>字典运算符和方法
> lenmy_dict字典中键值对的数量
> key in my_dict快速判断key是否为字典中的键=\>my_dict.has_key(key)
> for key in my_dict:能够遍历数组中所有的键(不是值)
> my_dict.items()全部的键值对以列表的形式存在好像Python中称数组为列表吧
> my_dict.keys() 全部的键
> my_dict.values()全部的值
> my_dict.clear() 清空字典
\>\>关于文件处理中涉及到的一些函数
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/52345031)
[copy](http://blog.csdn.net/estom_yin/article/details/52345031)
1. \# reading the essay and count the top ten using words
2.
3. f = open('emma.txt')
4.
5. word_freq = {}
6.
7. **for** line **in** f:
8. words = line.strip().split()
9. **for** word **in** words:
10. **if** word **in** word_freq:
11. word_freq[word] += 1
12. **else**:
13. word_freq[word] = 1
14.
15. freq_word = []
16. **for** word, freq **in** word\_freq.items():
17. freq\_word.append((freq, word))
18.
19. freq\_word.sort(reverse=True)
20.
21. **for** freq, word **in** freq\_word[:10]:
22. **print** word
23. f.close()
**\>集合**
\>\>定义:无需不重复元素的集合,和字典相同没有值,只有键
\>\>创建集合x = set() x = {key1,key2,...}
\>\>添加和删除x.add('body') x.remove('body')
\>\>集合的运算符
> \-差集
> &交集
> \|并集
> !=不等于判断
> ==判断相等
> in成员运算
> for枚举运算

132
Python/python2/字符串.md Normal file
View File

@@ -0,0 +1,132 @@
\>字符串的定义
\>\>字符串是一个字符的序列,可以使用‘单引号’或者“双引号”表示。
\>\>使用‘’‘三引号’‘’表示时,可以保留字符串的格式信息。
\>\>可以使用转义字符表示字符串内部的引号。/n回车换行/t制表符
\>字符串的基本运算
\>\>len(字符串):返回字符串的长度
\>\> + 拼接操作name = first_name + "jordan"
\>\> \* 重复操作name \* 3 = "mike mike mike"
\>in运算
\>\> in
判断一个字符串是不是另一个字符串的子串大小写敏感返回一个true或false
> name = 'michael jordan'
> 'a' in name
> 返回true
\>\>for语句
> my_str = "hello word"
> for char in my_str
> 循环体
\>字符串索引index
\>\>字符创中每个字符都有个索引值下标索引0从前向后或-1从后向前开始
\>\>将其视为数组
\>字符串切片(将字符串视为字符串数组)
> 变量名[start:finish:conuntBy]获得子串
> start子序列开始的所以
> finish子序列结束位置的下一个位置
> countby字符串的方向和步长同range的第三个参数当取负数时逆向输出
\>\>字符串的不可变性
> 一个字符串一旦生成内容不可改变,不支持每项的赋值。
> 通过切片改变某个下标对应的字符。
\>\>通过切片生成新的字符串
my_str = my\_str[:1] + 'a' + my_str[2:]
\>\>通过切片获取逆字符串
reverse_str = my\_str[ : :-1]
\>字符串对象提供的函数(又称为方法)
> .replace('被替换的字符','新的字符'):返回新的字符串,不能修改原来字符串的内容。
> .find('查找字符'):查找一个字符
> .split():在制定的地方(默认是空格处),进行切分,返回一个字符串数组。
\>\>文件操作:
> 打开文件
> f =open(filename, mode)/mode=r or w
> 按行读取文件内容
> for line in f:
> pass
> 关闭文件:
> f.close()
> 写入文件
> f.write()
\>\>定义函数判断是否是回文字符串
非递归算法
递归算法
\>字符串比较
\>\>按字典顺序进行比较可以直接使用大于小于号返回true或者false
\>字符串的格式化输入输出
\>\>print "Hello{}good{}.".format(5,'DAY')
用中括号代替需要输出的字符,然后在中括号中进行格式化操作布局,调用.format对象的方法写入输出的内容。
\>\>例如
print 'pi is {: .4f}'.format(math.pi)
print 'pi is {:e}'.format(math.pi)
\>python的正则表达式
判断整个字符串name == 'Michael
判断是否 以 Mi 开始name[:2] == 'Mi
包含 cha 子串:'cha' in name
是否包含 c?a 子串:
是否包含 c\*e 子串?
.表示任意字符
\\d表示一系列数字
[a - z]表示任意一个小写字母

View File

@@ -0,0 +1,3 @@
基本语法规则
![pyre_ebb9ce1c-e5e8-4219-a8ae-7ee620d5f9f1.png](media/fb96ec92f6caab4ab0ac9fe60df68ddc.png)

View File

@@ -0,0 +1,74 @@
\>选择结构
\>\>程序流程图:用简单的图形表示问题的解决步骤;起止框,处理匡,判断框,文档框,流程线,圆形,输入输出框
\>\>语法python中大括号不是分区作用是靠语句块的缩进来体现语句块术语的范围
if 条件:
缩进语句块
其余的语句
if 条件:
缩进语句块
else
缩进语句块
\>\>if语句支持嵌套
\>\>多分支结构elif 条件==else if
条件,有助于简化缩进,是画面更加清晰,可读性更高
涉及到两个典型的例子elif计算多分支结构领先是否安全的例子
\>循环结构
\>\>while条件判断成立则执行循环体不成立则不执行
初始化语句
while 条件语句:
循环体
其它语句
\>\>break结束当前循环体
\>\>continue结束这次循环或者说开始新的循环
\>\>for循环
for element in object
循环体
\>\>range(startstopstep)生成连续整数
\>\>穷举法的使用-鸡兔同笼问题
\>\>循环的嵌套问题
\>程序控制结构的练习题
\>\>if-else 句型
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51854060)
[copy](http://blog.csdn.net/estom_yin/article/details/51854060)
1. **for** i **in** range(2,x):
2. **if** x % i == 0 :
3. **break**
4. **else** :
5. prin 'x is a prime'
当else在循环外与for对齐的时候说明了一个问题有无数个if与else对应当其中的任何一个if执行后都不在执行else否则若if没有执行过则会执行else

View File

@@ -0,0 +1,103 @@
\>递归的实现:
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51892697)
[copy](http://blog.csdn.net/estom_yin/article/details/51892697)
1. \<pre name="code" **class**="python"\>**def** p(n):
2. **if** n ==1 **or** n == 0:
3. **return** 1
\>递归的设计:
> 将问题分解成许多同构的问题,然后以相同的方式解决最终分解的小问题。
> 递归的要素:
> 递归执行的操作
> 递归的结束条件
> 递归的参数传递
\>实例一:兔子序列(菲波那切数列,在自然界一些动植物身上都有体现)
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51892697)
[copy](http://blog.csdn.net/estom_yin/article/details/51892697)
1. **def** fib(n):
2. **if** n == 1 **or** n == 2:
3. **return** 1
4. **else**:
5. **return** fib(n - 1) + fib(n - 2)
6. **print** fib(20)
\>实例二:汉诺塔问题
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51892697)
[copy](http://blog.csdn.net/estom_yin/article/details/51892697)
1. **def** hanoi(n, A, B, C):
2. **if** n == 1:
3. **print** "move", n, "from", A, "to", C
4. **else**:
5. hanoi(n - 1, A, C, B)
6. **print** 'move', n, 'from', A, 'to', C
7. hanoi(n - 1, B, A, C)
8.
9. hanoi(10, 'left', 'Mid', 'Right')
\>实例三:停车问题
> 要求:在固定长度的马路上随机停车,根据车身长度以及随机性特点确定,马路长度与停车数量的关系
**[python]** [view
plain](http://blog.csdn.net/estom_yin/article/details/51892697)
[copy](http://blog.csdn.net/estom_yin/article/details/51892697)
1. **import** random
2. \#if the w big enough, lim parking to 3.7472 named Reni constance
3.
4. **def** parking(low, high):
5. **if** high - low \< 1:
6. **return** 0
7. **else**:
8. x = random.uniform(low, high - 1)
9. **return** parking(low, x) + 1 + parking(x + 1, high)
10. **print** parking(0, 5)
\>递归的优劣
\>\>能使一个蕴含递归关系而且结构复杂的程序简洁精练,增强可读性
\>\>嵌套层次深,函数调用开销大,存在大量的重复计算
\>补充琐碎知识
> random.uniform(low, high) 能产生从low到high的随机数

View File

@@ -0,0 +1,54 @@
csv 模块
逗号分隔值Comma-Separated ValuesCSV有时也称为字符分隔值因为分隔字符也可以不是逗号其文件以纯文本形式存储表格数据数字和文本。 纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。
>>> with open('test.csv', 'wt') as f:
... writer = csv.writer(f) # 把文件对象传给 csv.writer()
... writer.writerow(('ID', '用户', '类型')) # 写入标题
... for i in range(5):
... row = (i, f'用户{i}', f'类型{i}')
... writer.writerow(row)
In: cat test.csv
Out:
ID,用户,类型
0,用户0,类型0
1,用户1,类型1
2,用户2,类型2
3,用户3,类型3
4,用户4,类型4
>>> with open('test.csv', 'rt') as f:
... reader = csv.reader(f)
... for line in reader:
... print(line)
# 输出:
['ID', '用户', '类型']
['0', '用户0', '类型0']
['1', '用户1', '类型1']
['2', '用户2', '类型2']
['3', '用户3', '类型3']
['4', '用户4', '类型4']
>>> with open('test.csv', 'rt') as f:
... reader = csv.DictReader(f) # 键为第一行写入的键名, 值是对应的字段的值
... for line in reader:
... print(line)
... print(line['类型'])
# 输出:
OrderedDict([('ID', '0'), ('用户', '用户0'), ('类型', '类型0')])
类型0
OrderedDict([('ID', '1'), ('用户', '用户1'), ('类型', '类型1')])
类型1
OrderedDict([('ID', '2'), ('用户', '用户2'), ('类型', '类型2')])
类型2
OrderedDict([('ID', '3'), ('用户', '用户3'), ('类型', '类型3')])
类型3
OrderedDict([('ID', '4'), ('用户', '用户4'), ('类型', '类型4')])
类型4
作者:江洋林澜
链接https://www.jianshu.com/p/87a40fbac17f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

View File

@@ -0,0 +1,169 @@
logging 模块
在代码中使用 print() 打印输出是临时性的调试用途的方案。如果希望在线上记录应用日志或者错误日志等, 可以使用 Python 自带的日志模块 logging。
常用的日志记录类型有两种, 一种是写到文件里面, 另外一种是终端输出。日志文件存储下来是为了未来回溯的方便, 终端输出是以便于实时查看。
logging 模块自带了 6 种级别的日志类型。级别如下(变量值越高说明级别越高):
日志级别
变量值
CRITICAL
50
ERROR
40
WARNING
30
INFO
20
DEBUG
10
NOTSET
0
In: import logging
In: logging.warning('Watch out!')
Out: WARNING:root:Watch out!
In: logging.debug("This message won't be printed")
# 无输出
In: logging.basicConfig(level=logging.WARNING) # 使用 basicConfig() 指定默认的日志级别
# getLogger() 自定义 logger 实例, 不同的项目会有自己固定的 logger, 如果能找到 logger 的名字, 就能拿到对应日志的实例
In: logger1 = logging.getLogger('package1.module1')
In: logger2 = logging.getLogger('package1.module2')
In: logger1.warning('This message comes from module1')
Out: WARNING:package1.module1:This message comes from module1
In: logger2.warning('This message comes from module2')
Out: WARNING:package1.module2:This message comes from module2
In: logger2.debug("This message won't be printed")
# 无输出
把日志写入文件
import logging
logging.basicConfig(filename='myapp.log',
level=logging.INFO) # 日志文件为 myapp.log, 级别是 INFO
logging.info('Started') # 写入一行 INFO 的日志 Started
print(logging.root.handlers) # 日志的处理器。root 是默认的一个 logger, 也就是日志实例, 否则得使用 getLogger() 的方式去获得一个 Logger 实例
> python loging_to_file.py
[<FileHandler /home/jiangyanglinlan/myapp.log (NOTSET)>]
> cat myapp.log
INFO:root:Started
最佳使用 logging 的方案
In : import logging
...:
...: logger = logging.getLogger() # 获得一个 logger 的实例
...: handler = logging.StreamHandler() # 实例化 logging 模块自带的 handler
...: formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s') # 定制日志格式, name 为 logger 的名字(默认是 root), levelname 为日志的级别, message 是对应的日志内容
...: handler.setFormatter(formatter) # 设置 formatter
...: logger.addHandler(handler) # 给 logger 添加 handler
...: logger.setLevel(logging.DEBUG) # 设置 logger 的级别
...: logger.debug('This is a %s', 'test')
...:
DEBUG:root:This is a test
2018-04-02 18:34:08,443 root DEBUG this is a tes
logging 模块内置日志格式
格式
说明
%(name)s
生成日志的Logger名称。
%(levelno)s
数字形式的日志级别包括DEBUG, INFO, WARNING, ERROR和CRITICAL。
%(levelname)s
文本形式的日志级别包括DEBUGINFOWARNINGERRORCRITICAL
%(pathname)s
输出该日志的语句所在源文件的完整路径(如果可用)。
%(filename)s
文件名。
%(module)s
输出该日志的语句所在的模块名。
%(funcName)s
调用日志输出函数的函数名。
%(lineno)d
调用日志输出函数的语句所在的代码行(如果可用)。
%(created)f
日志被创建的时间UNIX标准时间格式表示从1970-1-1 00:00:00 UTC计算起的秒数。
%(relativeCreated)d
日志被创建时间与日志模块被加载时间的时间差,单位为毫秒。
%(asctime)s
日志创建时间。默认格式是 “2003-07-08 16:49:45,896”逗号后为毫秒数。
%(msecs)d
毫秒级别的日志创建时间。
%(thread)d
线程ID(如果可用)。
%(threadName)s
线程名称(如果可用)。
%(process)d
进程ID(如果可用)。
%(message)s
日志信息。
作者:江洋林澜
链接https://www.jianshu.com/p/87a40fbac17f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

View File

@@ -0,0 +1,149 @@
os 模块
os 模块中主要包含创建和管理进程或者文件系统内容(比如文件和目录)的函数, os 模块为平台特定的一些模块做了包装, 使得所有平台访问的函数接口相同, 这样就具备了可移植性。下面是 os 模块下一些常用的函数:
方法
说明
用法举例
os.getcwd()
获取当前所在的目录
os.getcwd()
os.chdir()
切换目录
os.chdir('..') (.. 为父级目录, 这里表示切换到上一级目录, 相当于命令行的 cd ..)
os.getenv()
获取系统变量的值(若变量不存在返回 None)
os.getenv('SHELL')
os.environ.getenv()
获取系统变量的值(若变量不存在会引发异常)
os.environ.getenv('SHELL')
os.listdir()
列出目录下的全部文件
os.listdir('dir'), 列出 dir 目录下的全部文件
os.walk()
递归地遍历指定的目录, 对于每个目录都会生成一个元组, 其中包含了目录的路径、该目录下所有的子目录以及该目录下所有文件的列表。它是一个生成器, 可以用 list() 转换成一个列表
os.walk('dir'), list(os.walk('dir'))
os.makedir()
创建一个目录, 只能创建单层目录, 若创建多层目录会报错
os.makedir('dir'), 创建一个名为 dir 的目录
os.makedirs()
创建多层目录
os.makedirs('/dir2/dir3')
os.remove()
删除指定文件
os.remove('1.txt'), 删除当前目录下的 1.txt 文件
os.rmdir()
删除目录
os.rmdir('dir1'), 删除当前目录下的 dir 目录
os.rename()
重命名文件或者目录
os.rename('dir2', 'dir1'), 将 dir2 目录重命名为 dir1
作者:江洋林澜
链接https://www.jianshu.com/p/87a40fbac17f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
os.path 模块、
os 模块下有一个独有的 path 子模块, 可以使用 os.path.函数名字 的方式调用, 也可以 import os.path。os.path 模块是和路径有关的。下面是此模块下一些常用的函数:
方法
说明
os.path.basename()
获得指定文件路径的文件名字
os.path.dirname()
获得文件路径的目录名字
os.path.exists()
判断文件或者目录是否存在
os.path.isdir()
判断指定路径是否是目录
os.path.isfile()
判断指定路径是否是文件
os.path.join()
拼接路径
os.path.split()
路径拆分
os.path.splitext()
获得路径的后缀
In: import os
In: p = '/home/jiangyang/a.txt'
In: os.path.basename(p) # 获得指定文件路径的文件名字
Out:
a.txt
In: os.path.dirname(p) # 获得文件路径的目录名字
Out:
/home/ubuntu
In: os.path.join('\\Users', 'jiangyang', 'flask\\app.py') # windows 下
Out:
\Users\jiangyang\flask\app.py
In: os.path.join('/Users', 'jiangyang', 'flask/app.py') # Ubuntu 下
Out:
/Users/jiangyang/flask/app.py
In: os.path.split(p) # 路径拆分
Out:
('/home/ubuntu', 'a.txt')
In: os.path.splitext(p) # 获得路径的后缀
Out:
('/home/ubuntu/a', '.txt')
作者:江洋林澜
链接https://www.jianshu.com/p/87a40fbac17f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

View File

@@ -0,0 +1 @@
>> 实现文件读写

View File

@@ -0,0 +1,65 @@
datetime 模块
datetime 模块用来完成日期和时间的解析、格式化和算术运算等。
In: import datetime
In: now = datetime.datetime.now() # 获取当前时间
In: now
Out: datetime.datetime(2018, 4, 14, 21, 49, 7, 733048)
In: now.year, now.month, now.day, now.hour, now.minute
Out: (2018, 4, 14, 21, 49)
In: today = datetime.date.today()
In: today
Out: datetime.date(2018, 4, 14)
In: today.year, today.month, today.day
Out: (2018, 4, 14)
In: d1 = datetime.date(2010, 9, 1)
In: d1
Out: datetime.date(2010, 9, 1)
# 可以使用 datetime.timedelta 对象进行时间的运算, 支持秒、分钟、小时、天、周
In : print('seconds :', datetime.timedelta(seconds=1))
...: print('minutes :', datetime.timedelta(minutes=1))
...: print('hours :', datetime.timedelta(hours=1))
...: print('days :', datetime.timedelta(days=1))
...: print('weeks :', datetime.timedelta(weeks=1))
...:
Out:
seconds : 0:00:01
minutes : 0:01:00
hours : 1:00:00
days : 1 day, 0:00:00
weeks : 7 days, 0:00:00
In: hour = datetime.timedelta(hours=1)
In: hour.total_seconds
Out: <built-in method total_seconds of datetime.timedelta object at 0x0000028F5609F418>
In hour.total_seconds() # 获得一个小时的秒数
Out: 3600.0
In: today = datetime.date(2010, 9, 1)
In: today + datetime.timedelta(days=1) # 加上一天
Out: datetime.date(2010, 9, 2)
In: today - datetime.timedelta(days=1) # 减去一天
Out: datetime.date(2010, 8, 31)
时间格式化
In: dt_format = '%Y-%m-%d %H:%M:%S'
In: s = datetime.datetime.now().strftime(dt_format)
In: print('strftime:'s)
Out: strftime: 2018-04-14 22:17:27
In: d = datetime.datetime.strptime(s, dt_format)
In: print('strptime:', d)
Out: strptime: 2018-04-14 22:17:27
In: d
Out: datetime.datetime(2018, 4, 14, 22, 17, 27)
作者:江洋林澜
链接https://www.jianshu.com/p/87a40fbac17f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

View File

@@ -0,0 +1,104 @@
sys 模块
sys 模块提供了特定系统的配置和操作。
方法
说明
sys.platform
用来构建解释器的操作系统平台
sys.version
构建时的版本信息, 包含完整的版本号和构建日期、编译器、平台信息等
sys.version_info
同样是版本信息, 但不是字符串, 可以直接获得对应类型版本的信息
sys.path[0]
搜索模块的路径列表
sys.modules.get()
已经导入的模块列表
sys.getrefcount()
查看对象的引用计数
sys.getsizeof()
以字节byte为单位返回对象大小。这个对象可以是任何类型的对象。 所以内置对象都能返回正确的结果 但不保证对第三方扩展有效,因为和具体实现相关。
作者:江洋林澜
链接https://www.jianshu.com/p/87a40fbac17f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
sys.getrefcount
Python 使用引用计数和垃圾回收来完成字段的内存管理, 当一个对象的引用数降为 0, 就会自动标记为回收。在实际开发中, 可能因为 debug 或者调试的需要, 需要了解引用计数, 就可以使用 sys.getrefcount()。
import sys
d = []
print(sys.getrefcount(d))
# 输出 2
x = d
print(sys.getrefcount(d))
# 输出 3
del x
print(sys.getrefcount(d))
# 输出 2
上面的计数比预期多一个, 是因为 getrefcount() 本身也会维护一个临时引用。
sys.getsizeof
了解对象的引用计数不足以发现内存泄漏, 可以使用 sys.getsizeof 辅助, 这样可以确定对象消耗内存的情况。
# 打印 Python 内置数据结构占用的字节数
for obj in ({}, [], (), 'string', 1, 12.3):
print(obj.__class__.__name__, sys.getsizeof(obj))
# 输出:
dict 240
list 64
tuple 48
str 55
int 28
float 24
命令行参数 sys.argv
在命令行下运行一个 Python 程序, 可以通过 sys.argv 获取脚本的名字和参数。有个 argv.py, 代码如下:
import sys
script_name, *args = sys.argv
print(f'Script: {script_name}')
print(f'Arguments: {args}')
> python argv.py
Script: argv.py
Arguments: []
> python argv.py -v
Script: argv.py
Arguments: ['-v']
> python argv.py -v -v -e 'foo'
Script: argv.py
Arguments: ['-v', '-v', '-e', "'foo'"]
作者:江洋林澜
链接https://www.jianshu.com/p/87a40fbac17f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。