This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wechatpy 2.0 的一些想法 #120
Comments
cc @cloverstd |
这个改进很好
由于 wechatpy 文档不全,或者说,我主要用在企业号,我不得不去看源代码和结合微信文档来调用 API 对于 Python 常用框架,我觉得可以作为类似于 Flask 的扩展一样,这个 @messense 好像也说过,作为一个扩展来添加使用,而不是集成在 wechatpy 里。 |
Python 中 json 对象就是个 dict,用起来非常方便,这里我不希望过度封装,假如需要封装的话也不会直接在
这个可以有,但不是非常重要。
抽象 http 层是需要做的,更面向对象需要更详细的说明。
验证 token 你指的是啥?
这个每个框架都不一样,可以考虑弄一个 我目前的想法是先把 |
|
可以有 |
这个需要我们实现一个机制(或者叫协议)才方便对接其他 ORM。要不要在我们的项目中实现都可以,看精力。 |
用 namespace package 的话,放到 |
关键是在调用者那边是如何用的。这些内容在调用者那边基本都是对象。如果不是返回对象,那调用者不得不封装这个json。另外,在我看来,json 是数据格式,不是实体,而是实体的一种表现。json 的作用在于存储,但缺少操作的能力。或许我们可以搞一些 serializer 去输出不同的格式,或者在对象上提供输出这些格式的方法。 |
如果只是用来做简单的公众号相关的功能,很多东西都不需要存储,调用之后直接从 dict 中取数据最简便、最少 overhead。Python is not Java,不希望变成和那些 Java 的微信 SDK 一样封装一切。我希望保持核心简单,然后可以做一些扩展。 |
关于这点我还是一个基础观点,对不想使用的项目来说,不要增加负担就行。 在具体一点的话,我们在 wechatpy 中实现一个 backend,在 |
这个不是问题,用 namespace package 的话, 参考 zope 相关的库的发布方式。 |
我并没有用其他语言的思想来考虑。如果说有哪些参照的话,更多是 django 的做法。关于封装的程度,我觉得把接口封装成对象是基本的面向对象的封装,并没有在这个对象上再进行封装。你可能觉得serializer就封装过渡了,其实django 就是这么做的。 |
这个我赞成。和我说的 |
Namespace package. FYI: |
这样做呢, |
这个非常赞成。 |
其实你只要想一想调用者拿到数据之后会自然怎么做就知道哪个方案更好了。这个看法离我的观点很近了,就差一步: from wechatpy.models import WechatGroup
group_result = client.group.get(name='xxx')
wechat_group = WechatGroup(group_result) 如果把 group_result = client.group.get(name='xxx') 放到 try:
wechat_group = client.group.get(name='xxx')
except SomeException as e:
print(e)
else:
wechat_group.get_fellowers() |
所以你想实现的是,部分 data model 上依然可以调用 API 咯?就像你举的这个 group 的例子。 |
是的。将微信的概念封装成对象,接口变成对象的方法。完全屏蔽接口。 |
没有问题,只是不希望改变默认的 |
这些对象可以通过某种方法联通其他 python 库。比如装饰器,或者注册机制。 |
嗯,需要做些 prototype 出来看看 |
是的。确实有这个问题。我们可以建立2.0分支。1.0分支只有 bugfix 和优化。2.0的对外接口提供1.0的兼容。慢慢过渡,想 python 本身一样。
这个还只是想法,有哪些好的实现,大家一起考虑一下。 @admin.register(WechatGroup)
class WechatGroupModelAdmin(admin.ModelAdmin):
list_display = ('name', 'groupid', 'wechat', 'count')
那我们是不是可以写出这样的代码: from wechatpy.models import WechatGroup
from wechatpy.decortors import bind_model
from django.db import models
@bind_model(WechatGroup)
class Group(models.Model):
pass 或者其他方案。 这只是一个示例,大家在一起考虑。 |
不建议过度封装,wechatpy应该保持自己的独立性,完善微信功能异常处理以及在此基础上的高级功能,不应该和对象以及ORM扯上关系,很多场景还是需要手写SQL的。为了方便其他WEB框架使用,可以考虑开发对应插件,简化调用,如flask插件等。 |
是不是可以考虑全面优化一下wechatpy了? 建议将wechatpy/wechatpy和jxtech/wechatpy同步一次,然后在wechatpy/wechatpy上建立2.0分支。wechatpy/wechatpy的master分支还是和jxtech/wechatpy保持同步,但jxtech/wechatpy只修复bug。 |
https://github.com/wechatpy/wechatpy/tree/v2 你有些想法的话可以先做起来。 |
应该也把小程序包括在内 |
试着用描述器的方式实现自动获取值,最初只需要传入一个字典结果值到模型中,值获取是一个懒处理的过程,处理完后的值会缓存。另外使用了typing解决类型注解问题 以下是参考: data = {
"errcode": 0,
"errmsg": "ok",
"checkindata": [{
"userid": "james",
"groupname": "打卡一组",
"checkin_type": "上班打卡",
"exception_type": "地点异常",
"checkin_time": 1492617610,
"location_title": "依澜府",
"location_detail": "四川省成都市武侯区益州大道中段784号附近",
"wifiname": "办公一区",
"notes": "路上堵车,迟到了5分钟",
"wifimac": "3c:46:d8:0c:7a:70",
"mediaids": ["WWCISP_G8PYgRaOVHjXWUWFqchpBqqqUpGj0OyR9z6WTwhnMZGCPHxyviVstiv_2fTG8YOJq8L8zJT2T2OvTebANV-2MQ"]
}, {
"userid": "paul",
"groupname": "打卡二组",
"checkin_type": "外出打卡",
"exception_type": "时间异常",
"checkin_time": 1492617620,
"location_title": "重庆出口加工区",
"location_detail": "重庆市渝北区金渝大道101号金渝大道",
"wifiname": "办公室二区",
"notes": "",
"wifimac": "3c:46:d8:0c:7a:71",
"mediaids": ["WWCISP_G8PYgRaOVHjXWUWFqchpBqqqUpGj0OyR9z6WTwhnMZGCPHxyviVstiv_2fTG8YOJq8L8zJT2T2OvTebANV-2MQ"],
"lat": 30547645,
"lng": 104063236,
"deviceid": "E5FA89F6-3926-4972-BE4F-4A7ACF4701E2"
}]
}
from typing import List
class DataDescriptor(object):
def __set_name__(self, owner, name):
if not hasattr(self, "_name"):
self._name = name
def __init__(self, name=None, type_=None):
if name:
self._name = name
self._type = type_
def __get__(self, instance, type_=None):
if not instance:
return
dataset = instance._data[self._name]
if self._type:
if isinstance(dataset, list):
res = [self._type(data) for data in dataset]
else:
res = self._type(dataset)
else:
res = dataset
instance.__dict__[self._name] = res
return res
class DataModel(object):
class CheckinDataModel(object):
def __init__(self, data: dict) -> None:
self._data = data
userid: str = DataDescriptor()
groupname: str = DataDescriptor()
checkin_type: str = DataDescriptor()
def __init__(self, data: dict) -> None:
self._data = data
checkindata: List[CheckinDataModel] = DataDescriptor(type_=CheckinDataModel)
@property
def checkin_data(self) -> List[CheckinDataModel]:
pass
d = DataModel(data)
print(d.checkindata)
print(d.checkindata[0].userid)
print(d.checkindata[0].userid) |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
wehctapy 已经在我们的项目中用了几个月,确实方便了我们很多。
但也有些用的别扭的地方。慢慢的也产生了一些想法。希望和你交流一下。
出现此想法的原因
改进方向:
易用性
、功能性
接口返回数据是纯 json,而非对象
这在项目中还要做各种处理,这种处理放在业务中意义不大,浪费精力,适合放到本库中。提供一下接口会更好:
做法:将微信中的概念变成对象,将接口变成对象的方法,方法返回对象实例。对象实例提供各种数据格式的转化能力。
只支持官方操作
可以在官方操作的基础上封装常用操作,这样更方便使用
不够对象化
实例化之后,就可以检查wechat_client可调用的对象(底层接口),没有权限时,抛出异常;
所有操作以面向对象的方式使用,屏蔽 http 层。
发布时非接口类功能缺失
发布项目时,经常需要额外开发。比如验证 token,开放平台的基本测试等,可以在库中实现。节省调用者开发时间。
没有对接 python 常用框架
多数情况下微信对象需要本地保存,如果能对象 django ORM、SqlAlchemy ORM 等数据库模型,会大大增加我们项目的友好度。比如 Django 中
这样就把 wechatpy 中的模型和 Django 的模型关联了。
在完成 django 模型功能(保存到数据库)的同时,也完成了和微信接口的交互。
下面是 wechatpy 2.0 架构:
绿色部分将是新 wechatpy 对外提供的功能。当微信接口变化时,我们修改黄色部分即可。
这个想法还不够细致。如果你对这个改进方向认可,我们可以就此多想一想细节。
The text was updated successfully, but these errors were encountered: