一、ORM介绍
1、ORM概念
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。
简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
ORM在业务逻辑层和数据库层之间充当了桥梁的作用。 2、ORM由来
让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。
几乎所有的软件开发过程中都会涉及到对象和关系数据库。在用户层面和业务逻辑层面,我们是面向对象的。当对象的信息发生变化的时候,我们就需要把对象的信息保存在关系数据库中。
按照之前的方式来进行开发就会出现程序员会在自己的业务逻辑代码中夹杂很多SQL语句用来增加、读取、修改、删除相关数据,而这些代码通常都是重复的。 3、ORM的优势
ORM解决的主要问题是对象和关系的映射。它通常把一个类和一个表一一对应,类的每个实例对应表中的一条记录,类的每个属性对应表中的每个字段。
ORM提供了对数据库的映射,不用直接编写SQL代码,只需像操作对象一样从数据库操作数据。
让软件开发人员专注于业务逻辑的处理,提高了开发效率。 4、ORM的劣势
ORM的缺点是会在一定程度上牺牲程序的执行效率。
ORM用多了SQL语句就不会写了,关系数据库相关技能退化... 5、ORM总结
ORM只是一种工具,工具确实能解决一些重复,简单的劳动。这是不可否认的。
但我们不能指望某个工具能一劳永逸地解决所有问题,一些特殊问题还是需要特殊处理的。
但是在整个软件开发过程中需要特殊处理的情况应该都是很少的,否则所谓的工具也就失去了它存在的意义。 二、Django中的ORM
1、Django项目使用MySQL数据库
1. 手动新建一个数据库 2. 在Django项目的settings.py文件中,配置数据库连接信息: DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "你的数据库名称", # 需要自己手动创建数据库
"USER": "数据库用户名",
"PASSWORD": "数据库密码",
"HOST": "数据库IP",
"POST": 3306
}
} 3. 告诉Django用什么模块连接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中是否有改动,把改动记录到migrations目录下
2. python manage.py migrate --> 把改动翻译成SQL语句去数据库执行
注意:当项目中不止有一个APP时,python manage.py makemigrations appname 可以单独判断某个app里面的models.py的变更 2、Model
在Django中model是你数据的单一、明确的信息来源。它包含了你存储的数据的重要字段和行为。通常,一个模型(model)映射到一个数据库表 基本情况: 每个模型都是一个Python类,它是django.db.models.Model的子类。
模型的每个属性都代表一个数据库字段。
综上所述,Django为您提供了一个自动生成的数据库访问API。、
3、说明
ORM定义表
from django.db import models class Book(models.Model):
title = models.CharField(max_length=20)
publisher = models.CharField(max_length=30)
title 和 publisher 是模型的字段。每个字段被指定为一个类属性,每个属性映射到一个数据库列。 上面的模型等于下面的SQL建表语句 CREATE TABLE myapp_book (
"id" int NOT NULL auto_increment PRIMARY KEY,
"title" varchar(20) NOT NULL,
"publisher" varchar(30) NOT NULL
); 表myapp_book的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时。
id字段是自动添加的且是自增主键,如果你想要指定自定义主键,只需在其中一个字段中指定 primary_key=True 即可。如果Django发现你已经明确地设置了Field.primary_key,它将不会添加自动ID列。
Django会根据配置文件中指定的数据库后端类型来生成相应的SQL语句。
Django支持MySQL5.5及更高版本。 4、字段
总览
    AutoField(Field)
- int自增列,必须填入参数 primary_key=True BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True 注:当model中如果没有自增列,则自动会创建一个列名为id的列
from django.db import models class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32) class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32) SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767
IntegerField(Field)
- 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~ 2147483647 BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field)
- 布尔值类型 NullBooleanField(Field):
- 可以为空的布尔值 CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度 TextField(Field)
- 文本类型 EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both" URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字 UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹 FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field)
- 浮点型 DecimalField(Field)
- 10进制小数
- 参数:
max_digits,整数位和小数位的总长度
decimal_places,小数位长度 BinaryField(Field)
- 二进制类型

字段总览



