miguelgrinberg / Flask-SocketIO

Socket.IO integration for Flask applications.
MIT License
5.31k stars 888 forks source link

new to this. how to implement socketio in my app, or side app for simple webchat #399

Closed kinganu closed 7 years ago

kinganu commented 7 years ago

Hi I am using this type of set up for my web applications, on Ubuntu 16, Python 3.5, Apache2.4.18 with mod-wsgi to serve my apps. From your docs it appears I will have to use another type of Web server in order to use flask-socketio. I want to build a simple web chat feature for my users, for live technical support, and later try building a simple social application with different chat rooms and search filters. Would I be able to utilize a standalone flask-socketio application side-by-side with my wsgi application somehow (and perhaps be able to use my current register/ login system to grab my user's usernames from the database for use in this chat functionality)? I suppose all I would use in terms of users database is their username for chat, ie something like

if 'username' == session['username']:

and use that as the users chat handle.

But the current crux is figuring out how to use flask-socketio next to my regular application.

Thanks bro

miguelgrinberg commented 7 years ago

Unfortunately mod_wsgi does not work well with WebSocket. If you are not attached to Apache, my recommendation is that you switch to nginx+gunicorn, which is a combination that will allow you to run your current app plus any Flask-SocketIO based features that you add, all together in a single app.

If that's not an option, you can always run nginx+gunicorn for a Flask-SocketIO app that does all the chat/social stuff, while the rest remains on Apache. It is sort of a weird combination, and will complicate sharing of state (such as the session you ask about above).

kinganu commented 7 years ago

Thanks, I just checked out digital oceans guides for configuring flask applications with gunicorn and nginx, as well as setting up SSL with lets encrypt on ubuntu 16. Seems simple enough. I'm excited to add this configuration to my skill set, as I have heard a lot of good things about nginx, being a better way to serve multiple applications on one server. Flask with mod wsgi + apache2 is good for quick apps but maybe nginx is more modern.

I want to tinker around with Flask-SocketIO in building a web chat page, which will be another good feature to be able to market as a web developer. What would be really kick ass and could possibly be a good moneymaker as a professional web application, is to copy/recreate the functionality of this very well constructed social dating site dateinasia.com. I'm pretty sure it uses sockets and it's quite impressive how it's put together. It has a good user profile with image uploads, search filters for country, city, age, and more, favorites, message history for individual conversations, and a few chat rooms as well as alert flashing and live updating every 10 seconds. The cool thing is it's a totally free service and it pretty much beats every other dating site out there. It's worth taking a look at and though I am at a loss on how to re-create such an awesome application maybe a genius like you could be up to the task. I will try to create something simpler and see how it goes. Anyways cheers later m8.

On Thu, Feb 2, 2017 at 12:40 AM, Miguel Grinberg notifications@github.com wrote:

Unfortunately mod_wsgi does not work well with WebSocket. If you are not attached to Apache, my recommendation is that you switch to nginx+gunicorn, which is a combination that will allow you to run your current app plus any Flask-SocketIO based features that you add, all together in a single app.

If that's not an option, you can always run nginx+gunicorn for a Flask-SocketIO app that does all the chat/social stuff, while the rest remains on Apache. It is sort of a weird combination, and will complicate sharing of state (such as the session you ask about above).

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/miguelgrinberg/Flask-SocketIO/issues/399#issuecomment-276888500, or mute the thread https://github.com/notifications/unsubscribe-auth/AQGf6cXqpWqmEClF9yO5XlWjZnzWNvddks5rYYhpgaJpZM4L0wq_ .

miguelgrinberg commented 7 years ago

@kinganu You may want to check out my Flack application. This is a chat app written with Flask, Celery and Flask-SocketIO. I did a 3 hour tutorial about it last year at PyCon called "Flask At Scale". You can find it in youtube if you are interested.

kinganu commented 7 years ago

Thanks, I skimmed through that presentation. It is mind blowing how much complexity goes into a simple chat application in order to optimize it. I am nowhere near that level of tweaking configurations in your application, but I can follow along - barely lol.

I just cloned and ran your basic readme commands. Worked more or less but on celery start get this message below. The page shows on localhost:5000 but new user register button wont connect, just sits there. Perhaps an upgrade of all pip packages for this venv might help, or break things I dont know. Maybe it needs a little updating. Anyways it would be cool to have a sort of copy pastable basic chat app like this, where I as an amateur could utilize this in production behind gunicorn + nginx. Do you know what Id have to change as far as config stuff in order to get this running behind a proper server setup like that? Or is it worth the trouble?

python manage.py celery [2017-02-02 17:30:51,095: WARNING/MainProcess] /var/www/flack/venv/lib/python3.5/site-packages/celery/apps/worker.py:161: CDeprecationWarning: Starting from version 3.2 Celery will refuse to accept pickle by default.

The pickle serializer is a security concern as it may give attackers the ability to execute any command. It's important to secure your broker from unauthorized access when using pickle, so we think that enabling pickle should require a deliberate action and not be the default choice.

If you depend on pickle then you should set a setting to disable this warning and to be sure that everything will continue working when you upgrade to Celery 3.2::

CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'msgpack', 'yaml']

You must only enable the serializers that you will actually use.

warnings.warn(CDeprecationWarning(W_PICKLE_DEPRECATED))

-------------- celery@k1vm v3.1.23 (Cipater) ---- * ----- --- * -- Linux-4.4.0-59-generic-i686-with-Ubuntu-16.04-xenial -- - **** ---

[2017-02-02 18:27:17,369: ERROR/MainProcess] consumer: Cannot connect to redis://localhost:6379//: . Trying again in 2.00 seconds...

