Model
class Model(object):
def __init__(self, form):
self.id = form.get('id', None)
Model
为数据的基类,以后数据的建立都基于此,比如User
,Comment
,Weibo
,Session
等。
用 __init__
方法定义类的属性,参数 form
是一个字典
@classmethod
def db_path(cls):
classname = cls.__name__
path = '{}.txt'.format(classname)
return path
有装饰器@classmethod
的称为类方法,第一个参数为cls
,可以直接调用;
普通方法的第一个参数为self
,必须经过实例化后才能调用;
__name__
属性能够返回类的名字,这个类方法的意义在于返回一个以类名字命名的text
文件;
@classmethod
def new(cls, form):
m = cls(form)
return m
该方法等价于Model(form)
,调用的__init__(form)
方法,也就是实例化一个对象,只是为了增加辨识性(增);
@classmethod
def all(cls):
path = cls.db_path()
models = load(path)
ms = [cls.new(m) for m in models]
return ms
同一个类下面的方法可以相互调用,all()方法获取所有的实例,组成一个列表(原始数据结构是属性结构,非字典结构,通过魔法函数改造后,才成了字典结构)。这里调用 new() 方法是为了获得类的数据结构,因为存储的数据结构和类的数据结构不一样:
存储在txt文件里的数据结构.png 类的数据结构.png @classmethod
def find_by(cls, **kwargs):
users = cls.all()
for user in users:
for key, value in kwargs.items():
if hasattr(user, key) and value == getattr(user, key):
return user
return None
这个类方法的作用是通过某个属性和值,获取对应的实例;
hasattr(objecrt, name)
:判断对象是否有name
属性,返回值为 True
或 False
;
getattr(object, name)
:表示获取对象name
属性的值;
这里需要用户名(如果想通过用户名查找的话,这里返回的是相同用户名的第一个实例)和id唯一;
这里不能用 else
,因为第一个不匹配的话,就直接else退出了。要遍历所有数据不能用 else
;
def find_all(self, **kwargs):
users = self.all()
pass_word = ''
for key in kwargs:
pass_word = kwargs[key]
user_list = []
for user in users:
if pass_word == getattr(user, 'password'):
user_list.append(user)
return user_list
找到具有共同属性的所有实例,一对多的时候需求较多;
def save(self):
models = self.all()
if self.id is None:
if len(models) == 0:
self.id = 1
else:
self.id = models[-1].id + 1
else:
for i, m in enumerate(models):
if m.id == self.id:
models[i] = self
models.append(self)
l = [m.__dict__ for m in models]
path = self.db_path()
save(l, path)
对第二个 else
的意义不是很了解;
最后三行,是将类的属性结构转换为字典结构,再储存在数据库中,不能实例直接存储;
def __repr__(self):
classname = self.__class__.__name__
properties = ['{}: ({})'.format(k, v) for k, v in self.__dict__.items()]
s = '\n'.join(properties)
return '< {}\n{} >\n'.format(classname, s)
这是个魔法函数,不需要调用,实例化时,就会自动运行,相当于自定义部分,根据自己的需求改变类的数据结构。
__class__
:拿到当前的类,再获取类的名字;
str.join():拼接
'-'.join('a', 'b', 'c')
a-b-c
s = '\n'.join(properties)
:键值对之间换行
return '< {}\n{} >\n'.format(classname, s)
:类名和字典的换行;
u = User.new(form)
u
repr(u)
u.__repr__()
后面这三个等价
- 这是去掉魔法函数之后,类的数据结构
- 这是有魔法函数,类的数据结构
这是去掉 join()
方法后,类的数据结构
数据存储结构一直没变:
数据存储的结构.png- 类的原始属性:
__name__
:类名
__dict__
:将树形结构转化为字典结构
Database
Json是一种轻量级的数据交互格式,易于人们阅读和编写。利用其dumps(序列化:将数组转化为 json
字符串)方法,可以将数据转化为所有程序都认识的字符串,并写入文件。loads
(反序列化:将json格式字符串转换为 python
格式字符串 str
)方法将 json
编码的字符串转化为 python
的数据结构。
数据的存储与读取:
def save(data, path):
s = json.dumps(data, indent=2, ensure_ascii=False)
with open(path, 'w+', encoding='utf-8') as f:
f.write(s)
json
就是一种数据格式,和 str
类似,json
格式的字符串交互好一点。
json.dumps()
的作用是将 data
转换为 json
字符串,缩进两个字符,并且对中文友好;
文件只能存字符串,所以需要转换;
def load(path):
with open(path, 'r', encoding='utf-8') as f:
s = f.read()
log('load', s)
return json.loads(s)
子类
class User(Model):
def __init__(self, form):
super().__init__(form)
self.username = form.get('username', '')
self.password = form.get('password', '')
def validate_login(self):
u = User.find_by(username = self.username)
if u is not None and u.password == self.password:
self.id = u.id
return True
else:
return False
def validate_register(self):
return len(self.username) > 2 and len(self.password) > 2
继承基类的属性:
super.__init__(form)
网友评论