質問

I've set up a Django project and I'm integrating it with version 2.x of Mopidy's pyspotify. I wrote a piece of code that checks for a Spotify session instance, creates one if there isn't one and then gets the name of a track from a Spotify URI. The code is as follows:

def spotify_logic(request):

    if spotify.session_instance is not None:
        foo = spotify.Track('spotify:track:7fHnHy7pH4hHLQxBq1NbE8')
        foo.load()
        name = foo.name
    else:
        config = spotify.SessionConfig()
        config.application_key_filename = os.path.dirname(os.path.realpath(__file__)) + '/spotify_appkey.key'
        session = spotify.Session(config=config)

        session.login('TehNanor', '*******')
        session.process_events()

        foo = spotify.Track('spotify:track:7fHnHy7pH4hHLQxBq1NbE8')
        foo.load()
        name = foo.name

    return render(request, 'clupus/spotify.html', {'name': name})

When I run the project locally using ./manage.py runserver and access the server it displays the name of the song: "Phase 11 - Until We Meet the Sky". When I pull the changes onto my Apache server and access the URL I get the following traceback.

Environment:


Request Method: GET
Request URL: http://ec2-54-196-205-226.compute-1.amazonaws.com/spotify/

Django Version: 1.6.1
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'raudio')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')


Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  114.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ubuntu/public_html/clupus.com/clupus/raudio/views.py" in spotify_logic
  63.         foo.load()
File "/usr/local/lib/python2.7/dist-packages/spotify/track.py" in load
  66.         return utils.load(self, timeout=timeout)
File "/usr/local/lib/python2.7/dist-packages/spotify/utils.py" in load
  126.         raise RuntimeError('Session must be logged in to load objects')

Exception Type: RuntimeError at /spotify/
Exception Value: Session must be logged in to load objects

I've tried a dozen variations of the code and every iteration that works on local doesn't work on production. I can only imagine the problem is because I use ./manage.py runserver locally and have a mod_wsgi approach on my Apache server but I'm having difficulty figuring out how I can rectify this.

役に立ちましたか?

解決

This was already answered in #mopidy on freenode, but since others might find the question here is the answer and some explanation.

libspotify and thus pyspotify is not thread safe. There is global state for the library so the setup of the global session need to be moved so that it is only done once a startup. A typical way to do this in django is to move it to the __init__ method for a middleware, and then attach the global state to each request.

class SpotifyMiddlware(object):
    def __init__(self):
        config = spotify.SessionConfig()
        config.application_key_filename = os.path.join(
            os.path.dirname(os.path.realpath(__file__)), 'spotify_appkey.key')

        self.session = spotify.Session(config=config)
        self.session.login('TehNanor', '*******')
        while not self.session.user:
            self.session.process_events()

    def process_request(self, request):
        request.spotify = self.session

Waiting for the login to complete could also be done doing a callback + a threading event. Our you could simply check the login state in your views, or even in the middleware's process_request

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top