Python常用知识
Python常用知识
##########################################################
# Web 框架的原理
# socket 服务端,收发的消息就是按照 HTTP 协议的格式
# socket 客户端,浏览器
#
# wsgiref模块
# Python内置的一个收发socket消息的模块
#
# HTTP 协议
# 请求 浏览器给服务端发消息叫请求(request)
# 响应 服务端给浏览器回消息叫响应(response)
# 请求方法
# Get POST ...
# 版本号: HTTP/1.1
# 默认端口:
# HTTP:80
# HTTP:443
#
# Python Web 框架分类
# a.发送 socket 消息,按照 HTTP 协议解析消息的
# b.字符串替换,用来实现动态网页的
# c.业务逻辑
#
# 框架
# 1.自己实现 a、b、c
# tornado
# 2.自己实现 b 和 c,使用第三方的 a
# Django
# 3.自己实现c,使用第三方的 a
# Flask
#
# Django
# 1.Django 的版本
# 1. LTS 版本 Long Team support
# 2.安装
# pip install django==1.11.11
# pip install django==1.11.11 -i http://pypi.tuna.tsinghua.edu.cn/simple
# 3.创建 Django 项目
# 1.命令行
# django-admin startproject mysite
# 2.PyCharm
# File -> new project -> ...
# 4.启动
# 1.命令行
# 1.进入执行的根目录
# 2.执行: python manage.py runserver 127.0.0.8080
# 2.PyCharm
# 1.点绿色三角
# 2.前提是左侧框框中的内容和项目名一致的
# 5.目录结构
# mysite
# __init__py
# settings.py 项目配置文件
# urls.py 路径和函数的对应关系
# wsgi.py
# static 项目的静态文件目录
# templates 项目的HTML文件目录
# db.sqlite3 Django 开发环境默认的文件数据库
# manage.py 项目的命令行入口文件
# 6.配置文件 mysite/settings.py
# 1.BASE_DIR ---> 项目的根目录
# 7.form表单提交数据的三个要素
# 1.form 标签必须要有 action 和 method 属性,如果有上传文件还需要设置enctype=multipart/form-data
# 2.所有获取用户输入的标签必须放在 form 表单中,必须要有 name 属性
# 3.必须要有 submit 按钮
##########################################################
# 实例 文件上传
from django.conf import settings
import os
file_obj = request.FILES.get('file_name')
# 判断当前是否存在
file_name = file_obj.name
if os.path.exists(os.path.join(settings.BASE_DIR, file_name)):
# 如果存在同名的文件
name, suffix = file_name.split('.')
name += '2'
file_name = name + '.' + suffix
# 从上传文件对象里一点一点读取数据,写到本地
with open(file_name, 'wb') as f:
# 从上传文件对象里一点一点读取数据
for chunk in file_obj.chunks():
f.write(chunk)
##########################################################
# 8.Django 基础必会三件套
# from django.shortcuts import HttpResponse, render, redirect
# 1.HttpResponse('ok') ---> 把字符串的 OK 转成二进制,然后按照 HTTP 响应的格式要求返回
# 返回一个指定的字符串时
# 2.render(request, 'login.html') ---> 打开文件,读取内容,按照响应格式返回
# 返回一个 HTML 文件
# 3.render(request, 'login.html', {"key": "value"}) ---> 打开文件,读取内容,按照响应格式返回 {{ key }}
# 返回一个 HTML 文件
# 1. 注意:特殊符号的替换这一步发生在 Django 服务端
# 4.redirect("/index/") ---> 在同网站不同地址间跳转(返回的是重定向的)
# 5.redirect('https://www.luffycity.com') ---> 让你的浏览器访问我指定的网址
# 跳转
# 1. 路径可以为相对路径('/book_list/'),绝对路径('https://www.luffycity.com')
# 2. 给浏览器返回的是一个特殊的响应,这个响应类似于一个命令,让浏览器去访问我指定的URL
# 9.request 所有和请求相关的数据都封装在这个 request 对象中
# 1.request.method --> 返回的是当前这次请求的方法(全大写): GET/POST
# 2.request.GET --> 取到 URL 里面携带的参数,类似于字典的数据结构
# 3.request.POST --> 取到 POST 提交的数据(form表单提交的数据),类似于字典的数据结构
# 10.Django的模板语言(HTML 中的特殊符号)
# {{ name }} {'name': '闷骚哥'}
# {{ 变量名 }}
# 11.程序连 mysql
# 使用 pymysql 模块
# 1.导入 pymysql 模块
# 2.创建连接
# 3.获取执行命令的游标
# 4.用游标去执行 SQL 语句
# 5.获取 SQL 语句的执行结果
# 6.关闭游标
# 7.关闭连接
#
# 创建一种工具帮你翻译 SQL 语句 --> ORM
# 优点:
# 1.开发效率高
# 2.开发不用直接写 SQL 语句
# 3.后端连得数据库变了,ORM代码不用变(适配性好)
# 缺点:
# 1.执行效率低
# 1.把ORM语句翻译成SQL语句有一定时间
# 2.ORM翻译的SQL语句有可能不是最优的SQL语句
#
# ORM的对应关系
# ORM DB
# 类 <===> 数据表
# 属性 <===> 字段
# 对象 <===> 数据行
#
# 以后就不会再想写 SQL 语句了
# 12.Django 项目 app ---> 项目中又分了一级 Python 包,不同的功能放到不同的包里面
# 13.配置settings.py
# 1.创建 app
# python manage.py startapp app01
# 2.告诉 Django 创建了一个 app
# 在 settings.py 找那个的 INSTALLED_APPS 中添加新创建的 app,INSTALLED_APPS = ['app 名',]
INSTALLED_APPS = [
# 告诉Django我自己新建了一个名叫app01的应用,推荐下面的写法
'app01.apps.App01Config',
# 'app01'
]
# 3.静态文件相关
STATIC_URL = 'static' # 别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static'),
]
# 4. TEMPLATES
'DIRS': [os.path.join(BASE_DIR, 'templates')]
# 14.Django中ORM的使用
# 1.用处
# 1.操作数据表
# 2.操作数据行
# 2.使用
# 1.手动创建一个数据库
# -> create database mysite charset=utf8;
# 2.告诉 Django 连哪个数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 连接数据库的类型
'NAME': 'mysite', # 数据库名
'HOST': '127.0.0.1', # 数据库主机地址
'PORT': 3306, # 数据库的端口
'USER': 'root',
'PASSWORD': '',
'OPTIONS': {
"init_command": "SET sql_mode='STRICT_TRANS_TABLES'",
}
}
}
# 3.用什么连数据库?
# 利用第三方的包,比如第三方包:pymysql 和 MySQLdb
# 告诉 Django 用 pymysql 模块代替默认的 MySQLdb 去连接 MySQL 数据库
# 和 settings.py 同级的 __init__.py 写上
import pymysql
pymysql.install_as_MySQLdb()
# 4.在 app/models.py 的文件中创建类
# 类必须继承 models.Model
# 5.另一个命令
# 1.python manage.py makemigrations ---> 找个小本本把 models.py 的变更记录一下
# 2.python manage.py migrate ---> 把上面的变更记录翻译成 SQL 语句,去数据库执行
# 3.ORM 查询
# 1.User.objects.filter(name='闷骚哥', pwd='123')
# 4.图书管理系统之出版社的增删改查
# 1.表结构设计
# 1.出版社
# id name
# 2.作者
# id name
# 3.书
# id title 出版社_id
# 4.作者_书_关系表
# id 书_id 作者_id
# 2.ORM 增删改查
# 1.类名.objects.all() ---> 返回一个列表
# 2.类名.objects.filter(条件) ---> 返回一个列表,可以找到多个,找不到也不报错
# 3.类名.objects.get(条件) ---> 返回一个对象,有且只能找到一个,找不到会报错
# 4.类名.objects.create(name='') ---> 创建一个对象,返回的就是刚创建的对象
# 5.类名.objects.filter(id=).delete ---> 删除
# 6.obj = 类名.objects.get(id='')
# obj.name = '新值' ---> 修改对象的属性(修改数据行某个字段的值)
# obj.save() ---> 把修改同步到数据库
# 3.Django 模板语言
# 1.for 循环
# {% for i in ret %}
# {{ i }}
# {{ forloop.counter }} ---> for 循环从 1 开始计数
# {{ forloop.counter0 }} ---> for 循环从 0 开始计数
# {% endfor %}
# 4.出问题就是单词写错了! 99%
# 5.HTML a 标签 href 属性
# 1.写绝对 URL
# 2.写相对 URL(同网站之间跳转)
# 3.瞄点(同网页标签之间的跳转)
# 6.ORM 创建字段
id = models.AutoField(primary_key=True) # -> 创建一个自增的 ID 列作为主键
email = models.CharField(max_length=24) # -> varchar(32)
# 5.书籍的增删改查
# 1.表结构设计
# 1.id title 出版社_id
# 2.SQL
# create table book (
# id int primary key auto_increment,
# title varchar(30) not null,
# press_id int not null,
# constraint fk_press foreign key(press_id) references press(id)
# on delete cascade
# on update cascade
# )
# 3. ORM外键的语法
press = models.ForignKey(to='Press', on_delete=models.CASCADE)
# 书
class Book(models.Model):
id = models.AutoField(primary_key=True) # 自增id主键
title = models.CharField(max_length=30) # 书名
price = models.IntegerField() # 价格
# Django 1.11 默认就是级联删除, Django 2.0之后必须指定on_delete
# to=关联的表名
press = models.ForeignKey('Press', on_delete=models.CASCADE)
# 4. 外键查询的语法
# book_obj.press --> 取到的是和这本书关联的出版社对象
# book_obj.press_id --> 数据库中实际保存的外键id
# 4.给数据库总已经存在的表添加另外一个字段,这个字段既没有默认值也不能为空,
# ORM 就不知道数据库中已经存在的数据该怎么处理
# 在命令行界面会提示两个选择
# 1.输入1,然后在输入一个一次性的默认值
# 2.输入2,退出此次变更记录,手动在models.py中做修改
# null=True --> 让该字段可以为空
# default=默认值 --> 给该字段指定一个默认值
# 2. 书籍的增删改查
# 1.查询
# 1.book_obj.press --> ORM层面封装的,返回的是和我这本书关联的出版社对象
# 2.book_obj.press_id --> 数据库中真正存在的字段,保存的是和我关联的出版社id值
# 2. 增加
# 1. 用select标签把已经存在的出版社在页面上展示出来
# 让用户去选择
# 使用的是:模板语言的for循环
# 3. 删除
# 1. 类似于昨天的操作
# 2. 补充一个3秒钟之后跳转到指定页面的操作
# 1. location.href
# 2. setTimeout()
# 3. setinterval()
# <script>
# // 每隔一秒钟就修改 s1 的text
# let currentNum = document.getElementById('s1').innerText;
# let t2 = setInterval(function () {
# currentNum = document.getElementById('s1').innerText;
# document.getElementById('s1').innerText = currentNum - 1;
# if (currentNum == 1) {
# clearInterval(t2);
# location.href = '/book_list/';
# }
# }, 1000);
# </script>
# 4. 编辑
# 1. 类似于于昨天的操作
# 2. 用select标签展示默认的出版社
# 1. Django模板语言中的if判断
# {% if 条件 %}
# ...
# {% else %}
# ...
# {% endif %}
# 6.多对多关系
#
# 作者 <--> 书籍
#
# 1.表结构设计
# 1.SQL设计
# -- 创建作者表
# create table author(
# id int primary key auto_increment,
# name varchar(32) not null
# );
#
# -- 创建作者和书的关系表
# create table author2book(
# id int primary key auto_increment,
# author_id int not null,
# book_id int not null,
# constraint fk_auther foreign key (author_id) references author(id) on delete cascade on update cascade
# constraint fk_book foreign key (book_id) references book(id) on delete cascade on update cascade
# };
# 2.ORM版
# 1. 第一版:
# 自己创建第三张表
# 2. 第二版
# 让ORM帮我们创建第三张表
# models.ManyToManyField()
# 作者
class Author(models.Model):
id = models.AutoField(primary_key=True) # 自增id主键
name = models.CharField(max_length=32) # 作者名字
books = models.ManyToManyField(to='Book') # 只是ORM层面建立的一个多对多关系,不是作者表的一个字段
#
def __str__(self):
return '<这是一个作者对象,它的名字是:{}>'.format(self.name)
# 3. 第三版
# 待补充...(ORM进阶操作的时候)
# 2.作者的增删改查
# 1.查询
# author_obj.books --> 得到的只是一个关联关系,并不能拿到数据
# author_obj.books.all() --> 得到和我这个作者关联的所有书籍对象列表
# 2.添加
# 1. add()
# 2. getlist()
# 3.删除
#
# 4.编辑
# 1. 模板语言中
# {% if book in author.books.all %}
# 2. ORM编辑多对多
# 1. 不能直接操作第三张关系表
# 2. 借助ORM给提供的方法
# 1. all() --> 查询所有
# 2. add(id1,id2) --> 修改
# 3. set([id1, id2]) --> 修改
# 4. clear() --> 清除对应关系
##########################################################
# 实例 作者数据的增删改查
############################
from django.shortcuts import render, HttpResponse, redirect
from app01.models import User, Press, Book, Author
from django.conf import settings
############################
# 作者展示函数
def author_list(request):
# 1.去数据库查询所有的作者数据
author_data = Author.objects.all()
# for author in author_data:
# print(author)
# # 取到每个作者出版的书籍
# # print(author.books) # 是一个 ORM 提供的桥梁(工具),帮我找对应关系
# print(author.books.all())
# 2.在页面上展示出来
return render(request, 'author_list.html', {'author_list': author_data})
############################
# 添加作者
def add_author(request):
if request.method == "POST":
# 1.取到用户填写的信息
new_author_name = request.POST.get('author_name')
# book_ids = request.POST.getlist("books") # --> 这个只能取到一个值
book_ids = request.POST.getlist("books")
# 2.添加到数据库
# 2.1.创建新的作者
author_id = Author.objects.create(name=new_author_name)
# 2.2.创建新作者和书的对应关系
# 两种方法都可以
author_id.books.add(*book_ids) # 参数是一个一个单独的id值
# author_id.books.set(book_ids) # 参数是书籍id值的列表
# 3.跳转到作者列表页
return redirect('/author_list/')
# 1.获取所有的书籍信息
book_data = Book.objects.all()
# 2.返回一个页面给用户,让用户填写作者信息
return render(request, 'add_author.html', {'book_list': book_data})
############################
# 删除作者
def delete_author(request):
# 1.取到要删除的作者的id值
delete_author_id = request.GET.get("id")
# 2.通过id找到数据,并删除
Author.objects.filter(id=delete_author_id).delete()
# 3.让用户再访问作者列表页面
return redirect('/author_list/')
############################
# 编辑作者
def edit_author(request):
# 1.取到要编辑的作者的id值
edit_author_id = request.GET.get('id')
# 2.找到要编辑的作者对象
edit_author_obj = Author.objects.get(id=edit_author_id)
if request.method == "POST":
# 3.拿到编辑之后的数据
new_author_name = request.POST.get('author_name')
new_book_ids = request.POST.getlist('book_ids')
# 4.去数据库修改
# 4.1.修改作者表
edit_author_obj.name = new_author_name
edit_author_obj.save()
# 4.2.修改作者和书的关系表
edit_author_obj.books.set(new_book_ids)
# 5.跳转到作者列表页
return redirect('/author_list/')
# 2.2.找到所有的书籍对象
book_data = Book.objects.all()
# 3.返回一个页面
return render(request, 'edit_author.html', {'author': edit_author_obj, 'book_list': book_data})
############################
# 作者展示HTML页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>作者列表</title>
</head>
<body>
<a href="/add_author/">添加作者</a>
<table border="1">
<thread>
<tr>
<th>序号</th>
<th>作者id</th>
<th>作者姓名</th>
<th>作者作品</th>
<th>操作</th>
</tr>
</thread>
<thbody>
{% for author in author_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ author.id }}</td>
<td>{{ author.name }}</td>
<td style="text-align: center">
{% for book in author.books.all %}
{% if forloop.last %}
《{{ book.title }}》
{% else %}
《{{ book.title }}》,
{% endif %}
{% empty %}
暂无作品
{% endfor %}
</td>
<td>
<a href="/delete_author/?id={{ author.id }}">删除</a>
<a href="/edit_author/?id={{ author.id }}">编辑</a>
</td>
</tr>
{% endfor %}
</thbody>
</table>
</body>
</html>
############################
# 添加作者HTML页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加作者</title>
</head>
<body>
<h1>添加作者</h1>
<form action="" method="post">
{% csrf_token %}
<input type="text" name="author_name">
<select name="books" multiple="multiple">
{% for book in book_list %}
<option value="{{ book.id }}">{{ book.title }}</option>
{% endfor %}
</select>
<input type="submit">
</form>
</body>
</html>
############################
# 修改作者HTML页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>编辑作者</title>
</head>
<body>
<h1>编辑作者</h1>
<form action="" method="post">
{% csrf_token %}
<input type="text" name="author_name" value="{{ author.name }}">
<select name="book_ids" multiple>
{% for book in book_list %}
{% if book in author.books.all %}
<option value="{{ book.id }}" selected>{{ book.title }}</option>
{% else %}
<option value="{{ book.id }}">{{ book.title }}</option>
{% endif %}
{% endfor %}
</select>
<input type="submit">
</form>
</body>
</html>
##########################################################
# Django模板语言
# 1. 基础语法
# 1. 变量相关{{ 变量名 }}
# 2. 逻辑相关 {% ... %}
#
# 当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。 变量的命名包括任何字母数字以及下划线 ("_")的组合。
# 变量名称中不能有空格或标点符号。
#
# 点(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询:
# 字典查询(Dictionary lookup)
# 属性或方法查询(Attribute or method lookup)
# 数字索引查询(Numeric index lookup)
#
# 注意事项:
# 1.如果计算结果的值是可调用的,它将被无参数的调用.调用的结果将成为模版的值。
# 2.如果使用的变量不存在,模版系统将插入string_if_invalid选项的值,它被默认设置为'' (空字符串)。
###############################
# view中代码:
def template_test(request):
l = [11, 22, 33]
d = {"name": "alex"}
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def dream(self):
return "{} is dream...".format(self.name)
Alex = Person(name="Alex", age=34)
Egon = Person(name="Egon", age=9000)
Eva_J = Person(name="Eva_J", age=18)
person_list = [Alex, Egon, Eva_J]
return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})
###############################
# 模板中支持的写法:
{# 取l中的第一个参数 #}
{{ l.0 }}
{# 取字典中key的值 #}
{{ d.name }}
{# 取对象的name属性 #}
{{ person_list.0.name }}
{# .操作只能调用不带参数的方法 #}
{{ person_list.0.dream }}
#
# 2. filter(过滤器)
# 1. 基础语法
# {{ 变量|方法名:'参数' }}
# 注意:|和:左右都不要加空格
# 2.常用的内置filter
# 1.default
# 如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。
# 如果value没有传值或者值为空的话就显示nothing
{{ value|default:"nothing"}}
# 2.length
# 返回值的长度,作用于字符串和列表。
# 返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4
{{ value|length }}
# 3.filesizeformat
# 将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:
# 如果 value 是 123456789,输出将会是 117.7 MB。
{{ value|filesizeformat }}
# 4.slice
# 切片
{{value|slice:"2:-1"}}
# 5.date(重点)
# 格式化
{{value|date:"Y-m-d H:i:s"}}
# 复习时间操作
import time
import datetime
# 创建一个时间 2018-10-01
t1 = time.strptime('2018-10-01', '%Y-%m-%d')
# 结构化时间
print(t1)
print(t1.tm_year)
# 把时间格式转化成指定格式字符串:2018.10.01
t2 = time.localtime()
print(t2)
t3 = time.strftime('%Y.%m.%d', t2)
print(t3)
# 时间间隔
# 加一天
t4 = datetime.datetime.now()
print(t4)
print(type(t4))
t5 = t4 + datetime.timedalta(days=1)
print(t5)
# 加一年
t6 = t4 + datetime.timedalta(weeks=52)
print(t6)
# 6.safe
# Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。
# 但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,
# 这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。
# 为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码
# 是安全的不必转义。
# 比如:
value = "<a href='#'>点我</a>"
{{value|safe}}
# 7.truncatechars
# 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列("...")结尾。
# 参数:截断的字符数
{{ value|truncatechars:9}}
# 8.truncatewords
# 在一定数量的字后截断字符串。
{{ value|truncatewords:9}}
# 9.cut
# 移除value中所有的与给出的变量相同的字符串
# 如果value为'i love you',那么将输出'iloveyou'.
{{ value|cut:' ' }}
# 10.join
# 使用字符串连接列表,例如Python的str.join(list)
# 11.timesince
# 将日期格式设为自该日期起的时间(例如,“4天,6小时”)。
# 采用一个可选参数,它是一个包含用作比较点的日期的变量(不带参数,比较点为现在)。
# 例如,如果blog_date是表示2006年6月1日午夜的日期实例,并且comment_date是2006年6月1日08:00的日期实例,则以下将返回“8小时”:
# 分钟是所使用的最小单位,对于相对于比较点的未来的任何日期,将返回“0分钟”。
{{ blog_date|timesince:comment_date }}
# 12.timeuntil
# 似于timesince,除了它测量从现在开始直到给定日期或日期时间的时间。 例如,如果今天是2006年6月1日,
# 而conference_date是保留2006年6月29日的日期实例,则{{ conference_date | timeuntil }}将返回“4周”。
# 使用可选参数,它是一个包含用作比较点的日期(而不是现在)的变量。 如果from_date包含2006年6月22日,则以下内容将返回“1周”:
{{ conference_date|timeuntil:from_date }}
# 3.自定义filter步骤
# 定义:
# 1. 在app目录下创建一个名为 templatetags 的python包
# 2. 在上面创建的包内部创建一个python文件: ooxx.py
# 3. 在ooxx.py文件中按照固定的格式注册的一个自定义的filter
from django import template
# 固定写法,生成一个注册实例对象
register = template.Library()
# 告诉Django的模板语言我现在注册一个自定义的filter
@register.filter()
def add_sb(value):
"""
给任意指定的变量添加sb
:param value: |左边被修饰的那个变量
:return: 修饰后的变量内容
"""
return value + 'sb'
@register.filter()
def add_str(value, arg):
return value + arg
# 使用:
# 1. 重启Django项目
# 2. 在HTML页面中:{% load python文件名 %}
# 3. {{ name|add_str:'大好人' }}
#############################
# 装饰器(Decorator)
#
# 在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),
# 是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。
#
##############################
# 实例: 装饰器
def wrapper(fn):
def inner(*args, **kwargs):
print('准备点钱')
ret = fn(*args, **kwargs) # 真正执行原来的代码
return ret
return inner
#
@wrapper
def yue(tools):
print('使用%s约一约' % tools)
return '约成功了'
posted on 2020-03-17 08:25 herisson_pan 阅读(14) 评论(0) 收藏 举报
浙公网安备 33010602011771号