常用字段
1. AutoField() *****
- int自增列,必须填入参数 primary_key=True
- 当model中如果没有自增列,则自动会创建一个列名为id的列(即自增的id主键) 2. IntegerField *****
- 整数列(有符号的) -2147483648 ~ 2147483647 3. BooleanField
- 布尔值类型
- 在数据库中BooleanField存的是数字,一般用1或者0表示 4. CharField *****
- 字符类型varchar
- 必须提供max_length参数, max_length表示字符长度 5. TextField
- 文本类型 6. EmailField
- 字符串类型,Django Admin以及ModelForm中提供验证机制 7. GenericIPAddressField
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both" 8. UUIDField *****
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 9. FileField
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage 10. ImageField
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串) 11. DateTimeField *****
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 12. DateField *****
- 日期格式 YYYY-MM-DD 13. TimeField
- 时间格式 HH:MM[:ss[.uuuuuu]] 14. FloatField
- 浮点型 15. DecimalField *****
- 10进制小数
- 参数:
max_digits,整数位和小数位总长度
decimal_places,小数位长度
- 例如:DecimalField(max_digits=6, decimal_places=2) # 那么整数位最多只能有4位,小数位只有两位,4444.12 正确; 12345.11 错误 5、自定义字段
1.自定义char类型字段:
from django.db import models class MycharField(models.Field):
"""
自定义的char类型的字段类
"""
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super(MycharField, self).__init__(max_length=max_length, *args, **kwargs) def db_type(self, connection):
"""
限定生成数据库表的字段类型为char,长度为length指定的值
"""
return 'char(%s)' % self.max_length class UserInfo(models.Model):
name = MycharField(max_length=12) 2.自定义无符号整数字段:
class UnsignedIntegerField(models.IntegerField):
def db_type(self, connection):
return 'integer UNSIGNED' 3.返回值为字段在数据库中的属性,Django字段默认的值为:
    'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',

字段的属性


6、字段参数
null                数据库中字段是否可以为空
db_column 数据库中字段的列名
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 verbose_name Admin中显示的字段名称
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
如:sex = models.IntegerField(choices=[(1, '男'), (2, '女'), (3, '保密')], default=3) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'} validators 自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
)

字段参数总览



常用字段的参数
1.null 数据库中字段是否可以为空
2.db_column 数据库中字段的列名
3.default 数据库中字段的默认值
4.primary_key 数据库中字段是否为主键
5.db_index 数据库中字段是否可以建立索引
6.unique 数据库中字段是否可以建立唯一索引
7.unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
8.unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
9.unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 .DatetimeField和Datefield独有的参数:
auto_now_add = True --> 当前数据的创建时间
auto_now = True --> 当前数据的最后修改时间
注意:auto_now_add和auto_now 不能写在同一个字段上 . 带choice参数的字段
get_字段名_display() --> 获取choice字段的显示值
例如:
     # 元组第一个参数是存在数据库的值,第二个参数是给我们展示在页面的值,如:(1,"男"),在数据库中存的是 1 而不是 "男","男"是为了方便我们页面的展示
sex = models.IntegerField(choices=[(1, '男'), (2, '女'), (3, '保密')], default=3)
get_sex_display() --> 保密 12. 建表的元信息
class Meta:
db_table = '表名'
unique_together = (('ip', 'port'),)
index_together = (("pub_date", "deadline"),) 7、元信息
class UserInfo(models.Model):
nid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32)
class Meta:
# 数据库中生成的表名称默认是app名称 + 下划线 + 类名(全小写)
# 可以通过db_table进行修改
db_table = "userinfo" # 告诉Django这个表名就叫userinfo,不要默认建成 app名称_userinfo # 联合索引
index_together = [
("pub_date", "deadline"),
] # 联合唯一索引
unique_together = (("ip", "port"),) # admin中显示的表名称
verbose_name # verbose_name加s
verbose_name_plural 例如:
# 博客表
class Blog(models.Model):
title = models.CharField(max_length=32)
push_time = models.DateTimeField(auto_now_add=True) # 创建时间
edit_time = models.DateTimeField(auto_now=True) # 最后修改时间 class Meta:
db_table = 'blog' # 控制建表名称 # 应用程序表
class Size(models.Model):
ip = models.GenericIPAddressField()
port = models.IntegerField() class Meta:
unique_together = (('ip', 'port'),) 三、ORM的相关操作
小知识:
import os

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "DjangoPractice.settings")
import django
django.setup()
from appname.models import TableName
ORM语句
...
UserInfo表:
class UserInfo(models.Model):
name = MycharField(max_length=12)
birthday = models.DateTimeField(verbose_name='生日', null=True)
sex = models.IntegerField(choices=[(1, '男'), (2, '女'), (3, '保密')], default=3) def __str__(self):
return self.name

UserInfo


1、基本操作13条(必会)
1-1、返回QuerySet对象(列表)的方法(返回的是列表,列表中的元素是对象)
all()
查询所有结果 filter(**kwargs)
它包含了与所给筛选条件相匹配的对象 exclude(**kwargs)
它包含了与所给筛选条件不匹配的对象 order_by(*field)
对查询结果排序 reverse()
对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。 distinct()
从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。) 1-2、特殊的QuerySet(返回的是列表,但列表中的元素不是对象)
values(*field)
返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
   User.objects.all().values('id', 'name')
   QuerySet [{'id': 1, 'name': '小明'}, {'id': 2, 'name': '小东'}] values_list(*field)
它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
   User.objects.all().values_list('id', 'name')
   QuerySet [(1, '小明'), (2, '小东')] 1-3、返回具体对象的
get(**kwargs)
返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 first()
返回第一条记录 last()
返回最后一条记录 1-4、返回布尔值的方法
exists()
如果QuerySet包含数据,判断表中是否有数据,有就返回True,否则返回False 1-5、返回数字的方法
count()
返回数据库中匹配查询(QuerySet)的对象数量。 例子:
# all()找到UserInfo表中所有的对象
ret = UserInfo.objects.all()
print(ret) # filter()找到名字是小明的那个人
ret1 = UserInfo.objects.filter(name='小明')
print(ret1) # exclude()找到名字不是小明的那些人
ret1 = UserInfo.objects.exclude(name='小明')
print(ret1) # values()返回的还是列表,但列表中的不是对象,而是字典
ret = UserInfo.objects.all().values('name', 'sex')
print(ret) # values_list()返回的还是列表,但列表中的不是对象,而是元组
ret1 = UserInfo.objects.all().values_list('name', 'sex')
print(ret1) # order_by('xx')根据xx升序排序,order_by('-xx')根据xx降序排序
ret = UserInfo.objects.all().order_by('id')
ret1 = UserInfo.objects.all().order_by('-id')
ret2 = UserInfo.objects.all().order_by('birthday')
print(ret)
print(ret1)
print(ret2) # reverse() 对排序的结果进行反序
ret = UserInfo.objects.all().order_by('id').reverse()
print(ret) # count()返回数量
ret = UserInfo.objects.all().count()
print(ret) # first()返回第一条记录和last()返回最后一条记录
ret1 = UserInfo.objects.all().first()
ret2 = UserInfo.objects.all().last()
print(ret1)
print(ret2) # exists()判断表中是否有数据
ret = UserInfo.objects.exists()
print(ret) 2、单表查询之神奇的双下划线
# __lt:查询id值小于3的对象
ret = UserInfo.objects.filter(id__lt=3)
print(ret) # __lte:查询id值小于等于3的对象
ret = UserInfo.objects.filter(id__lte=3)
print(ret) # __gt:查询id值大于3的对象
ret = UserInfo.objects.filter(id__gt=3)
print(ret) # __in:id是1,3,5的对象
ret = UserInfo.objects.filter(id__in=[1, 3, 5])
print(ret) # __in:id不是1,3,5的对象
ret = UserInfo.objects.exclude(id__in=[1, 3, 5])
print(ret) # __contains:找到名字包含"小"的对象,__icontains:和__contains一样,但是不区分大小写
ret = UserInfo.objects.filter(name__contains='小')
print(ret) # __range:找到范围在[1, 3]之间的对象
ret = UserInfo.objects.filter(id__range=[1, 3])
print(ret) # __endswith:找到以"仔"结尾的对象
ret = UserInfo.objects.filter(name__endswith='仔')
print(ret) # date字段还可以使用__year、__month等:找到10月出生的人
ret = UserInfo.objects.filter(birthday__month=10)
print(ret) # __isnull:判断这个字段是否为空,查询name为空的对象
ret = UserInfo.objects.filter(name__isnull=True)
print(ret) # 双下还可以链式操作:找到出生小于2000年的
ret = UserInfo.objects.filter(birthday__year__lt=2000)
print(ret)

