V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
paloalto
V2EX  ›  编程

正在给网站增加“用豆瓣登录”功能,遇到一些问题,求指导。

  •  
  •   paloalto · 2012-12-15 19:09:41 +08:00 · 3291 次点击
    这是一个创建于 4394 天前的主题,其中的信息可能已经有所发展或是发生改变。
    网站之前有用户注册功能,为了让豆瓣用户更方便的登录到我的网站上,最近正在增加“用豆瓣登录”功能,

    原先的用户注册功能,是把用户的 username、email、nickname、password 信息存到 users 表中,其他的年龄、地址、简介等信息存到 profile 表中。

    原先的注册、登录功能很久之前就已经写完,其他的功能也都搞定,可以说网站已经做完了。

    但是后来在增加”用豆瓣登录“功能时,发现豆瓣返回的用户信息和我上面写的数据表结构不一致,比如,豆瓣返回的数据是这样的,和我的users表数据结构不一致:

    "id": "1000001",
    "uid": "ahbei",
    "name": "阿北",
    "avatar": "http://img3.douban.com/icon/u1000001-28.jpg", //头像小图
    "alt": "http://www.douban.com/people/ahbei/",
    "relation": "contact", //和当前登录用户的关系,friend或contact
    "created": "2006-01-09 21:12:47", //注册时间
    "loc_id": "108288", //城市id
    "loc_name": "北京", //所在地全称
    "desc": "现在多数时间在忙忙碌碌地为豆瓣添砖加瓦。坐在马桶上看书,算是一天中最放松的时间。”

    于是为了不和以前的 users 表冲突,我又新建了一个 douban_users 表,用来单独存储用豆瓣登录的用户。目前已经能够把用豆瓣登录的用户信息保存到数据库 douban_users 表中。

    可以说目前为止一切正常。

    但是。。。

    查询用户的时候就出现麻烦了,因为不知道如何解决以下问题,所以发帖请教:

    因为现在查询用户的相关代码都是查询的 users 表,比如获取昵称、头像神马的,增加了这个 douban_users 表之后,就得先判断这个用户是不是通过豆瓣登录的,如果是,就去查询douban_users;如果不是,就去查原先的users表。想到这里,我觉得不对劲,所以就没有继续往下写代码。

    虽然我知道能通过以上的判断来解决问题,但是总觉得这么做不是最好的解决办法。而且如果以后再增加”用新浪微博登录“、”用腾讯微博登录“啥的,返回的数据结构再不一样的话,就又要重新建表,再增加一个判断。

    不知道大家在处理类似”用豆瓣登录“这种功能的时候,有没有遇到这样的问题?
    13 条回复    1970-01-01 08:00:00 +08:00
    talentsnail
        1
    talentsnail  
       2012-12-15 19:30:19 +08:00
    只保存你的users表中已有的字段信息,再给users表加上一个用户来源的字段,本站注册的为0,豆瓣1,微博2……
    这样可以不?
    paloalto
        2
    paloalto  
    OP
       2012-12-15 19:34:40 +08:00
    @talentsnail 是个解决办法。等我找找看还有没有其他的方案。。
    ksky
        3
    ksky  
       2012-12-15 19:38:01 +08:00
    给豆瓣用户创建一个新用户在你之前的用户表里通用信息存一起,然后关联到新的豆瓣用表里。
    paloalto
        4
    paloalto  
    OP
       2012-12-15 19:53:30 +08:00
    @ksky 你的意思是说把 usename \ nickname 等通用信息都存到users表,把其他豆瓣独有的字段存到douban_users表,两张表通过某个共有的字段关联起来,是这样吗?
    ksky
        5
    ksky  
       2012-12-15 22:49:39 +08:00   ❤️ 1
    @paloalto 我的意思是,你还是用一个表来查询所有用户,如果你想要完整的豆瓣用户的资料就单独建表存储,在users表里加字段关联起来就行了。以后加新浪微博登录也可以同样处理。
    ergatea
        6
    ergatea  
       2012-12-16 01:32:16 +08:00
    base user
    (key username、email、nickname、password )

    douban user info
    (base user key ...)
    paloalto
        7
    paloalto  
    OP
       2012-12-16 02:27:23 +08:00
    感谢
    @ergatea
    @ksky
    @talentsnail
    三位的解答。

    我打算综合三位的方案, users 表中增加一个来源字段,原始注册是0,豆瓣是1,新浪是2...主要是考虑到这样,就可以根据来源字段来判断需要是否需要拼接头像的连接地址,比较方便一些。因为原始注册时,我是在 users 的 avatarPath 字段里存了部分路径,需要调用头像时就在前端拼接:

    $if user.avatarPath:
    ----$ src = '/static/upload/image' + user.avatarPath + '_48.jpg'
    ----<img src="$src" width="30" alt="$user.nickname" />
    $else:
    ----<img src="/static/public/img/default_48x48.jpg" width="30" alt="$user.nickname" />

    以后再加一个判断就可以了:

    $if user.avatarPath:
    ----$if user.via == 0 #原始注册
    --------$ src = '/static/upload/image' + user.avatarPath + '_48.jpg'
    --------<img src="$src" width="30" alt="$user.nickname" />
    ----$if user.via == 1 #豆瓣
    --------$ src = user.avatarPath
    --------<img src="$src" width="30" alt="$user.nickname" />
    $else:
    ----<img src="/static/public/img/default_48x48.jpg" width="30" alt="$user.nickname" />

    另外,把豆瓣的uid 当做 username,nickname = nickname,存储到users表中,其他的个人简介和常居地什么的就放到原先的 profile 表中,因为之前 users 和 profile 俩表就是关联的。

    这样就不用再新建一个douban_users表,全部通过一个 users 表来实现了。
    ergatea
        8
    ergatea  
       2012-12-16 22:29:21 +08:00   ❤️ 1
    擴展你的 user class 添加 get_avatar 方法,把你的邏輯寫在裏面,至於表結構合方式都是可以接受的,都可以,關於 get 過來的 api 數據,本人不建議大量存儲關係數據庫,存放cache系統應該可以滿足你的需求了。


    下面是我的model代碼, accesstoken表主要就是存儲用戶的api信息。
    ======

    class AccessToken(db.Model):
    __tablename__ = 'accesstoken'
    id = db.Column(db.Integer, primary_key = True)
    email = db.Column(db.String(100))
    service = db.Column(db.String(50))
    token = db.Column(db.String)
    token_secret = db.Column(db.String)

    class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.String(40), primary_key=True)
    email = db.Column(db.String(100), unique=True)
    username = db.Column(db.String(50), unique=True)
    password = db.Column(db.String(40))
    activate = db.Column(db.Boolean)
    join_date = db.Column(db.DateTime)
    tags = db.relationship('Tag', secondary=book_tag,
    backref=db.backref('users', lazy='dynamic'))


    class Profile(db.Model):
    pass
    paloalto
        9
    paloalto  
    OP
       2012-12-17 01:25:01 +08:00
    @ergatea 谢谢你的回答!另外问一个问题,从豆瓣过来的用户的用户名可能会跟我网站中的用户名有重复,所以我想在存储豆瓣用户的数据之前,先检查一下数据库中是否已经存在有相同的用户名了,如果有,就给新用户的用户名后面加一个后缀“_1”。

    #判断username是否有重名
    if not users.is_username_available(username):
    ----username = username + '_1'

    但是这样只能顶一次用。比如:
    用户在豆瓣的用户名是 ahbei ,恰巧我的网站中也有一个 ahbei 。按照上面的代码,这位新用户用豆瓣登录后,存储在数据库中的用户名会变成 ahbei_1;但是如果后来又有一个叫 ahbei_1 的豆瓣用户过来了,按照上面的程序,这位用户的用户名就会变成 ahbei_1_1。 —— 但其实我是想让他变成 ahbei_2的。

    请问怎么才能在遇到有重复的用户名之后让新用户名后面的那个数字递增呢?
    paloalto
        10
    paloalto  
    OP
       2012-12-17 07:26:31 +08:00
    目前的解决方案是先把原始注册关闭了,只开放“用豆瓣登录”功能。
    ergatea
        11
    ergatea  
       2012-12-17 19:31:17 +08:00   ❤️ 1
    你把簡單的事情複雜了,你完全可以別去判斷username,這種重複率很高的項,你的用戶如果是註冊用戶,那麼你讓他自己來授權api登錄,如果不是如果還沒註冊,你可以在用戶使用api登錄後讓系統自己建立一個用戶,你說對嗎?
    paloalto
        12
    paloalto  
    OP
       2012-12-17 19:40:06 +08:00
    @ergatea 不好意思,你说的我没明白。
    你的意思是给使用原始方式进行注册的用户增加一个绑定豆瓣帐号的功能?
    ergatea
        13
    ergatea  
       2012-12-17 22:41:13 +08:00
    可以這麼理解。如果是網站註冊用戶,就讓他選擇是否綁定API登入服務,反之則通過API登入後由系統建立用戶信息。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1088 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 19:02 · PVG 03:02 · LAX 11:02 · JFK 14:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.