I’m trying to start python-telegram-bot in a web application with the django framework. To do this, I follow any example from the Telegram library and end up calling the method application.run_polling(). I know it’s not the best option because this blocks my web server, and I want to replace it with a better one, but I can’t find it.
According to official documentation, there is a tip that indicates the following:
When combining python-telegram-bot with other asyncio based frameworks, using this method is likely not the best choice, as it blocks the event loop until it receives a stop signal as described above. Instead, you can manually call the methods listed below to start and shut down the application and the updater. Keeping the event loop running and listening for a stop signal is then up to you.
And then I find the following section:
See also
initialize(), start(), stop(), shutdown() telegram.ext.Updater.start_polling(), telegram.ext.Updater.stop(), run_webhook()
I’ve tried to understand the methods in the list, but I can’t figure out how to run python-telegram-bot in the background and not affect my main server.
Are there any links or documents that expand the information or detail the steps to follow in these cases?
Thank you in advance
EDIT: Telegram I run it from an app configured in django as follows:
import asyncio
from django.apps import AppConfig
from telegram import Update
from telegram.ext import ContextTypes, Application, CommandHandler
from TaixTracking.configApp import ConfigApp
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text("Help!")
async def start_telegram():
application = Application.builder().token(ConfigApp().get_value('telegram', 'token', '')).build()
application.add_handler(CommandHandler("help", help_command))
await application.initialize()
await application.start()
await application.updater.start_polling()
print('Telegram load')
class CommunicationConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'communication'
def ready(self):
if not ConfigApp().is_telegram_launch():
ConfigApp().set_telegram_launch(True)
asyncio.run(start_telegram())
Related
I created a Django website and I want to launch a tkinter program if the user clicks on a button. Can anyone tell me how to do that?
Any help is appreciated.
Generally, websites cannot cause other programs on the user's computer to run just by clicking a button on a webpage. The next-best thing is a specialized link that the client understands is associated with another installed application. See: How can I launch my windows app when a users opens a url?
If you happen to be running the django server on the same local system AND is running in the foreground by the same currently logged in user, you could also invoke a GUI program this way, as well for example using subprocess or os.system. Though, this would be quite an odd way to do this.
def my_view(): # Technically works, but in very limited practical use cases.
subprocess.Popen(['python', 'my-tk-app.py'])
Because tkinter also doesn't like to be run in any other thread besides the main thread, and other event loop-related issues, it's not really practical to invoke a tkinter app directly from a Django view, which usually will be running in a separate thread and needs to not be blocked.
For example, this would not work:
def my_view():
root.mainloop() # start the TK app
# fails because tk only wants to start in the main thread
# even if TK _could_ start, the view would eventually timeout
If you need a local tkinter app to also interface with a django server, you're almost always going to be better off by making your GUI app a client of the server -- that is to say, your tkinter app should use HTTP(S) or similar mechanism to communicate with Django.
I'm trying to use Channels2 in my project. it's the first time that I meet channel in Django :)
I have two main useful and almost complete sources here: 1)video on youtube DJANGO CHANNELS 2 Tutorial (V2) - Real Time 2)document of Channel in Read The Doc
as I don't know what will happen in the future of my code I need you to help me choose using between AsyncConsumer as mentioned in source #1, or AsyncWebsocketConsumer that is used in source # 2 for starting Django channel app that including by this way:
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.consumer import AsyncConsumer
explanation:
class AsyncConsumer:
"""
Base consumer class. Implements the ASGI application spec, and adds on
channel layer management and routing of events to named methods based
on their type.
"""
class AsyncWebsocketConsumer(AsyncConsumer):
"""
Base WebSocket consumer, async version. Provides a general encapsulation
for the WebSocket handling model that other applications can build on.
"""
my goal of using channel: trying to integrated real-time chat, notification/alert/transfer_data to the clients for the specific situations. (now the app working without Websocket with DRF)
and if you have any suggestions, ideas or notices I will be very happy to listen.thank you so much.
Channels is a project meant to be used to work with different protocols including but not limited to HTTP and WebSockets as explained on the docs page.
The AsyncConsumer is the base generic consumer class from which other protocol-specific consumer classes are derived. One of those classes is the AsynWebsocketConsumer which you mentioned. As the name goes, it's used to work with websockets, so if you want use websockets for your realtime app, then that is the class you should use. There is also the AsyncHttpConsumer for working with HTTP. You most likely want to work with websockets so go with the AsynWebsocketConsumer or its derivative, AsyncJsonWebsocketConsumer.
I would also advise that you read the documentation to understand in better detail about the supported protocols and how and when to use them.
I want to execute one or more functions after a user logs into my site. How is this possible? I looked into Middleware. Djangobook says that I'll need this to run a piece of code on each and every request that Django handles. However, I just need the code run when the authentication happens successfully.
Note: I am using Django Allauth for authentication and I don't have any view of my own to log in users.
You need to tap into Allauth's signals. Specifically the user logged in signal
allauth.account.signals.user_logged_in(request, user)
Sent when a user logs in.
So add code similar to the following in your project.
from django.dispatch.dispatcher import receiver
from allauth.account.signals import user_logged_in
#receiver(user_logged_in, dispatch_uid="unique")
def user_logged_in_(request, user, **kwargs):
print request.user
This code should be in a place that's likely to be read when django starts up. models.py and views.py are good candidates.
As per the official documentation, there is a signal allauth.account.signals.user_logged_in which gets triggered when a user logs in. This can serve your purpose.
I have a Django application, and need to deal with the following:
One of my views, needs to make a POST request to another URL endpoint of the same application.
In order to do so, I use the requests module. I assemble the URL of the endpoint I need to call, dump the POST parameters, and perform the call.
This works fine for the most part, however fails miserably when testing, since the view that corresponds to the URL that I talk to, knows nothing about the state of the testing environment.
The code is similar to this:
from django.conf import settings
import json
def view1(request, *args, **kwargs):
url = 'http://api.%s/view2/' % settings.DOMAIN
r = requests.post(
url,
data=json.dumps({'key': 'value'}),
)
// Notice that the ``url`` is a url of the actual deployed application,
// and therefore knows nothing about testing and its state. That's where
// it goes wrong.
The question is, is there a way that this can behave correctly in testing? I use the django.test.client.Client class for creating my test requests. As far as I know, instances of this class talk directly to the URL mapper. Therefore the url that I construct in the view is simply an external http request to the deployed application, instead of the tested application.
Thanks.
One way to solve this is to mock the response from the URL for the purposes of the tests. I'd suggest using a lightweight mocking library, such as this:
http://blog.moertel.com/posts/2011-11-07-a-flyweight-mocking-helper-for-python.html
See the example code. It's very similar to your situation. I've used both of these in combination with requests and flask, but not django.
I love how django server auto-reloads itself on code change, so that no restarting the server is required.
We currently use django custom management commands that may take a very long time to complete.
Is there any way we can use the
auto-reloading feature of the django
server for our management command?
For example, if the change of the underlying django codebase is detected, the command reloads itself and resumes execution of the very long (stateless) loop.
Whatever your management command is doing, abstract that to a single function and call that function using django.utils.autoreload.main
from django.utils import autoreload
def do_something(*args, **kwargs):
# management command logic
class Command(BaseCommand):
def handle(self, *args, **options):
self.stdout('This command auto reloads. No need to restart...')
autoreload.main(do_something, args=None, kwargs=None)
For django 2.2 or above use
autoreload.run_with_reloader(do_something, args=None, kwargs=None)
Checkout the way runserver (specifically the run method) does it with the django.utils.autoreload module. You'll want to copy this pattern with your custom command.