Question

I've written a small app in Flask, and I'm trying to get it to work on a Linode server. But currently, if I enter the server IP address in my browser, I get a list of files.

I have python installed not in a virtualenv (currently), checked, it's working.

I've been mostly following this tutorial: https://www.digitalocean.com/community/articles/how-to-deploy-a-flask-application-on-an-ubuntu-vps

My app structure is this (the top folder is located in /var/www/):

|--mythmuff/
|----mythmuff/
|------__init__.py
|------app.db
|------config.py
|------models.py
|------templates/
|--------index.html
|------views.py
|--mythmuff.wsgi

Here's my init.py:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.mail import Mail
import os
basedir = os.path.abspath(os.path.dirname(__file__))


app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'app.db')
# app email settings go here
mail = Mail(app)
db = SQLAlchemy(app)

import views
import models

Here's my mythmuff.wsgi:

import sys
sys.path.insert(0, '/var/www/mythmuff')
from mythmuff import app as application

And here's my /etc/apache2/sites-available/mythmuff.ru.conf (I 'pointed' Apache to the file).

<VirtualHost *:80>
    ServerName mythmuff.ru

    WSGIDaemonProcess mythmuff user=www-data group=www-data threads=5
    WSGIScriptAlias / /var/www/mythmuff/mythmuff.wsgi

    <Directory var/www/mythmuff/mythmuff>
        Order allow,deny
        Allow from all
    </Directory>
    Alias /static /var/www/mythmuff/mythmuff/static
    <Directory /var/www/mythmuff/mythmuff/static>
        Order allow,deny
        Allow from all
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    LogLevel warn
</VirtualHost>

I'm quite new in the area of setting up Apache/wsgi, but I think the fact that when I go to the IP address and get just a list of files and folders in the /var/www/ directory means that I'm missing an app.run() somewhere. I tried adding this to __init__.py:

if __name__ == "__main__":
    app.run()

But I get an error when running __init__.py on my home computer:

  File "/Users/georgeoblapenko/Dropbox/University/Python/flask/MythMuff/mythmuff/mythmuff/__init__.py", line 18, in <module>
    import views
  File "/Users/georgeoblapenko/Dropbox/University/Python/flask/MythMuff/mythmuff/mythmuff/views.py", line 5, in <module>
    from models import Product
  File "/Users/georgeoblapenko/Dropbox/University/Python/flask/MythMuff/mythmuff/mythmuff/models.py", line 6, in <module>
    class Product(db.Model):
  File "/Users/georgeoblapenko/anaconda/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 510, in __init__
    DeclarativeMeta.__init__(self, name, bases, d)
  File "/Users/georgeoblapenko/anaconda/lib/python2.7/site-packages/sqlalchemy/ext/declarative/api.py", line 53, in __init__
    _as_declarative(cls, classname, cls.__dict__)
  File "/Users/georgeoblapenko/anaconda/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 246, in _as_declarative
    **table_kw)
  File "/Users/georgeoblapenko/anaconda/lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 342, in __new__
    "existing Table object." % key)
sqlalchemy.exc.InvalidRequestError: Table 'product' is already defined for this MetaData instance.  Specify 'extend_existing=True' to redefine options and columns on an existing Table object.

At home, I ran a runserver.py script from the top mythmuff folder for testing (as documented here: http://flask.pocoo.org/docs/patterns/packages/).

So, what do I need to add to actually make the whole thing work?

Update: I decided to run a simple wsgi hello world test. So I replaced everything in mythmuff.wsgi with

import os
import sys
sys.path.append('/var/www/mythmuff/mythmuff')

def application(environ, start_response):
        status = '200 OK'
        output = 'Hello World!'

        response_headers = [('Content-type', 'text/plain'),
                                        ('Content-Length', str(len(output)))]
        start_response(status, response_headers)
        return [output]

However, I still get the files/folder list, instead of the "Hello World!" page. So it seems the request doesn't get passed to the WSGI for some reason.

Was it helpful?

Solution

OK, I managed to figure it out. Turns out, I deleted the default apache index.html file, and didn't disable the 000-default.conf (via dissite), so that's why it showing the folder. Everything works now.

OTHER TIPS

Yeah. If you want to access the server via the external IP address, you have to disable the default site configuration first.

sudo a2dissite 000-default.conf
service apache2 restart
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top