ORM基础之ORM介绍和基础操作的更多相关文章

  1. .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 介绍和基础)--学习笔记

    2.5.1 MongoDB -- 介绍 mysql vs mongo 快速开始 mysql vs mongo 对比 mysql mongo 数据存储 table 二维表结构,需要预先定义结构 json ...

  2. ActiveMQ基础教程----简单介绍与基础使用

    概述 ActiveMQ是由Apache出品的,一款最流行的,能力强劲的开源消息总线.ActiveMQ是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,它非常快速,支持多 ...

  3. 手撸ORM浅谈ORM框架之基础篇

    好奇害死猫 一直觉得ORM框架好用.功能强大集众多优点于一身,当然ORM并非完美无缺,任何事物优缺点并存!我曾一度认为以为使用了ORM框架根本不需要关注Sql语句如何执行的,更不用关心优化的问题!!! ...

  4. python django基础四 ORM简介

    ORM,全称是object relation mapping.翻译过来,就是对象关系映射. 主要来学习MySQL操作,MySQL是一个软件.它的优点:1.免费 2.开源 pymysql,就是Mysql ...

  5. LYNC2013介绍和基础架构准备角色

    LYNC2013部署系列PART1:LYNC2013介绍和基础架构准备 前言:LYNC 2013发布已经很久了,本人一直在进行相关的学习和测试,在有限的资源条件下,把能够模拟出来的角色进行了安装部署, ...

  6. Hadoop 综合揭秘——MapReduce 基础编程(介绍 Combine、Partitioner、WritableComparable、WritableComparator 使用方式)

    前言 本文主要介绍 MapReduce 的原理及开发,讲解如何利用 Combine.Partitioner.WritableComparator等组件对数据进行排序筛选聚合分组的功能.由于文章是针对开 ...

  7. windows下mongodb基础玩法系列二CURD操作(创建、更新、读取和删除)

    windows下mongodb基础玩法系列 windows下mongodb基础玩法系列一介绍与安装 windows下mongodb基础玩法系列二CURD操作(创建.更新.读取和删除) windows下 ...

  8. Git及基础命令的介绍以及如何向本地仓库添加文件

    在介绍Git的使用之前,我们得要先来了解一下Git.那么什么是Git? Git是一个版本管理工具(VCS),具有以下的特点: 分布式版本控制: 多个开发人员协调工作: 有效监听谁做的修改: 本地及远程 ...

  9. Linux shell脚本基础学习详细介绍(完整版)一

    Linux shell脚本基础学习这里我们先来第一讲,介绍shell的语法基础,开头.注释.变量和 环境变量,向大家做一个基础的介绍,虽然不涉及具体东西,但是打好基础是以后学习轻松地前提.1. Lin ...

随机推荐

  1. 【代码笔记】Web-CSS-CSS Fonts(字体)

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  2. springboot 使用 redis

    springboot 自己是实现了一套 redis 缓存框架, 地址: https://www.cnblogs.com/huanggy/p/9473822.html, 通过配置即可轻松愉快地实现 某些 ...

  3. 用webpack打包加密静态配置文件

    webpack处理静态文件,如json.xml等配置文件,可以采用 copy-webpack-plugin 插件直接复制到打包后的文件夹下,但如果想采用一些手段隐藏一下这些配置文件的内容怎么办呢? 虽 ...

  4. getDimension与getDimensionPixelOffset与getDimensionPixelSize的区别

    getDimension()                       返回float型px值     精确  getDimensionPixelOffset()     返回int型px值     ...

  5. 跨进程SharedPreferences异常。

    诡异的SharedPreferences异常,在ACC之后,SharedPreferences获取不到值了,但是另一个应用可以获取到值.同样的方法,一个正常一个异常. Context c = null ...

  6. 关于如何使用xposed来hook某支付软件

    由于近期有业务上的需要,所以特地花时间去研究了一下如何使用hook技术.但是当我把xposed环境和程序编写完成时,突然发现手机上的某个支付软件无法使用了.这个时候我意识到,应该是该软件的安全机制在起 ...

  7. PM过程能力成熟度2级

    当PM意识到自己不再是程序员后,就会在项目管理方面,逐渐达到过程能力成熟度1级.尽管这种亲身经历会带给PM管理的信心,但从项目的层面来说,整体还是混沌的,PM在经历过1级的阶段性胜利后,将面临更多的问 ...

  8. spring学习总结——高级装配学习二(处理自动装配的歧义性)

    我们已经看到如何使用自动装配让Spring完全负责将bean引用注入到构造参数和属性中.自动装配能够提供很大的帮助.不过,spring容器中仅有一个bean匹配所需的结果时,自动装配才是有效的.如果不 ...

  9. JavaScript中闭包的写法和作用详解

    1.什么是闭包 闭包是有权访问另一个函数作用域的变量的函数. 简单的说,Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内.而且,这些内部函数可以访问它们所在的外 ...

  10. pip install PIL The _imagingft C module is not installed

    需要先删除PIL再进行安装 sudo pip uninstall -y PIL 删除PIL相关文件夹:/usr/local/bin/pil , usr/lib/python2.7/dist-packa ...