Django 测试。
143 | {% block mainbody %} 144 |original
145 | {% endblock %} 146 | 147 | 148 | 149 | ``` 150 | 151 | 以上代码中,名为 mainbody 的 block 标签是可以被继承者们替换掉的部分。 152 | 153 | 所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。 154 | 155 | hello.html 中继承 base.html,并替换特定 block, hello.html 修改后的代码如下: 156 | 157 | HelloWorld/templates/hello.html 文件代码: 158 | 159 | ``` 160 | {% extends "base.html" %} 161 | 162 | {% block mainbody %}继承了 base.html 文件
163 | {% endblock %} 164 | 165 | ``` 166 | 第一行代码说明 hello.html 继承了 base.html 文件。可以看到,这里相同名字的 block 标签用以替换 base.html 的相应 block。 167 | 168 | 8. 169 | 170 | -------------------------------------------------------------------------------- /Django/unit3-model-1.md: -------------------------------------------------------------------------------- 1 | # 模型 2 | 3 | 1. 介绍 4 | 5 | 模型是有关数据的单一,明确的信息来源。它包含您要存储的数据的基本字段和行为。通常,每个模型都映射到单个数据库表。 6 | 7 | 基础: 8 | 9 | * 每个模型都是一个子类的Python类 django.db.models.Model。 10 | * 模型的每个属性代表一个数据库字段。 11 | 12 | 2. ORM 13 | 14 | 关系对象映射(Object Relational Mapping,简称ORM)。 15 | 16 | 生成表结构(默认数据库为sqllite) 17 | 18 | 1. 在引用下的models.py文件中(如果没有就新键)。创建类 19 | 20 | from django.db import models 21 | 22 | # Create your models here. 23 | class userinfo(models.Model): 24 | # 自动创建一个id列,id为主键、自增长 25 | telephone = models.CharField(max_length=30) 26 | password = models.CharField(max_length=64) 27 | email = models.EmailField() 28 | # memo = models.TextField() 29 | 2. 修改配置文件(settings.py),告诉应用从哪里应用模块中创建 30 | 31 | INSTALLED_APPS = [ 32 | 'django.contrib.admin', 33 | 'django.contrib.auth', 34 | 'django.contrib.contenttypes', 35 | 'django.contrib.sessions', 36 | 'django.contrib.messages', 37 | 'django.contrib.staticfiles', 38 | 'jobapp' #注意这里加上的是模块名称 39 | ] 40 | 3. 执行创建命令-python manage.py makemigrations 41 | 42 | **注意** 43 | 44 | 该模块目录下必须有一个文件夹:migrations(如果没有就新键) 45 | 46 | 47 | 执行python manage.py makemigrations生成临时文件:“0001_initial.py” 48 | 49 | 4. python manage.py migrate 生成数据表 50 | 51 | 52 | 默认表名:“jobapp01_uerinfo” 53 | 54 | 5. 把数据库从sqllite改为mysql 55 | 56 | 修改配置文件: 57 | 58 | 之前为: 59 | 60 | DATABASES = { 61 | 'default': { 62 | 'ENGINE': 'django.db.backends.sqlite3', 63 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 64 | } 65 | } 66 | 67 | 修改为: 68 | 69 | DATABASES = { 70 | 'default': { 71 | 'ENGINE': 'django.db.backends.mysql', 72 | 'NAME':'jobapp_django', 73 | 'USER': 'root', 74 | 'PASSWORD': '12345678', 75 | 'HOST': '127.0.0.1', 76 | 'PORT': '3306', 77 | } 78 | } 79 | 80 | **注意** 81 | 82 | 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替 83 | 84 | 如下设置放置的与project同名的配置的 __init__.py文件中 85 | 86 | import pymysql 87 | pymysql.install_as_MySQLdb() 88 | 89 | **所以啊,要先安装:pip install pymysql** 90 | 91 | 1. **删除数据表重新生成,解决 python No migrations to apply 无法生成表** 92 | 93 | 第一步: 94 | 95 | 删除该app名字下的migrations文件。 96 | 97 | 第二步: 98 | 99 | 进入数据库,找到django_migrations的表,删除该app名字的所有记录。 100 | delete from django_migrations; 101 | 102 | 或者删除数据库重新新建 103 | 104 | 第三部: 105 | 106 | python manage.py makemigrations 107 | 108 | python manage.py migrate 109 | 110 | 3. 访问数据数据库 111 | 112 | 1. 增加数据 113 | 114 | 在views.py文件中,增加 115 | 116 | from . import models 117 | 118 | 119 | def regist(request): 120 | # uu返回数据库中刚加入的那个对象 121 | uu=models.userinfo.objects.create( 122 | telephone="root", 123 | password="123456" 124 | ) 125 | 126 | #或者 127 | 128 | uu=models.userinfo.objects.create(**dict) 129 | 130 | 131 | #或者 132 | 133 | user=models.userinfo(telephone="admin",password="6666") 134 | user.save() 135 | 136 | return HttpResponse('regist ok') 137 | 138 | #再者 139 | 140 | dic={"telephone":"alex","password":"888"} 141 | 142 | models.userinfo(**dic).save() #当然了, models.userinfo.objects.create(**dic)也可以 143 | 144 | **force_update和force_insert** 145 | 146 | 这两个参数一般较少用到,因为save()之后django执行的是UPDATE或者INSERT这两条SQL语句的哪一条,遵循如下算法: 147 | 148 | 1.如果这个对象已经有主键而且主键的值是True的(即不是None或者空字符串等),就执行UPDATE。 149 | 150 | 2.如果没有主键或者这条save()不会update任何字段,那么它就INSERT。 151 | 152 | 只有在某些特定情况下,需要强制save()执行INSERT或UPDATE时才会使force_update=True或force_insert=True(比如我要求能UPDATE就UPDATE,不能我也不取INSERT,那么我就把这个force_update参数设置为True)。 153 | 2. 关于自增长id 154 | 155 | **id必须为models.AutoField** 156 | 157 | class userinfo(models.Model): 158 | # id = models.IntegerField(primary_key=True) 159 | id = models.AutoField(primary_key=True) 160 | 161 | # 自动创建一个id列,id为主键、自增长 162 | telephone = models.CharField(unique=True,max_length=30) 163 | password = models.CharField(max_length=64) 164 | email = models.EmailField() 165 | # memo = models.TextFi eld() 166 | 167 | **save()之后直接拿** 168 | 169 | dic={"telephone":"root","password":"999"} 170 | 171 | comment=models.userinfo(**dic) 172 | comment.save() 173 | 174 | print(comment.id) 175 | 176 | 2. 查询数据 177 | 178 | 1. 查询所有数据 179 | 180 | users=models.userinfo.objects.all() 181 | 182 | # 返回的是对象列表 183 | for user in users: 184 | print(user.id,user.telephone,user.password) 185 | 186 | #获取部分列 187 | users=models.userinfo.objects.all().values(‘id’,'telephone') 188 | #这个时候users为字典列表 189 | 190 | #获取部分列 191 | models.userinfo.objects.all().values_list(‘id’,'telephone') 192 | 193 | #这个时候users为元组列表 194 | 195 | 2. 条件查询 196 | 197 | 1. 单条件 198 | 199 | 200 | users=models.userinfo.objects.filter(telephone='root') 201 | #select * from userinfo where telephone='root' 202 | for user in users: 203 | print(user.id,user.telephone,user.password) 204 | 205 | 206 | 2. and 207 | 208 | 逗号表示and 209 | 210 | users=models.userinfo.objects.filter(telephone='root',password='123) 211 | 212 | 213 | 1. .... 214 | 215 | 3. 删除 216 | 217 | affect_rows=models.userinfo.objects.all().delete() 218 | 219 | affect_rows=models.userinfo.objects.filter(id='4').delete() 220 | 221 | 4. 更新 222 | 223 | affect_rows=models.userinfo.objects.all().update(password="666666") 224 | affect_rows=models.userinfo.objects.filter(id='4').update(password="666666") 225 | 226 | 227 | 228 | 4. demo 实现用户登录 229 | 230 | **注意** 231 | 232 | 如果数据没有查到返回的是[]空列表 233 | 234 | 如果user=models.userinfo.objects.filter(telephone='root').first()没有查到数据则结果为None 235 | 236 | 如果num=models.userinfo.objects.filter(telephone='root').count()没有查到数据则结果为0 237 | -------------------------------------------------------------------------------- /Django/unit3-model-2-mysql.md: -------------------------------------------------------------------------------- 1 | # mysql 2 | 1. model字段类型 3 | 4 | *'AutoField': 'integer AUTO_INCREMENT', 5 | 'BigAutoField': 'bigint AUTO_INCREMENT', 6 | 'BinaryField': 'longblob', 7 | *'BooleanField': 'bool', 8 | *'CharField': 'varchar(%(max_length)s)', 9 | 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 10 | *'DateField': 'date', 11 | *'DateTimeField': 'datetime', 12 | *'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 13 | 'DurationField': 'bigint', 14 | 'FileField': 'varchar(%(max_length)s)', 15 | 'FilePathField': 'varchar(%(max_length)s)', 16 | *'FloatField': 'double precision', 17 | *'IntegerField': 'integer', 18 | 'BigIntegerField': 'bigint', 19 | 'IPAddressField': 'char(15)', 20 | 'GenericIPAddressField': 'char(39)', 21 | 'NullBooleanField': 'bool', 22 | *'OneToOneField': 'integer', 23 | 'PositiveIntegerField': 'integer UNSIGNED', 24 | 'PositiveSmallIntegerField': 'smallint UNSIGNED', 25 | 'SlugField': 'varchar(%(max_length)s)', 26 | 'SmallIntegerField': 'smallint', 27 | *'TextField': 'longtext', 28 | *'TimeField': 'time', 29 | *'UUIDField': 'char(32)', 30 | 31 | 32 | DEMO: 33 | 34 | from django.db import models 35 | 36 | # Create your models here. 37 | class userinfo(models.Model): 38 | # id = models.IntegerField(primary_key=True) 39 | id = models.AutoField(primary_key=True) 40 | 41 | # 自动创建一个id列,id为主键、自增长 42 | telephone = models.CharField(unique=True,max_length=11) 43 | password = models.CharField(max_length=64) 44 | email = models.EmailField(null=True,db_column='uemail') 45 | regist_time=models.DateTimeField(auto_now_add=True,null=True) 46 | salary = models.DecimalField(max_digits=5, decimal_places=2) # 一共5位,保留两位小数 47 | 48 | ########Admin部分。放在后面谈...... 49 | # Admin为了不额外添加一张用户类型表,可以使用choices字段 50 | user_types=( 51 | (1,'普通用户'), 52 | (2,'VIP用户'), 53 | (3,'管理员') 54 | ) 55 | 56 | user_type_id=models.IntegerField(choices=user_types,default=1) 57 | # memo = models.TextField() 58 | 59 | 2. model 数据约束 60 | 61 | null 数据库中字段是否可以为空 62 | db_column 数据库中字段的列名 63 | email = models.EmailField(null=True,db_column='uemail') 64 | 65 | 66 | db_tablespace 67 | default 数据库中字段的默认值 68 | primary_key 数据库中字段是否为主键 69 | 70 | telephone = models.CharField(unique=True,max_length=30) 71 | 72 | db_index 数据库中字段是否可以建立索引 73 | unique 数据库中字段是否可以建立唯一索引 74 | unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引 75 | unique_for_month 数据库中字段【月】部分是否可以建立唯一索引 76 | unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 77 | auto_now_add 该列自动填充系统当前时间 78 | == 79 | Admin模块中用到的字段 80 | 81 | verbose_name Admin中显示的字段名称 82 | blank Admin中是否允许用户输入为空 83 | editable Admin中是否可以编辑 84 | help_text Admin中该字段的提示信息 85 | choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 86 | 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) 87 | 88 | error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 89 | 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 90 | 如:{'null': "不能为空.", 'invalid': '格式错误'} 91 | 92 | validators 自定义错误验证(列表类型),从而定制想要的验证规则 93 | from django.core.validators import RegexValidator 94 | from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ 95 | MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 96 | 如: 97 | test = models.CharField( 98 | max_length=32, 99 | error_messages={ 100 | 'c1': '优先错信息1', 101 | 'c2': '优先错信息2', 102 | 'c3': '优先错信息3', 103 | }, 104 | validators=[ 105 | RegexValidator(regex='root_\d+', message='错误了', code='c1'), 106 | RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'), 107 | EmailValidator(message='又错误了', code='c3'), ] 108 | ) 109 | 110 | 111 | DEMO: 112 | 113 | class UserInfo(models.Model): 114 | nid = models.AutoField(primary_key=True) 115 | username = models.CharField(max_length=32) 116 | class Meta: 117 | # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名 118 | db_table = "table_name" 119 | 120 | # 联合索引 121 | index_together = [ 122 | ("pub_date", "deadline"), 123 | ] 124 | 125 | # 联合唯一索引 126 | unique_together = (("driver", "restaurant"),) 127 | 128 | # admin中显示的表名称 129 | verbose_name 130 | 131 | # verbose_name加s 132 | verbose_name_plural 133 | 134 | 更多:https://docs.djangoproject.com/en/1.10/ref/models/options/ 135 | 136 | 137 | -------------------------------------------------------------------------------- /Django/unit3-model-3-mysql增删改查进阶.md: -------------------------------------------------------------------------------- 1 | # mysql-增删改查 2 | 1. 查询行数 3 | 4 | #查询结果的行数 5 | # users=models.userinfo.objects.all().count() 6 | users=models.userinfo.objects.filter(id=1).count() 7 | #查询第一个结果 8 | # user=models.userinfo.objects.all().first() 9 | # user=models.userinfo.objects.get(id=1) 10 | 11 | 12 | 13 | 14 | 2. 关系查询 15 | 16 | **注意双下划线** 17 | 18 | #获取部分列 19 | users=models.userinfo.objects.all().values(‘id’,'telephone') 20 | #这个时候users为字典列表,通过list(users)转化为字典列表,然后json.dumps(list(users))转化为字符串,传给客户端即可。 21 | 22 | #获取部分列 23 | models.userinfo.objects.all().values_list(‘id’,'telephone') 24 | #这个时候users为元组列表 25 | 26 | # 大于,小于 27 | # models.userinfo.objects.filter(id__gt=1) # 获取id大于1的值 28 | # models.userinfo.objects.filter(id__gte=1) # 获取id大于等于1的值 29 | # models.userinfo.objects.filter(id__lt=10) # 获取id小于10的值 30 | # models.userinfo.objects.filter(id__lte=10) # 获取id小于10的值 31 | # models.userinfo.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 32 | 33 | #不等于 34 | 35 | from django.db.models import Q 36 | #查询工资不等于10000 37 | jobs = models.job.objects.filter(~Q(salary_min=10000)).values('title','com_name','salary_min') 38 | 39 | 3. in 40 | 41 | # models.userinfo.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 42 | # models.userinfo.objects.exclude(id__in=[11, 22, 33]) # not in 43 | 44 | 4. is null 45 | 46 | users=models.userinfo.objects.filter(id__isnull=False) #True 47 | 48 | 5. contains 49 | 50 | users=models.userinfo.objects.filter(email__contains='admin') 51 | 52 | #不区分大小写 53 | 54 | users=models.userinfo.objects.filter(email__icontains='admin') 55 | 56 | #不包含 57 | 58 | users=models.userinfo.objects.exclude(email__icontains='admin') 59 | 60 | 6. range 61 | 62 | users=models.userinfo.objects.filter(id__range=[3,7]) 63 | 64 | 7. endswith startswith 65 | 8. order_by() 66 | 67 | users=models.userinfo.objects.all().order_by('id') #asc 68 | users=models.userinfo.objects.all().order_by('-id') #desc 69 | 70 | 9. group by 71 | 72 | group by 73 | 74 | # 75 | # from django.db.models import Count, Min, Max, Sum 76 | # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) 77 | # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" 78 | 79 | 10. limit 80 | 81 | models.Tb1.objects.all()[10:20] 82 | 11. regex正则匹配,iregex 不区分大小写 83 | 84 | users=models.userinfo.objects.filter(email__regex=r'_admin') 85 | 86 | 12. date 87 | 88 | date 89 | 90 | # 91 | # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) 92 | # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) 93 | 94 | # year 95 | # 96 | # Entry.objects.filter(pub_date__year=2005) 97 | # Entry.objects.filter(pub_date__year__gte=2005) 98 | 99 | 13. 执行原生SQL 100 | 101 | # from django.db import connection, connections 102 | # cursor = connection.cursor() # cursor = connections['default'].cursor() 103 | # cursor.execute("""SELECT * from auth_user where id = %s""", [1]) 104 | # row = cursor.fetchone() -------------------------------------------------------------------------------- /Django/unit3-model-4-表关系.md: -------------------------------------------------------------------------------- 1 | # mysql-多表查询 2 | 3. 表关系 3 | 4 | 5 | 6 | * 一对多:models.ForeignKey(其他表) 7 | * 多对多:models.ManyToManyField(其他表) 8 | * 一对一:models.OneToOneField(其他表) 9 | 10 | 11 | 12 | 1. 一对多关系(从表为userinfo和主表usertype) 13 | 14 | 1. 设置外键 15 | 16 | user_type=models.ForeignKey(to="usertype",to_field="id",default=1,on_delete= models.CASCADE) 17 | 18 | >此时、主表为usertype,从表为userinfo.**注意在数据库中表明为“模块名_类名的小写形势”。加入模块名为userinfo,这两个表名分贝为“user_usertype”和"user_userinfo".** 19 | >在从表中会产生一个新的字段:user\_type_id.但注意user\_type代表的是主表usertpye对象。 20 | 21 | **注意加上on_delete= models.CASCADE** 22 | 23 | - models.CASCADE,删除关联数据,与之关联也删除 24 | 25 | - models.DO_NOTHING,删除关联数据,引发错误IntegrityError 26 | 27 | - models.PROTECT,删除关联数据,引发错误ProtectedError 28 | 29 | - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空) 30 | 31 | - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值) 32 | 33 | 34 | 2. 查询数据数据时user_type就是主表的对象 35 | 36 | ####查询数据 37 | 1. 正向查询(由从表到主表的查询) 38 | 39 | users=models.userinfo.objects.all() 40 | 41 | for user in users: 42 | print(user.user_type.id) #等价于print(user.user_type_id) 43 | print(user.user_type.name) 44 | 45 | 如果单纯想拿到user_type的值可以这么样: 46 | 47 | users=models.userinfo.objects.all().values('telephone','password','user_type') 48 | 49 | **请注意这是数据的类型为字典类型的queryset** 50 | 51 | 2. 逆向查询(由主表到从表的查询) 52 | 53 | #get得到的直接是一个对象,不过get只能查看有一条记录的 54 | #查询类型为vip的对象 55 | t = models.usertype.objects.get(name='vip') 56 | 57 | #查询类型为vip的所有用户 58 | 59 | users=t.userinfo_set.all() 60 | #users=t.userinfo_set.all().values() 61 | #users=t.userinfo_set.all().values("id","telephone") 62 | 63 | >注意userinfo_set为系统提供的集合表示方式 64 | 65 | 66 | 3. 比较厉害的双下划线 67 | 68 | users=models.userinfo.objects.all().values('telephone','user_type__name')# __name 69 | 70 | s数据类型 71 | 72 | {"telephone": "root", "password": "999", "user_type__name": "\u666e\u901a\u7528\u6237"}, {"telephone": "admin", "password": "123", "user_type__name": "VIP\u7528\u6237"} 73 | 74 | ####添加数据 75 | 76 | 1. 方式一,先主表然后从表(不推荐) 77 | 78 | 例如: 79 | try: 80 | t = { 81 | "name": "user" 82 | } 83 | 84 | 85 | obj = models.Type.objects.create(**t) 86 | print(obj.id) 87 | 88 | #获取主表id 89 | user = { 90 | "telephone": "138", 91 | "password": "111", 92 | "user_type_id":obj.id 93 | } 94 | 95 | obj_u=models.UserInfo.objects.create(**user) 96 | 2. 方式二 97 | 98 | 例如:增加一个vip用户 99 | 100 | #1. 找出类型表中vip 101 | 102 | obj_type =models.Type.objects.filter(name='vip')[0] 103 | #2. 把查出的对象直接写入,注意user_type就是一对多链接对象: 104 | # user_type=models.ForeignKey(to='Type',to_field='id',default=1,on_delete=models.CASCADE) 105 | 106 | 107 | user = { 108 | "telephone": "139", 109 | "password": "222", 110 | "user_type":obj_type 111 | } 112 | 113 | obj_u=models.UserInfo.objects.create(**user) 114 | 115 | 1. 多对多关系 116 | 117 | 需要导入包时: 118 | 119 | from jobapp.models import * 120 | 121 | 因为setting.py已经设置 122 | 123 | INSTALLED_APPS = [ 124 | 'django.contrib.admin', 125 | 'django.contrib.auth', 126 | 'django.contrib.contenttypes', 127 | 'django.contrib.sessions', 128 | 'django.contrib.messages', 129 | 'django.contrib.staticfiles', 130 | 'position', 131 | 'jobapp' 132 | 133 | ] 134 | 135 | 136 | 2. 创建多对多关系表 137 | 138 | 139 | # 模拟多对多关系:用户-投递-职位 140 | class applyposition(models.Model): 141 | id = models.AutoField(primary_key=True) 142 | # 自动创建一个id列,id为主键、自增长 143 | uobj = models.ForeignKey(to=userinfo,to_field='id',on_delete=True) 144 | pobj = models.ForeignKey(to="position",to_field='id',on_delete=True) 145 | publish_time=models.DateTimeField(auto_now_add=True,null=True) 146 | 147 | **当然,这样创作好理解但是繁琐,我们可以直接在岗位模型中加入一条语句** 148 | 149 | from jobapp.models import * 150 | 151 | #在job表中 152 | apply=models.ManyToManyField(userinfo) 153 | 154 | 3. 数据操作 155 | 156 | 1. 增加数据 157 | 158 | 这个时候要先确定一个条件,比如user01投递了position01,那么我们就确定了岗位: 159 | 160 | pos=positon.objects.get(id=1) 161 | 162 | pos.apply.add(1) #这个时候的1就是用户id 163 | pos.apply.add(1,2,3) #这个时候的1,2,3就是用户id 164 | pos.apply.add(*[1,2,3,4]) #这个时候的1就是用户id 165 | 166 | 2. 删除数据 167 | 168 | pos.apply.remove(2) 169 | pos.apply.remove(1,2,3) 170 | pos.apply.remove(*[1,2,3]) 171 | pos.apply.clear() 172 | 173 | 3. 修改数据 174 | 175 | #关系表中岗位表是1的,只会有用户名1,2,3.其他都会删除 176 | pos.apply.set(1,2,3) 177 | 178 | 3. 查询数据 179 | 180 | pos=positon.objects.get(id=1) 181 | 182 | #此时拿到的对象集合为用户对象集合 183 | pos.apply.all() 184 | 185 | #要拿到关联表中(比如用户表中的)其他字段 186 | 187 | pos.apply.all().values('job_apply_password','job_apply_telephone') 188 | 189 | == 190 | # 添加数据 191 | pp = models.position.objects.get(id=2) 192 | pp.apply.add(7) 193 | 194 | #查询数据 195 | pos=models.position.objects.get(id=1) 196 | print(pos.name) 197 | print(pos.apply.all().filter(id=1)) 198 | users=pos.apply.all() 199 | for u in users: 200 | print(u.telephone) 201 | 202 | -------------------------------------------------------------------------------- /Django/unit4-middleware.md: -------------------------------------------------------------------------------- 1 | # 中间件 2 | 3 | 1. 哪里有 4 | 5 | settings.py 6 | 7 | MIDDLEWARE = [ 8 | 'django.middleware.security.SecurityMiddleware', 9 | 'django.contrib.sessions.middleware.SessionMiddleware', 10 | 'django.middleware.common.CommonMiddleware', 11 | # 'django.middleware.csrf.CsrfViewMiddleware', 12 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 13 | 'django.contrib.messages.middleware.MessageMiddleware', 14 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 15 | ] 16 | 17 | 18 | 2. 说明 19 | 20 | django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。 21 | 22 | 全局: 23 | 24 | 中间件 django.middleware.csrf.CsrfViewMiddleware 25 | 26 | 局部: 27 | 28 | @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。 29 | 30 | @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。 31 | **注:from django.views.decorators.csrf import csrf_exempt,csrf_protect** -------------------------------------------------------------------------------- /Django/uuid.md: -------------------------------------------------------------------------------- 1 | # uuid 2 | 3 | 1. 介绍 4 | 5 | 该模块提供不可变的UUID对象(UUID类)和功能uuid1(),uuid3(),uuid4(),uuid5()如在指定用于生成版本1,3,4和5点的UUIDRFC 4122。 6 | 7 | 如果你想要的只是一个唯一的ID,你应该打电话给uuid1()或 uuid4()。请注意,uuid1()可能会破坏隐私,因为它会创建包含计算机网络地址的UUID。 uuid4()创建一个随机的UUID。 8 | 2. 方法 9 | 10 | 1. uuid.uuid1(node = None,clock_seq = None ) 11 | 12 | 从主机ID,序列号和当前时间生成UUID。如果 未给出节点,getnode()则用于获取硬件地址。如果 给出clock_seq,则将其用作序列号; 否则,选择随机的14位序列号。 13 | 14 | 2. uuid.uuid3(名称空间,名称) 15 | 16 | 基于命名空间标识符(UUID)和名称(字符串)的MD5哈希生成UUID。 17 | 18 | 3. uuid.uuid4() 19 | 20 | 生成随机UUID。 21 | 22 | 4. uuid.uuid5(名称空间,名称) 23 | 24 | 基于命名空间标识符(UUID)和名称(字符串)的SHA-1哈希生成UUID。 25 | 26 | 27 | import uuid 28 | 29 | uuid01=uuid.uuid1() 30 | print(uuid01) 31 | uuid04=uuid.uuid4() 32 | print(uuid04) 33 | uuid03=uuid.uuid3(uuid.NAMESPACE_DNS,'JOBAPP.COM') 34 | uuid05=uuid.uuid5(uuid.NAMESPACE_DNS,'JOBAPP.COM') 35 | print(uuid03) 36 | 3. 命名空间标识符 37 | 38 | * uuid.NAMESPACE_DNS 39 | 40 | 指定此命名空间时,名称字符串是完全限定的域名。 41 | 42 | * uuid.NAMESPACE_URL 43 | 44 | 指定此命名空间时,名称字符串是URL。 45 | 46 | * uuid.NAMESPACE_OID 47 | 48 | 指定此命名空间时,名称字符串是ISO OID。 49 | 50 | * uuid.NAMESPACE_X500 51 | 52 | 指定此命名空间时,名称字符串是DER或文本输出格式的X.500 DN。 -------------------------------------------------------------------------------- /Flask/resfful api.md: -------------------------------------------------------------------------------- 1 | 网上整理的对于Rest和Restful api的理解 2 | 3 | 1. 什么是Rest? 4 | 5 | REST不是"rest"这个单词,而是几个单词缩写 -- REpresentational State Transfer 直接翻译:表现层状态转移,但这个翻译正常人根本看不懂,找到的一种最好理解的说法是,URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作。 6 | 7 | REST成熟度的四个层次 8 | 9 | 第一个层次(Level0)的Web 服务只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形 式。SOAP和 XML-RPC都属于此类。 10 | 11 | 第二个层次(Level1)的Web 服务引入了资源的概念。每个资源有对应的标识符和表达。 12 | 13 | 第三个层次(Level2)的Web 服务使用不同的 HTTP 方法来进行不同的操作,并且使用HTTP 状态码来表示不同的结果。如 HTTPGET 方法来获取资源,HTTPDELETE 方法来删除资源。 14 | 15 | 第四个层次(Level3)的Web 服务使用 HATEOAS。在资源的表达中包含了链接信息。客户端可以根据链接来发现可以执行的动作。 16 | 17 | 2. Restful api接口有什么特征? 18 | 19 | 20 | REST描述的是在网络中client和server的一种交互形式;REST本身不实用,实用的是如何设计 RESTful API(REST风格的网络接口)。 21 | 22 | 1. URL的根路径 23 | 24 | http://api.chesxs.com/v1 25 | 2. 需要有api版本信息 26 | 27 | http://api.chesxs.com/v1 28 | 3. URL中只使用名词指定资源,不用动词,且推荐使用复数 29 | 30 | 服务(Server)提供的RESTful API中,URL中只使用名词来指定资源,原则上不使用动词。“资源”是REST架构或者说整个网络处理的核心。比如: 31 | 32 | http://api.chesxs.com/v1/cars // 获取某个账户下的车辆列表 33 | http://api.chesxs.com/v1/fences // 获取某个账户下的围栏列表 34 | 4. 用HTTP协议里的动词来实现资源的添加,修改,删除等操作。即通过HTTP动词来实现资源的状态扭转 35 | 36 | GET 用来获取资源, 37 | 38 | POST 用来新建资源(也可以用于更新资源)。比如:POST http://api.chesxs.com/v1/car: 添加车辆 39 | 40 | PUT 用来更新资源, 41 | 42 | DELETE 用来删除资源。比如:DELETE http://api.chesxs.com/v1/cars 删除某辆车 (在http parameter指定好友id) 43 | 44 | UPDATE http://api.chesxs.com/v1/fence 更新围栏信息 45 | 46 | 错误使用: GET http://api.chesxs.com/v1/deleteCar 删除车辆 47 | 复制代码 48 | 5. GET应该是安全的,不会改变资源状态 49 | 50 | 这个应该很好理解,get的时候就只是获取资源,而不涉及添加、更新、删除资源。 51 | 52 | 6. 使用正确的HTTP Status Code返回状态码 53 | 54 | 常用的有404,200,500,400等等。 55 | 56 | 7. 过滤信息 57 | 58 | 如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。 59 | 60 | 下面是一些常见的参数。 61 | 62 | ?limit=10:指定返回记录的数量 63 | ?offset=10:指定返回记录的开始位置。 64 | ?page=2&per_page=100:指定第几页,以及每页的记录数。 65 | ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。 66 | ?producy_type=1:指定筛选条件 67 | 8. 规范返回的数据 68 | 69 | 为了保障前后端的数据交互的顺畅,建议规范数据的返回,并采用固定的数据格式封装。 70 | 71 | 接口返回模板: 72 | 73 | 74 | { 75 | status:0, 76 | 77 | data:{}||[], 78 | 79 | msg:’’ 80 | } 81 | 82 | 83 | 84 | 85 | 86 | ###总结,看一个标准的restful api要可以做到 87 | 88 | 看Url就知道要操作的资源是什么,是操作车辆还是围栏 89 | 90 | 看Http Method就知道操作动作是什么,是添加(post)还是删除(delete) 91 | 92 | 看Http Status Code就知道操作结果如何,是成功(200)还是内部错误(500) 93 | 94 | 参考文章:https://www.cnblogs.com/bndong/p/6139598.html -------------------------------------------------------------------------------- /Flask/unit0: -------------------------------------------------------------------------------- 1 | 1. HTTP1.1协议中文版-RFC2616 2 | https://www.cnblogs.com/k1988/archive/2010/01/12/2165683.html 3 | 2. -------------------------------------------------------------------------------- /Flask/unit1-基础.md: -------------------------------------------------------------------------------- 1 | #unit1 2 | **作者:詹亮** 3 | 4 | 1. 安装Flask 5 | 6 | ``` 7 | pip install Flask 8 | ``` 9 | 这些发行版将在安装Flask时自动安装。 10 | 11 | 1. Werkzeug实现了WSGI,这是应用程序和服务器之间的标准Python接口。 12 | 2. Jinja是一种模板语言,可呈现应用程序服务的页面。 13 | 3. MarkupSafe带有Jinja。它在渲染模板时逃避不可信的输入以避免注入攻击。 14 | 4. 它的危险性可靠地标记数据以确保其完整性。这用于保护Flask的会话cookie。 15 | 5. Click是编写命令行应用程序的框架。它提供了该flask命令并允许添加自定义管理命令 16 | 17 | 18 | 这些发行版不会自动安装。如果安装它们,Flask将检测并使用它们。 19 | 20 | 1. Blinker为信号提供支持。 21 | 2. SimpleJSON是一种与Python json模块兼容的快速JSON实现。如果安装了JSON操作,则是首选。 22 | 3. python-dotenv在运行 命令时支持来自dotenv的环境变量flask。 23 | 4. 看门狗为开发服务器提供更快,更高效的重载器。 24 | 2. hello world 25 | 26 | ``` 27 | from flask import Flask 28 | app = Flask(__name__) 29 | 30 | @app.route('/') 31 | def hello_world(): 32 | return 'Hello, World!' 33 | if __name__ == '__main__': 34 | app.run() 35 | ``` 36 | 3. 启动代码 37 | 38 | 使用flask命令或者-m使用Flask的python 开关。在你这样做之前,你需要通过导出FLASK_APP环境变量告诉你的终端应用程序 : 39 | 40 | ``` 41 | $ export FLASK_APP=hello.py 42 | $ flask run 43 | * Running on http://127.0.0.1:5000/ 44 | ``` 45 | 如果您在Windows上,环境变量语法取决于命令行解释器。在命令提示符下: 46 | 47 | ``` 48 | C:\path\to\app>set FLASK_APP=hello.py 49 | ``` 50 | 4. 启动调试模式 51 | 52 | app.run(host='0.0.0.0', port=5000, debug=True) 53 | 54 | >允许外网访问,并修改端口号 -------------------------------------------------------------------------------- /Flask/unit2-router.md: -------------------------------------------------------------------------------- 1 | # unit2 路由 2 | **作者:詹亮** 3 | 4 | 1. 简单入门 5 | 6 | ``` 7 | @app.route('/') 8 | def index(): 9 | return 'Index Page' 10 | 11 | @app.route('/hello/') 12 | #路由会执行下面的第一个方法,方法名不必和路由相同 13 | def hello(): 14 | return 'Hello, World' 15 | ``` 16 | **projects端点的规范URL 具有尾部斜杠。它类似于文件系统中的文件夹。如果您访问的URL没有斜杠,则Flask会将您重定向到带有斜杠的规范URL。** 17 | 2. 路由参数 18 | 19 | 可以通过标记部分将可变部分添加到URL inside
144 | print p.extract()
145 |
146 | for p in divs.xpath('p'):
147 | print p.extract()
--------------------------------------------------------------------------------
/spider/2-scrapy/unit3-item.md:
--------------------------------------------------------------------------------
1 | # python items & spider
2 | **作者:詹亮**
3 |
4 |
5 |
6 | 3. Items
7 |
8 | 1. item值操作
9 |
10 | #获取item属性值
11 | item['title']
12 | item.get('title')
13 |
14 | item.keys()
15 | item.items()
16 |
17 |
18 | 2. spider
19 |
20 | 对spider来说,爬取的循环类似下文:
21 |
22 | 1. 以初始的URL初始化Request,并设置回调函数。 当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数。
23 |
24 | >spider中初始的request是通过调用 start_requests() 来获取的。
25 | start_requests() 读取 start_urls 中的URL, 并以 parse 为回调函数生成 Request 。
26 |
27 | 3. 在回调函数内分析返回的(网页)内容,返回 Item 对象或者 Request 或者一个包括二者的可迭代容器。 返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的callback函数(函数可相同)。
28 | 4. 在回调函数内,您可以使用 选择器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 来分析网页内容,并根据分析的数据生成item。
29 | 5. 最后,由spider返回的item将被存到数据库(由某些 Item Pipeline 处理)或使用 Feed exports 存入到文件中。
30 |
31 | 虽然该循环对任何类型的spider都(多少)适用,但Scrapy仍然为了不同的需求提供了多种默认spider。
32 |
33 | 2. allowed_domains
34 |
35 |
36 | 可选。包含了spider允许爬取的域名(domain)列表(list)。 当 OffsiteMiddleware 启用时, 域名不在列表中的URL不会被跟进。
37 |
38 | 3. start_urls
39 |
40 | URL列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。
41 |
42 | 这个列表中的url会被依次取出并爬取。
43 | 3. start_requests()
44 |
45 | 如果您想要修改最初爬取某个网站的Request对象,您可以重写(override)该方法。
46 |
47 | start_url = ['']
48 | def start_requests(self):
49 | for i in range(100): # 爬31页数据差不多了
50 | url = self.start_url[0] + '&s=' + str(i * 44)
51 | yield scrapy.FormRequest(url=url, callback=self.parse)
52 |
53 | **回顾url**
54 |
55 | from urllib import parse
56 | import string
57 |
58 | #生成url
59 |
60 | qs={
61 | "page_start":20*4
62 | }
63 |
64 | url=url+parse.urlencode(qs)
65 |
66 | #解决url中文的问题
67 | url='https://s.taobao.com/search?q=手机&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=' \
68 | 'tbindexz_20170306&p4ppushleft=5%2C48&'
69 |
70 | url=parse.quote(url,safe=string.printable)
71 |
72 |
73 | print(url)
74 |
75 |
76 | [动态爬虫](https://blog.csdn.net/sdulsj/article/details/52984824)
77 |
78 |
79 |
--------------------------------------------------------------------------------
/spider/3-NOSQL/mongoDB 用户.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg936\cocoartf1561\cocoasubrtf200
2 | {\fonttbl\f0\fnil\fcharset134 PingFangSC-Regular;\f1\fswiss\fcharset0 Helvetica;}
3 | {\colortbl;\red255\green255\blue255;}
4 | {\*\expandedcolortbl;;}
5 | \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0
6 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0
7 |
8 | \f0\fs24 \cf0 \'b9\'dc\'c0\'ed\'d4\'b1
9 | \f1 \
10 | \
11 |
12 | \f0 \'ca\'fd\'be\'dd\'bf\'e2
13 | \f1
14 | \f0 \'d3\'c3\'bb\'a7\'c3\'fb
15 | \f1
16 | \f0 \'c3\'dc\'c2\'eb
17 | \f1 \
18 | admin useradmin adminpassword\
19 | \
20 | liepin lili 123456\
21 | }
--------------------------------------------------------------------------------
/spider/3-NOSQL/unit3-mongoDB-python.md:
--------------------------------------------------------------------------------
1 | ###pymongo
2 |
3 | 1. 安装连接驱动
4 |
5 | pip install pymongo
6 |
7 | 2. 连接
8 |
9 | 连接方式:
10 |
11 | 1)默认client = MongoClient()
12 |
13 | 2) 通过host+port的方式:client = MongoClient(host,port)
14 |
15 | 3) 通过uri的方式:client = MongoClient(uri)
16 |
17 | 示例:
18 |
19 | from pymongo import MongoClient
20 | #conn = MongoClient('127.0.0.1', 27017)
21 |
22 | uri = 'mongodb://lili:123456@127.0.0.1:27017/liepin'
23 | conn = MongoClient(uri)
24 | db = conn.liepin #连接liepin数据库,没有则自动创建
25 | col_user = db.user
26 | for u in col_user.find():
27 | print(u['name'])
28 | 3. 数据库连接uri
29 |
30 | mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
31 |
32 | 1. mongodb:// 这是固定的格式,必须要指定。
33 |
34 | 1. username:password@ 可选项,如果设置,在连接数据库服务器之后,驱动都会尝试登陆这个数据库
35 |
36 | 1. host1 必须的指定至少一个host, host1 是这个URI唯一要填写的。它指定了要连接服务器的地址。如果要连接复制集,请指定多个主机地址。
37 |
38 | 1. portX 可选的指定端口,如果不填,默认为27017
39 |
40 | 1. /database 如果指定username:password@,连接并验证登陆指定数据库。若不指定,默认打开 test 数据库。
41 |
42 | 1. ?options 是连接选项。如果不使用/database,则前面需要加上/。所有连接选项都是键值对name=value,键值对之间通过&或;(分号)隔开
43 |
44 | 4. 添加数据
45 |
46 | 插入数据(insert插入一个列表多条数据不用遍历,效率高, save需要遍历列表,一个个插入,save通常用来更新数据....)
47 |
48 | my_set.insert({"name":"zhangsan","age":18})
49 | #或
50 | my_set.save({"name":"zhangsan","age":18})
51 |
52 | 案例:
53 |
54 | from pymongo import MongoClient
55 | import json
56 | uri = 'mongodb://lzhan:123456@127.0.0.1:27017/jumei'
57 | try:
58 | conn = MongoClient(uri)
59 | db = conn.jumei # 连接jumei数据库,没有则自动创建
60 | col_user = db.user
61 | with open('data/users.json') as fp:
62 | users=json.load(fp)
63 | # 添加用户
64 | col_user.insert(users)
65 | conn.close()
66 | except Exception as ex:
67 | print(ex)
68 | 5. 修改数据
69 |
70 | my_set.update(
71 |