[2017-02-02 18:27:19,378: ERROR/MainProcess] consumer: Cannot connect to redis://localhost:6379//: . Trying again in 4.00 seconds...

On Thu, Feb 2, 2017 at 8:57 AM, Miguel Grinberg notifications@github.com wrote:

@kinganu https://github.com/kinganu You may want to check out my Flack https://github.com/miguelgrinberg/flack application. This is a chat app written with Flask, Celery and Flask-SocketIO. I did a 3 hour tutorial about it last year at PyCon called "Flask At Scale". You can find it in youtube if you are interested.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/miguelgrinberg/Flask-SocketIO/issues/399#issuecomment-276997270, or mute the thread https://github.com/notifications/unsubscribe-auth/AQGf6RMosxePatOwrw1bjH7Nc_AzKG8Wks5rYfzWgaJpZM4L0wq_ .

miguelgrinberg commented 7 years ago

It is mind blowing how much complexity goes into a simple chat application in order to optimize it.

Yes, but getting to this level is only necessary if you plan on having large number of clients. I used a chat application as an example because the actual logic is quite simple, but the point of the class was to show how far you can get opimizing and scaling. If your needs are not that demanding, you may be just fine using one of the early versions of Flack I showed in the class, before I went nuts with Celery, Socket.IO, etc.

kinganu commented 7 years ago

Hello Miguel, hope you are doing well. I was able to configure my websites using nginx, and soon I'm going to attempt to get a quite basic version of Live web chat working using flask socketIO. A couple relatively basic features I would like to implement though are, email confirmation on account creation and password reset function for a user in case they forget password. I believe both have relatively similar processes making use of a token associated with users session or email? I took a look at your big tutorial but was not able to get them working, I must be missing something.

I have a very light weight web application with a basic register / login system as shown at the paste below and was wondering how easy it would be to implement email confirmation and password reset processes. If you have a minute to take a glance or give me some direction that would be much appreciated. And I frequently share my latest web tidbits and tips with pythonprogramming.net to help others learn. If it's too much hassle, no worries. Anyways thanks.

https://dpaste.de/Pizc

miguelgrinberg commented 7 years ago

@kinganu I covered creation of a complete user system in my book: https://flaskbook.com.

kinganu commented 7 years ago

awesome got your book looks awesome and very thorough. thanks brother

On Fri, Mar 3, 2017 at 9:00 AM, Miguel Grinberg notifications@github.com wrote:

@kinganu https://github.com/kinganu I covered creation of a complete user system in my book: http://flaskbook.com.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/miguelgrinberg/Flask-SocketIO/issues/399#issuecomment-283992914, or mute the thread https://github.com/notifications/unsubscribe-auth/AQGf6a-2Wd-qGYjLa6Sf-ijUsWcTo4g1ks5riDk7gaJpZM4L0wq_ .

kinganu commented 7 years ago

hey I am trying to get flask-moment to work. cannot for the life of me. checked like 4 stack overflow posts and still nothing works. maybe the extension is broken or something.

followed the workflow in your book exactly. I dont know if the bootstrap files are even inheriting properly because if I remove my manual stylesheets the page looks like crap. I have pip installed flask-bootstrap and flask-moment in venv.

from datetime import timedelta, datetime from flask_bootstrap import Bootstrap from flask_moment import Moment

app = Flask(name) bootstrap = Bootstrap(app) moment = Moment(app)

@app.route("/") def homepage(): return render_template("index.html", current_time=datetime.utcnow())

base.html

{% extends "bootstrap/base.html" %} {% block scripts %} {{ super() }} {{ moment.include_jquery() }} {{ moment.include_moment() }} {% endblock %}

index.html

{% extends "base.html" %}

The local date and time is {{moment(current_time).format('LLL')}}.

That was {{moment(current_time).fromNow(refresh=True)}}

miguelgrinberg commented 7 years ago

@kinganu you seem to be missing a block where the main contents of the site are inserted. In base.html, you should have something like this, and in index.html something like this. In your case the contents of the blocks are going to be simpler, but that's the correct structure.

kinganu commented 7 years ago

thanks man. so I tried using those blocks, was a little troublesome. I found a better solution, to use an include! because it makes more sense to have a little time widget inserted wherever its needed. like so:

index.html

{% include 'includes/time.html' %} {% block time %} {% endblock %}

includes/time.html

{{ moment.include_jquery() }} {{ moment.include_moment() }}

{% block time %}

The local date and time is {{moment(current_time).format('LLL')}}.

That was {{moment(current_time).fromNow(refresh=True)}}

{% endblock %}

It shows time but its off an hour, probably my browser is off or something. 2 fast questions though if you could my friend.

1) on flask bootstrap. I get this error when I try to put it on my base.html : 'jinja2.exceptions.TemplateAssertionError: cannot use extend from a non top-level scope'. seems like its not pulling properly, when I comment out my hard coded <link rel=stylesheet src=assets/css/bootstrap.min.css etc> the page turns to jumbled mess. heres my base below.

2) how can i make current_time variable global to aid in usage anywhere, rather than in one view function? ie:

current_time=datetime.utcnow())

@app.route("/") def homepage(): return render_template("index.html", current_time=datetime.utcnow())

base.html

<!DOCTYPE html>

SkyLine {% block title %}{% endblock %} {% extends "bootstrap/base.html" %}
{% block header %} {% endblock %}
{% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %}
{% endfor %} {% endif %} {% endwith %}
{% block body %} {% endblock %} {% block jscripts %} {% endblock %}