理解“与朋友一起跑步” facebook 应用程序示例代码

发布于 2024-12-23 10:37:26 字数 1265 浏览 2 评论 0原文

这是我第一次网络编程经历,所以我希望我的问题听起来不是很愚蠢。我已经被这个问题困扰很多天了。

我试图理解示例代码: https://github.com/facebook/runwithfriends

但是我不太了解信息流是如何工作的以及如何修改该示例(即代码如何工作)。

例如,在代码的以下部分中:

class RecentRunsHandler(BaseHandler):
"""Show recent runs for the user and friends"""
def get(self):
    if self.user:
        friends = {}
        for friend in select_random(
                User.get_by_key_name(self.user.friends), 30):
            friends[friend.user_id] = friend

        self.render(u'runs',
            friends=friends,
            user_recent_runs=Run.find_by_user_ids(
                [self.user.user_id], limit=5),
            friends_runs=Run.find_by_user_ids(friends.keys()),
        )
    else:
        self.render(u'welcome')

据我了解(与 HTML 一起)对于显示使用同一应用程序的朋友很有用,如果我理解正确,这里是重要部分:

*friends_runs=Run .find_by_user_ids(friends.keys())*

但是如果我想显示任何给定的朋友怎么办?我该怎么做呢?

总结一下,我想知道:

1-代码流程如何工作? (我不完全理解这里的解释)

2-我如何操作代码来显示用户的朋友列表(不需要使用相同的应用程序)? 此外,我可以显示按某些特征(例如性别)过滤的朋友吗?

非常感谢!

this is my first web-programming experience so I hope my questions doesn't sound very dumb. I have been stucked on this for many days.

I am trying to understand a sample code:
https://github.com/facebook/runwithfriends

However I am not understanding very well how the information flow works and how can I modify that sample (i.e. how the code works).

For example, in the following section of the code:

class RecentRunsHandler(BaseHandler):
"""Show recent runs for the user and friends"""
def get(self):
    if self.user:
        friends = {}
        for friend in select_random(
                User.get_by_key_name(self.user.friends), 30):
            friends[friend.user_id] = friend

        self.render(u'runs',
            friends=friends,
            user_recent_runs=Run.find_by_user_ids(
                [self.user.user_id], limit=5),
            friends_runs=Run.find_by_user_ids(friends.keys()),
        )
    else:
        self.render(u'welcome')

As I understand (along with HTML) is useful for showing friends that are using the same app, and if I understand correctly, here is the essential part:

*friends_runs=Run.find_by_user_ids(friends.keys())*

But what if I want to show any given friend. How can I do it?

Summarizing, I would like to know:

1- How the flow of the code works? (I don't fully understand the explanation here)

2- How can I manipulate the code so to get, for example, to show a list of friends of the user (not necessary that use the same app)?
Moreover, Can I show friends filtered by some characteristic (for example, gender)?

Thanks a lot!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月亮是我掰弯的 2024-12-30 10:37:26

我使用的 facebook 的 python“SDK”取自 https://gist.github.com/1190267
并将其与示例应用程序中的代码相结合,以实现我想要的画布应用程序和网站使用的功能。

这取决于您使用的是 Facebook 网站还是画布应用程序。对于画布应用程序,您可能可以很好地使用 javascript SDK,但对于“使用 facebook 登录”,我需要应在关闭 javascript 的情况下工作的服务器端逻辑,因此我已经完成了该解决方案,其中包含您可能需要了解的详细信息。您可以尝试对特定应用程序“runwithfriends”进行一些小的更改,以了解哪些代码执行哪些操作。不过,您正在查看的项目包含一些过时的做法:

  • 现在可能更愿意使用 webapp2 的内置函数来获取和设置 cookie,而不是使用 FB 示例应用程序附带的代码

  • 登录和注销现在是使用 OAuth 2.0 完成的,因此您正在查看的登录系统可能是这样的已过时,您需要使用此处描述的 OAuth 2.0。我更喜欢在服务器端进行登录/注销,因此我按照 FB 教程中提到的身份验证步骤,做了一个 OAuth 2.0 纯 python 解决方案来登录/注销。我必须清除 cookie 才能注销未记录的用户。

  • 要升级到 python 2.7,我还必须进行修改,以便 HTTP 标头不会转换为 unicode。我不知道为什么,但它抱怨标头“不是字符串”

要更详细地回答您的具体问题:

1)您发布的 requesthandler 类是 BaseHandler 的子类,因此要完全理解它的作用,您可以查看BaseHandler 类,因为您发布的是 BaseHandler。 BaseHandler使用django模板进行渲染,如果你想可以将模板引擎切换到推荐的jinja2。此外,代码访问从 BaseHandler 继承的用户对象,对其执行一些操作并将其呈现给模板。您可以尝试创建自己的请求处理程序,子类 BaseHandler 并执行您想要的操作。

2)我可以操纵代码,但我不是专家,所以你也应该能够做到。我想要一个简单的 FB 应用程序来显示随机图像,并且我可以操纵它通过 blob 选择随机图像并渲染到模板,同时保留 facebook 基本功能。用于让用户使用 Graph API 的函数我这样做:

def parse_signed_request(signed_request, secret):
    """
    Parse signed_request given by Facebook (usually via POST),
    decrypt with app secret.

    Arguments:
    signed_request -- Facebook's signed request given through POST
    secret -- Application's app_secret required to decrpyt signed_request
    """

    if '.' in signed_request:
        (esig, payload) = signed_request.split('.')
    else:
        return {}

    sig = urlsafe_b64decode(str(esig))
    data = _parse_json(urlsafe_b64decode(str(payload)))

    if not isinstance(data, dict):
        raise SignedRequestError('Pyload is not a json string!')
        return {}

    if data['algorithm'].upper() == 'HMAC-SHA256':
        if hmac.new(secret, payload, hashlib.sha256).digest() == sig:
            return data
    else:

        raise SignedRequestError('Not HMAC-SHA256 encrypted!')

    return {}


def get_user_from_cookie(cookies, app_id, app_secret):
    """Parses the cookie set by the official Facebook JavaScript SDK.

    cookies should be a dictionary-like object mapping cookie names to
    cookie values.

    If the user is logged in via Facebook, we return a dictionary with the
    keys "uid" and "access_token". The former is the user's Facebook ID,
    and the latter can be used to make authenticated requests to the Graph API.
    If the user is not logged in, we return None.

    Download the official Facebook JavaScript SDK at
    http://github.com/facebook/connect-js/. Read more about Facebook
    authentication at http://developers.facebook.com/docs/authentication/.
    """
    cookie = cookies.get('fbsr_' + app_id, '')
    if not cookie:
        return None
    response = parse_signed_request(cookie, app_secret)
    if not response:
        return None

    args = dict(code=response['code'], client_id=app_id,
                client_secret=app_secret, redirect_uri='')

    file = \
        urllib.urlopen('https://graph.facebook.com/oauth/access_token?'
                       + urllib.urlencode(args))
    try:
        token_response = file.read()
    finally:
        file.close()

    access_token = cgi.parse_qs(token_response)['access_token'][-1]
    logging.debug('returning cookie')
    return dict(uid=response['user_id'], access_token=access_token)

请参阅 http://developers.facebook。 com/docs/api 获取 API 的完整文档。您可以在 http://github.com/facebook/connect-js 获取官方 Facebook JavaScript SDK /

我现在正在编写代码以将 webapp2_extras.auth 帐户与 facebook 同步,以便自定义帐户和 facebook 帐户可以共存,我们正在 webapp2 群组和类别。我目前的做法是将推荐的 current_user 添加到基本处理程序中,并在“合并”我的类 FBUser 时使用它作为 FB 身份,FBUser 是授权我的网站的 facebook 用户的自定义类, /或画布应用程序与 webapp2_extras.auth.models.User 同步,这是一个 Expando 模型,因此它可以只添加它没有的属性,例如 facebookid、名字、姓氏等。

@property
def current_user(self):
    if not hasattr(self, '_current_user'):
        self._current_user = None
        cookie = get_user_from_cookie(self.request.cookies,
                facebookconf.FACEBOOK_APP_ID,
                facebookconf.FACEBOOK_APP_SECRET)
        if cookie:

            # Store a local instance of the user data so we don't need
            # a round-trip to Facebook on every request
            user = FBUser.get_by_key_name(cookie['uid'])
            if not user:
                graph = GraphAPI(cookie['access_token'])
                profile = graph.get_object('me')
                user = FBUser(key_name=str(profile['id']),
                              id=str(profile['id']),
                              name=profile['name'],
                              profile_url=profile['link'],
                              access_token=cookie['access_token'])
                user.put()
            elif user.access_token != cookie['access_token']:
                user.access_token = cookie['access_token']
                user.put()
            self._current_user = user
    return self._current_user

您可以还可以使用会话对象解决身份验证问题,并围绕它构建身份验证系统。这就是我在使用自定义帐户和 Facebook 帐户时所做的事情,欢迎您访问我的存储库有关更多代码示例,请参阅如何使用 python 2.7 将 facebook 与 google 应用引擎集成。

The python "SDK" for facebook I use I took from https://gist.github.com/1190267
and combined it with the code from the example app to achieve the functionality I wanted both for a canvas app and for website usage.

It depends whether you're using facebook with websites or a canvas application. For a canvas application you probably could do well with the javascript SDK but for a "login with facebook" I required serverside logic that should work with javascript turned off so I've completed that solution with details you might have help to know. You can try make small changes of that specific app 'runwithfriends' to get an understanding which code does what. The project you're looking at contains some outdated practice though:

  • getting and setting cookies is likely preferable now doing with webapp2's builtin functions for this instead of the code that comes with the FB example app

  • logging in and out is now done with OAuth 2.0 so it's likely that the login system you're looking at is outdated and you need to use OAuth 2.0 which is described here. I much rather do login/logout serverside so I did an OAuth 2.0 pure python solution to login / logout following the authentication steps mentioned in the tutorial from FB. I had to clear the cookie to log a user out which was not documented.

  • To upgrade to python 2.7 I had to also modify so that HTTP header did not cast to unicode. I don't know why but otherwise it complained that headers were "not strings"

