在函数中的使用:
- **kwargs:
=
连接 - kwargs:
:
,字典形式
基类主要实现连接数据库和增删查改的作用,相当于是操纵数据库
import time
from bson import ObjectId
from pymongo import MongoClient
class Model(object):
# 类变量,类里面可以通过 self 或 cls 调用
db = MongoClient()['web21_1']
@classmethod
def valid_names(cls):
names = [
# (字段名, 类型, 默认值)
('deleted', bool, False),
('created_time', int, 0),
('updated_time', int, 0),
]
return names
def __repr__(self):
class_name = self.__class__.__name__
properties = ('{0} = {1}'.format(k, v) for k, v in self.__dict__.items())
return '<{0}: \n {1}\n>'.format(class_name, '\n '.join(properties))
mongodb 字段的定义
@classmethod
def new(cls, form, **kwargs):
m = cls()
for name in cls.valid_names():
k, t, v = name
if k in form:
setattr(m, k, t(form[k]))
else:
setattr(m, k, v)
for k, v in kwargs.items():
if hasattr(m, k):
setattr(m, k, v)
else:
raise KeyError
timestamp = int(time.time())
m.created_time = timestamp
m.updated_time = timestamp
m.save()
return m
增:
一般增加评论、发表文章都是以表单方式发送数据,所以这里设置了个参数 form,可以直接将接收的数据拿过来用。当 form
的数据不够时,还可以通过参数 **kwargs
来增加;
-
m = cls()
:新的对象,属性值都是默认值;
- 第一个 for 循环用于解析表单发送的数据,将数据保存至类:
-
name
代表字段,元祖,三个元素(k, t, v)对应键、类型、值。 - if k in form:这种方式判断字典的键;
- setattr(m, k, v),用于设置属性值,设置 m 的属性 k 为 v
-
- 第二个 for 循环用于解析手动传递的数据
- hasattr(m, k) 用于判断 m 是否存在属性 k
- 最后,将自动生成的属性赋值(基本是时间)
放在 new() 函数这里,是因为每个数据创建时,才会生成时间。如果放在基类属性那里,那么每次调用类方法的时候,时间都会被改变为当前事件。 - 调用 save() 方法保存至数据库
def save(self): name = self.__class__.__name__ _id = self.db[name].save(self.__dict__) self.id = str(_id)
- 保存至数据库:
- name 获取子类名
- 保存至类名对应的表
- 将属性转换为字典形式保存
-
self.id = str(_id)
这个属性并不会保存至数据库,是保存之后再设置的,目的在于替换_id
,因为id
比_id
好看;而且id
是字符串类型,'_id' 是 ObjectId 类型。
@classmethod
def delete(cls, id):
name = cls.__name__
query = {
'_id': ObjectId(id),
}
values = {
'$set': {
'deleted': True
}
}
cls.db[name].update_one(query, values)
删:
这是一个假删除,每组数据都有个 delete
字段,初始值都是 false
;假删除后,delete
的值变为 false
。假删除并不会真正删除数据,只是显示的时候会排除这些数据,后台可以恢复。
-
name
获取表名,定位到表 - 通过 id 定位到具体数据,更改属性值。
注意:
- update() 是数据库文件的方法,类似
save()
。- 第一个参数是属性值的字典,用于找到实例。
- 第二个参数是要改变的字段的属性值字典,注意格式;
-
ObjectId(id) 是什么东西还不是很清楚
https://segmentfault.com/a/1190000007593341
http://blog.csdn.net/sasoritattoo/article/details/10365847
- id 是字符串类型,需要转换为 _id 对应 ObjectId 类型;
@classmethod
def update(cls, id, form):
name = cls.__name__
query = {
'_id': ObjectId(id),
}
values = {
'$set': form,
}
cls.db[name].update_one(query, values)
改:
update()
方法类似于 delete()
方法
- 用 update_one() 而不用 update() 方法,是因为,找到目标数据后,就更新,不再循环其他的数据,节省时间。
@classmethod
def all(cls, **kwargs):
kwargs['deleted'] = False
if 'id' in kwargs:
kwargs['_id'] = ObjectId(kwargs['id'])
kwargs.pop('id')
name = cls.__name__
docuemtns = cls.db[name].find(kwargs)
l = [cls._new_with_bson(d) for d in docuemtns]
return l
查(all):
- 加入没有被删除的限定条件
- 将外部传入的
id
改为mongodb
的_id
,并删除id
,字典也有 pop() 方法,返回删除的键的值,参数为键; - 通过 mongodb 的 find() 方法,找到所有符合条件的数据,(列表)
-
实例以字典形式储存至 mongodb,以实例(属性)形式返回:
@classmethod def _new_with_bson(cls, bson): """ 这是给内部 all 这种函数使用的函数 从 mongo 数据中恢复一个 model """ m = cls() for key in bson: setattr(m, key, bson[key]) m.id = str(bson['_id']) return m
- bson 是 mongodb 内部用来存数据的 json 的改写,是二进制版本,快一点,但还是 json 格式,json 是纯文本,用起来一样。
-
_id
改写为id
,这样方便外界(controls、templates)书写调用。
@classmethod
def one(cls, **kwargs):
documents = cls.all(**kwargs)
if len(documents) > 0:
return documents[0]
else:
return None
查(one):
返回所有符合条件的第一个数据;
def json(self):
d = self.__dict__
d.pop('_id')
return d
不知道这个函数有什么作用,感觉其他地方也没用到;
总结:
- 基类实现增删查改,方便子类调用;
-
id
与_id
的转换 - 储存数据的格式与取出数据的格式
- 极度的条件抽象
- 初始化时间的创建节点
- mongodb 的各种方法
save()、update_one()、find()、
数据库连接:
-
引入中间包
from pymongo import MongoClient
-
在基类内建立类变量,连接数据库管理系统,建立数据库文件。
db = MongoClient()['web21']
- 实际是是两步:
db = MongoClient('localhost', '27017')['web21']
- 实际是是两步:
-
建立集合,保存
_id = db[self.__class__.__name__].save(self.__dict__)
- 也是两步,建表(获取集合)、保存
classname = self.__class__.__name__
_id = db[classname].save(classname.__dict__)
一般封装在基类的 save() 方法中;
插入方法:save()、insert_one()、insert_many([,])
def save(self): name = self.__class__.__name__ # print('save', self.__dict__) _id = self.db[name].save(self.__dict__) self.id = str(_id)
- 也是两步,建表(获取集合)、保存
基类是数据库文件,子类就是表,实例的集合组成表,实例的属性就是字段


https://www.cnblogs.com/Lin-Yi/p/7384991.html
网友评论