To more elaborately answer your specific questions:

1) The requesthandler class you posted is a subclass of a BaseHandler so to fully understand what it does you can look at the BaseHandler class since what you are posting is a BAseHandler. The BaseHandler uses django templates for rendering and if you want to can switch the template engine to jinja2 which is remmended. Further the code accesses the user object inherited from the BaseHandler and does some operations on it and renders it to a template. You can try make a requesthandler of your own, subclass BaseHandler and do what you want.

2) I could manipulate the code and I'm not an expert so you should be able to do it too. I wanted a simple FB app to display random images and I could manipulate it to select random images via blobs and render to to a template while keeping the facebook base functions. A function to use for getting the user using the Graph API I do this:

def parse_signed_request(signed_request, secret):
    """
    Parse signed_request given by Facebook (usually via POST),
    decrypt with app secret.

    Arguments:
    signed_request -- Facebook's signed request given through POST
    secret -- Application's app_secret required to decrpyt signed_request
    """

    if '.' in signed_request:
        (esig, payload) = signed_request.split('.')
    else:
        return {}

    sig = urlsafe_b64decode(str(esig))
    data = _parse_json(urlsafe_b64decode(str(payload)))

    if not isinstance(data, dict):
        raise SignedRequestError('Pyload is not a json string!')
        return {}

    if data['algorithm'].upper() == 'HMAC-SHA256':
        if hmac.new(secret, payload, hashlib.sha256).digest() == sig:
            return data
    else:

        raise SignedRequestError('Not HMAC-SHA256 encrypted!')

    return {}


def get_user_from_cookie(cookies, app_id, app_secret):
    """Parses the cookie set by the official Facebook JavaScript SDK.

    cookies should be a dictionary-like object mapping cookie names to
    cookie values.

    If the user is logged in via Facebook, we return a dictionary with the
    keys "uid" and "access_token". The former is the user's Facebook ID,
    and the latter can be used to make authenticated requests to the Graph API.
    If the user is not logged in, we return None.

    Download the official Facebook JavaScript SDK at
    http://github.com/facebook/connect-js/. Read more about Facebook
    authentication at http://developers.facebook.com/docs/authentication/.
    """
    cookie = cookies.get('fbsr_' + app_id, '')
    if not cookie:
        return None
    response = parse_signed_request(cookie, app_secret)
    if not response:
        return None

    args = dict(code=response['code'], client_id=app_id,
                client_secret=app_secret, redirect_uri='')

    file = \
        urllib.urlopen('https://graph.facebook.com/oauth/access_token?'
                       + urllib.urlencode(args))
    try:
        token_response = file.read()
    finally:
        file.close()

    access_token = cgi.parse_qs(token_response)['access_token'][-1]
    logging.debug('returning cookie')
    return dict(uid=response['user_id'], access_token=access_token)

See http://developers.facebook.com/docs/api for complete documentation for the API. And you can get the the official Facebook JavaScript SDK at http://github.com/facebook/connect-js/

I'm now writing code to sync a webapp2_extras.auth account with facebook so that custom accounts and facebook accounts can co-exist and we're discussing solutions for this in the webapp2 groups and categories. The current way I do it is adding the recommended current_user to a basehandler and using that as the FB identity while working on "merging" my class FBUser that is a custom class for facebook users that autheorized my website and/or canvas application to sync with webapp2_extras.auth.models.User which is an expando model so it can just add the properties it doesn't have such as facebookid, firstname, lastname, etc.

@property
def current_user(self):
    if not hasattr(self, '_current_user'):
        self._current_user = None
        cookie = get_user_from_cookie(self.request.cookies,
                facebookconf.FACEBOOK_APP_ID,
                facebookconf.FACEBOOK_APP_SECRET)
        if cookie:

            # Store a local instance of the user data so we don't need
            # a round-trip to Facebook on every request
            user = FBUser.get_by_key_name(cookie['uid'])
            if not user:
                graph = GraphAPI(cookie['access_token'])
                profile = graph.get_object('me')
                user = FBUser(key_name=str(profile['id']),
                              id=str(profile['id']),
                              name=profile['name'],
                              profile_url=profile['link'],
                              access_token=cookie['access_token'])
                user.put()
            elif user.access_token != cookie['access_token']:
                user.access_token = cookie['access_token']
                user.put()
            self._current_user = user
    return self._current_user

You can also solve your authentication with session objects and build your authentication system around that. That is what I do when using both custom accounts and facebook accounts and you're welcome to have a lok at my repository for more code examples how to intregrate facebook with google app engine using python 2.7.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文