Django async testing: Cannot operate on a closed database - django

I was following this tutorial on testdriven.io in order to test some async functions in django and I need to add som decorators in order to enable my async tests to access to the DB.
However, I get the following error message:
Error
Traceback (most recent call last):
File "/Users/apple/.local/share/virtualenvs/backend-KucV-wUh/lib/python3.9/site-packages/django/db/backends/base/base.py", line 237, in _cursor
return self._prepare_cursor(self.create_cursor(name))
File "/Users/apple/.local/share/virtualenvs/backend-KucV-wUh/lib/python3.9/site-packages/django/db/backends/sqlite3/base.py", line 274, in create_cursor
return self.connection.cursor(factory=SQLiteCursorWrapper)
sqlite3.ProgrammingError: Cannot operate on a closed database.
#database_sync_to_async
def create_user():
user = User.objects.create(
username='username',
)
user.set_password('password')
user.save()
#pytest.mark.asyncio
#pytest.mark.django_db(transaction=True)
class WebsocketTests(TestCase):
async def test_not_authenticated(self):
await create_user()
..... other async functions

make sure to `pip install pytest pytest-django pytest-asyncio
use #pytest.mark.asyncio and #pytest.mark.django_db(transaction=True)
from asgiref.sync import sync_to_async
from channels.db import database_sync_to_async
#database_sync_to_async
def MakeMessage():
Message.objects.create()
#pytest.mark.asyncio
#pytest.mark.django_db(transaction=True)
class TestWebSocket:
async def test_connection(self, settings):
communicator = WebsocketCommunicator( application=application, path=path )
connected, _ = await communicator.connect()
assert connected
m = await sync_to_async(Message.objects.count)()
assert m == 0
await MakeMessage()
m = await sync_to_async(Message.objects.count)()
assert m == 1
#settings.py
WSGI_APPLICATION = 'frosty_breeze_25125.wsgi.application'
ASGI_APPLICATION = 'frosty_breeze_25125.asgi.application'
host = os.environ.get('REDIS_URL', 'redis://localhost:6379') if IS_DEPLOYED else ('0.0.0.0', 6379)
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [host],
},
},
}
REDIS_URL = [host]

Related

Asynchrony in Python. How to receive requests in a Python Telegram bot and at the same time perform another function

I am coding telegram-bot, using Flask and asyncio. And I have a function for receiving and processing requests - get_messages(). And test function - sleep_func(), which will sleep for a while(20 seconds), but get_messages() will be working at this moment, when sleep_func() is sleeping. After 20 seconds sleep_func() must wake up, print some text, but doesn't finish the get_messages(). So, I want to implement asynchrony. I tried to do this, using asyncio.create_task, that worked, but only for one request(see at the comments in get_messages()). Now I tried another way, but it gives me this error:
ERROR:asyncio:Task exception was never retrieved
future: <Task finished name='Task-7' coro=<get_messages() done, defined at D:\Python_Labs\FilmMarketBot\fm_bot.py:31> exception=RuntimeError('Timeout context manager should be used inside a task')>
Traceback (most recent call last):
File "D:\Python_Labs\FilmMarketBot\fm_bot.py", line 37, in get_messages
await message(bot)
File "D:\Python_Labs\FilmMarketBot\bot_files\message_handling.py", line 14, in message
await commands(bot, chat_id)
File "D:\Python_Labs\FilmMarketBot\bot_files\messages\bot_commands\commands.py", line 11, in commands
await start(bot, chat_id)
File "D:\Python_Labs\FilmMarketBot\bot_files\messages\bot_commands\commands_methods.py", line 11, in start
await bot.send_message(chat_id, f"Hello, {first_name}!")
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiogram\bot\bot.py", line 339, in send_message
result = await self.request(api.Methods.SEND_MESSAGE, payload)
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiogram\bot\base.py", line 231, in request
return await api.make_request(await self.get_session(), self.server, self.__token, method, data, files,
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiogram\bot\api.py", line 139, in make_request
async with session.post(url, data=req, **kwargs) as response:
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiohttp\client.py", line 1138, in __aenter__
self._resp = await self._coro
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiohttp\client.py", line 466, in _request
with timer:
File "D:\Python_Labs\FM_Bot_test\venv\lib\site-packages\aiohttp\helpers.py", line 701, in __enter__
raise RuntimeError(
RuntimeError: Timeout context manager should be used inside a task
This is my fm_bot.py:
# бібліотека request для отримання запитів(повідомлень), які надходять на Flask-сервер від Телеграм-серверу і Stripe
from flask import Flask, request
import logging
from aiogram import Bot, Dispatcher
from threading import Thread
# from dotenv import load_dotenv
from time import sleep
import asyncio
import time
from bot_files.models import db, Users, Films, Purchases
from bot_files.message_handling import message, callback_query, object, other_messages
# from bot_files.other import technical_works
from bot_files.chat_member import delete_user
from bot_files.stripe import create_stripe_webhook
from bot_files.objects.stripe_requests_files.purchases import add_purchase
from bot_files.config import *
logging.basicConfig(level=logging.INFO)
bot = Bot(token=bot_token)
dp = Dispatcher(bot)
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = db_url
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
db.init_app(app)
async def get_messages():
print("Flag")
print(request.json)
message_type = list(request.json.keys())[1]
if message_type == 'message':
await message(bot)
elif message_type == 'callback_query':
await callback_query(bot, payment_token, stripe_token)
elif message_type == 'my_chat_member':
chat_id = request.json["my_chat_member"]["chat"]["id"]
if request.json["my_chat_member"]["new_chat_member"]["status"] == "kicked":
await delete_user(chat_id)
elif message_type == 'object':
await object(bot)
elif message_type == 'pre_checkout_query':
# Номер карти - 4242 4242 4242 4242
chat_id = request.json["pre_checkout_query"]["from"]["id"]
await add_purchase(bot, chat_id)
pre_checkout_query_id = request.json["pre_checkout_query"]["id"]
await bot.answer_pre_checkout_query(pre_checkout_query_id, True)
# else:
# await other_messages(bot)
return {"get_messages is ok": True}
async def sleep_func():
await asyncio.sleep(20)
print("Hello!")
#app.route('/' + bot_token, methods=['POST'])
async def asynchrony():
#start_time = time.time()
#get_messages_task = asyncio.create_task(get_messages())
#sleep_task1 = asyncio.create_task(sleep_func())
#sleep_task2 = asyncio.create_task(sleep_func())
#await asyncio.wait([get_messages_task, sleep_task1])
#print(time.time() - start_time)
get_messages_task = asyncio.create_task(get_messages())
await asyncio.wait([get_messages_task])
#await get_messages()
return {"asynchrony is ok": True}
#app.route('/')
async def webhook():
await bot.delete_webhook()
await bot.set_webhook(url=app_url)
# chat_id = None
await create_stripe_webhook(app_url, payment_token)
# await test_users()
# await test_films()
# await test_purchases()
# await test_discounts()
# while True:
# time_now = datetime.datetime.now()
# if datetime.date.today().isoweekday() == 4:
# await technical_works(bot)
sleep_task = asyncio.create_task(sleep_func())
await asyncio.wait([sleep_task])
return '!', 200
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))
I will be very appreciative for you help!
My answer is not suitable for this code, which is Flask-app. But it is answer for this question. So you must use Aiogram for asynchrony receiving and processing messages. Aiogram has special decorator async_task for this: https://docs.aiogram.dev/en/latest/_modules/aiogram/dispatcher/dispatcher.html#Dispatcher.async_task.
If your bot at the same time must perform another function, for example, change data in database once a day, you can create button only for administrator that will start infinity cycle which will sleep for number of seconds in one day.

django channels WebsocketCommunicator TimeoutError

I am trying to run the following test:
tests.py
from rest_framework.test import APITestCase
from myapp.routing import application
from channels.testing import WebsocketCommunicator
from account.models import User
from rest_framework.authtoken.models import Token
class Tests(APITestCase):
def setUp(self):
self.user = User.objects.create(email='test#test.test',
password='a password')
self.token, created = Token.objects.get_or_create(user=self.user)
async def test_connect(self):
communicator = WebsocketCommunicator(application, f"/ws/user/{self.token}/")
connected, subprotocol = await communicator.connect()
self.assertTrue(connected)
await communicator.disconnect()
application is a boilerplate instance of channels.routing.ProtocolTypeRouter (like in here: https://channels.readthedocs.io/en/latest/topics/routing.html). Everything works fine in production. The test exits with the following error:
Traceback (most recent call last):
File "/home/projects/myapp/myapp-env/lib/python3.7/site-packages/asgiref/testing.py", line 74, in receive_output
return await self.output_queue.get()
File "/usr/lib/python3.7/asyncio/queues.py", line 159, in get
await getter
concurrent.futures._base.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/projects/myapp/myapp-env/lib/python3.7/site-packages/asgiref/sync.py", line 223, in __call__
return call_result.result()
File "/usr/lib/python3.7/concurrent/futures/_base.py", line 428, in result
return self.__get_result()
File "/usr/lib/python3.7/concurrent/futures/_base.py", line 384, in __get_result
raise self._exception
File "/home/projects/myapp/myapp-env/lib/python3.7/site-packages/asgiref/sync.py", line 292, in main_wrap
result = await self.awaitable(*args, **kwargs)
File "/home/projects/myapp/myapp-api/app/tests.py", line 35, in test_connect
connected, subprotocol = await communicator.connect()
File "/home/projects/myapp/myapp-env/lib/python3.7/site-packages/channels/testing/websocket.py", line 36, in connect
response = await self.receive_output(timeout)
File "/home/projects/myapp/myapp-env/lib/python3.7/site-packages/asgiref/testing.py", line 85, in receive_output
raise e
File "/home/projects/myapp/myapp-env/lib/python3.7/site-packages/asgiref/testing.py", line 74, in receive_output
return await self.output_queue.get()
File "/home/projects/myapp/myapp-env/lib/python3.7/site-packages/asgiref/timeout.py", line 66, in __aexit__
self._do_exit(exc_type)
File "/home/projects/myapp/myapp-env/lib/python3.7/site-packages/asgiref/timeout.py", line 103, in _do_exit
raise asyncio.TimeoutError
concurrent.futures._base.TimeoutError
----------------------------------------------------------------------
Ran 1 test in 1.026s
I have tried python versions 3.7.5, 3.8.0 and 3.9.9 using channels 3.0.4 with django 3.2.10 and channels-redis 3.3.1 ('BACKEND': 'channels_redis.core.RedisChannelLayer' in settings.py). The error persists. What am I doing wrong?
I had the same problem. APITestCase or TestCase dont allow transactions, you have to use SimpleTestCase from django test, and set databases to all. Just with that difference i think it will work.
Note that the transactions will be saved between test, and not rolled back after the test.
from django.test import SimpleTestCase
from myapp.routing import application
from channels.testing import WebsocketCommunicator
from account.models import User
from rest_framework.authtoken.models import Token
class Tests(SimpleTestCase):
databases = '__all__'
def setUp(self):
self.user = User.objects.create(email='test#test.test', password='a password')
self.token, created = Token.objects.get_or_create(user=self.user)
async def test_connect(self):
communicator = WebsocketCommunicator(application, f"/ws/user/{self.token}/")
connected, subprotocol = await communicator.connect()
self.assertTrue(connected)
await communicator.disconnect()
here are the information of SimpleTestCase
https://docs.djangoproject.com/en/4.0/topics/testing/tools/
I faced a similar issue and the solution is usually to mimic your production router for the tests too, i.e whatever middleware or additional component used in production should also be added when imstantiating your Communicator. for example in my asgi.py I have:
application = ProtocolTypeRouter(
{
"http": get_asgi_application(),
"websocket": AllowedHostsOriginValidator(
jwt_auth_middleware_stack(URLRouter(chat.routing.websocket_urlpatterns)),
),
}
)
My communicator is instantiated as follows:
communicator = WebsocketCommunicator(jwt_auth_middleware_stack(URLRouter(websocket_urlpatterns)),
f"/ws/chat/{chat.id}/?token={token}")
And my url is:
websocket_urlpatterns = [
path("ws/chat/<str:chat_id>/", consumers.AsyncChatConsumer.as_asgi())
]

chat app work perfectly in local but stopped working when deployed to heroku - django

I did a chatting part in my web app with django it works perfectly in local but after I deployed it to heroku , it doesn't work:
this is my consumers.py class:
from channels.generic.websocket import AsyncWebsocketConsumer
from django.contrib.auth.models import User
from django.db.models import Q
from asgiref.sync import sync_to_async
import json
from chat.models import Thread, Message
from users.serializers import UserSerializer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
friend = None
me = self.scope['user'] # logged in user
friend_name = self.scope['url_route']['kwargs']['friend'] # get the username of that user, whoom you want to chat
friend_instance = await sync_to_async(User.objects.get, thread_sensitive=True)(username=friend_name) # get user object of friend
# create a new Thread object if thread of specific chat does not exists, otherwise return the thread
thread = None
try:
thread = await sync_to_async(Thread.objects.get, thread_sensitive=True)((Q(user1=me) & Q(user2=friend_instance)) | (Q(user1=friend_instance) & Q(user2=me)))
except:
thread = await sync_to_async(Thread.objects.create, thread_sensitive=True)(user1=me, user2=friend_instance)
self.room_name = thread.room_name # room name
await self.channel_layer.group_add(
self.room_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
'''
disconnect the websocket connection.
'''
await self.channel_layer.group_discard (
self.room_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
from_user = text_data_json['user']
to_user = text_data_json['friend']
from_user_instanse = await sync_to_async(User.objects.get, thread_sensitive=True)(username=from_user['username']) # get user object of friend
to_user_instanse = await sync_to_async(User.objects.get, thread_sensitive=True)(username=to_user['username']) # get user object of friend
thread_obj = await sync_to_async(Thread.objects.get, thread_sensitive=True)((Q(user1=from_user_instanse) & Q(user2=to_user_instanse)) | (Q(user1=to_user_instanse) & Q(user2=from_user_instanse)))
message_instane = await sync_to_async(Message.objects.create, thread_sensitive=True)(messag_body=message, from_user=from_user_instanse, to_user=to_user_instanse, thread=thread_obj)
await self.channel_layer.group_send(
self.room_name,
{
'type': 'chatroom_messages',
'message': message_instane.messag_body,
'user': message_instane.from_user
}
)
async def chatroom_messages(self, event):
message = event['message']
user = event['user']
user_serialized_data = UserSerializer(user)
await self.send(text_data=json.dumps({
'message': message,
'user': user_serialized_data.data
}))
in the template this is the connection request part with js:
chatSocket.send(JSON.stringify({ //the error shows in this part that WebSocket is already in CLOSING or CLOSED state
'message': msg,
'user': me,
'friend': friendName
}));
....
/* connection request */
const chatSocket = new WebSocket(
'wss://'
+ window.location.host
+ '/ws/chat/'
+ friendName['username']
+ '/'
);
in my chat app this I have routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<friend>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
in my project I have also routing.py
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import chat.routing
application = ProtocolTypeRouter ({
'websocket': AuthMiddlewareStack(
URLRouter (
chat.routing.websocket_urlpatterns
)
)
})
and this is actually my asgi.py :
import os
import django #added
#from django.core.asgi import get_asgi_application #removed
from channels.routing import get_default_application # added
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup() #added
application = get_default_application() #added
#application = get_asgi_application() #removed
in my procfile :
release: python manage.py migrate
web: daphne myproject.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channels --settings=myproject.settings -v2
in my settings.py
ASGI_APPLICATION = "myproject.routing.application"
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')],
},
},
}
it works perfectly in local but not anymore working after deployement, am I messing something

WebSocket is already in CLOSING or CLOSED state- heroku django

I did a chatting part in my web app with django it works perfectly in local but after I deployed it to heroku , it doesn't work:
this is my consumers.py class:
from channels.generic.websocket import AsyncWebsocketConsumer
from django.contrib.auth.models import User
from django.db.models import Q
from asgiref.sync import sync_to_async
import json
from chat.models import Thread, Message
from users.serializers import UserSerializer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
friend = None
me = self.scope['user'] # logged in user
friend_name = self.scope['url_route']['kwargs']['friend'] # get the username of that user, whoom you want to chat
friend_instance = await sync_to_async(User.objects.get, thread_sensitive=True)(username=friend_name) # get user object of friend
# create a new Thread object if thread of specific chat does not exists, otherwise return the thread
thread = None
try:
thread = await sync_to_async(Thread.objects.get, thread_sensitive=True)((Q(user1=me) & Q(user2=friend_instance)) | (Q(user1=friend_instance) & Q(user2=me)))
except:
thread = await sync_to_async(Thread.objects.create, thread_sensitive=True)(user1=me, user2=friend_instance)
self.room_name = thread.room_name # room name
await self.channel_layer.group_add(
self.room_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
'''
disconnect the websocket connection.
'''
await self.channel_layer.group_discard (
self.room_name,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
from_user = text_data_json['user']
to_user = text_data_json['friend']
from_user_instanse = await sync_to_async(User.objects.get, thread_sensitive=True)(username=from_user['username']) # get user object of friend
to_user_instanse = await sync_to_async(User.objects.get, thread_sensitive=True)(username=to_user['username']) # get user object of friend
thread_obj = await sync_to_async(Thread.objects.get, thread_sensitive=True)((Q(user1=from_user_instanse) & Q(user2=to_user_instanse)) | (Q(user1=to_user_instanse) & Q(user2=from_user_instanse)))
message_instane = await sync_to_async(Message.objects.create, thread_sensitive=True)(messag_body=message, from_user=from_user_instanse, to_user=to_user_instanse, thread=thread_obj)
await self.channel_layer.group_send(
self.room_name,
{
'type': 'chatroom_messages',
'message': message_instane.messag_body,
'user': message_instane.from_user
}
)
async def chatroom_messages(self, event):
message = event['message']
user = event['user']
user_serialized_data = UserSerializer(user)
await self.send(text_data=json.dumps({
'message': message,
'user': user_serialized_data.data
}))
in the template this is the connection request part with js:
chatSocket.send(JSON.stringify({ //the error shows in this part that WebSocket is already in CLOSING or CLOSED state
'message': msg,
'user': me,
'friend': friendName
}));
....
/* connection request */
const chatSocket = new WebSocket(
'wss://'
+ window.location.host
+ '/ws/chat/'
+ friendName['username']
+ '/'
);
in my chat app this I have routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<friend>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
in my project I have also routing.py
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import chat.routing
application = ProtocolTypeRouter ({
'websocket': AuthMiddlewareStack(
URLRouter (
chat.routing.websocket_urlpatterns
)
)
})
and this is actually my asgi.py :
import os
import django #added
#from django.core.asgi import get_asgi_application #removed
from channels.routing import get_default_application # added
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup() #added
application = get_default_application() #added
#application = get_asgi_application() #removed
in my procfile :
release: python manage.py migrate
web: daphne myproject.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channels --settings=myproject.settings -v2
in my settings.py
ASGI_APPLICATION = "myproject.routing.application"
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')],
},
},
}
it works perfectly in local but not anymore working after deployement, am I messing something
this is heroku logs :
......
2021-12-29T18:15:42.187913+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packa
ges/aioredis/connection.py", line 111, in create_connection
2021-12-29T18:15:42.187913+00:00 app[web.1]: reader, writer = await asyncio.wait_for(open_conne
ction(
2021-12-29T18:15:42.187916+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/ta
sks.py", line 442, in wait_for
2021-12-29T18:15:42.187916+00:00 app[web.1]: return await fut
2021-12-29T18:15:42.187916+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packa
ges/aioredis/stream.py", line 23, in open_connection
2021-12-29T18:15:42.187916+00:00 app[web.1]: transport, _ = await get_event_loop().create_conne
ction(
2021-12-29T18:15:42.187917+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/ba
se_events.py", line 1056, in create_connection
2021-12-29T18:15:42.187917+00:00 app[web.1]: raise exceptions[0]
2021-12-29T18:15:42.187917+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/ba
se_events.py", line 1041, in create_connection
2021-12-29T18:15:42.187917+00:00 app[web.1]: sock = await self._connect_sock(
2021-12-29T18:15:42.187917+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/ba
se_events.py", line 955, in _connect_sock
2021-12-29T18:15:42.187918+00:00 app[web.1]: await self.sock_connect(sock, address)
2021-12-29T18:15:42.187918+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/se
lector_events.py", line 502, in sock_connect
2021-12-29T18:15:42.187918+00:00 app[web.1]: return await fut
2021-12-29T18:15:42.187918+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/asyncio/se
lector_events.py", line 537, in _sock_connect_cb
2021-12-29T18:15:42.187919+00:00 app[web.1]: raise OSError(err, f'Connect call failed {address}
')
2021-12-29T18:15:42.187919+00:00 app[web.1]: ConnectionRefusedError: [Errno 111] Connect call f
ailed ('127.0.0.1', 6379)
2021-12-29T18:15:42.188173+00:00 app[web.1]: 2021-12-29 18:15:42,188 INFO failing WebSocket
opening handshake ('Internal server error')
2021-12-29T18:15:42.188439+00:00 app[web.1]: 2021-12-29 18:15:42,188 WARNING dropping connecti
on to peer tcp4:10.1.93.62:26296 with abort=False: Internal server error
2021-12-29T18:15:42.189132+00:00 app[web.1]: 2021-12-29 18:15:42,189 DEBUG WebSocket closed
for ['10.1.93.62', 26296]
2021-12-29T18:15:42.189195+00:00 app[web.1]: 10.1.93.62:26296 - - [29/Dec/2021:18:15:42] "WSDIS
CONNECT /ws/chat/person/" - -

Django concurrency: can't create data for testing in async function?

Goal Test async function with test database
Problem I have async functions for Django channels and when I create data in setUp the data are not reflected in the project!!!
My tests: note: these tests inside a APITestCase class
class WebsocketTests(APITestCase):
async def test_connect(self):
userx = await sync_to_async(User.objects.create)(username='newusername',email='emm#gg.com')
users_number = await sync_to_async(User.objects.count)()
print(users_number) #<=== this returns 1 just fine
communicator = WebsocketCommunicator(application, 'alerts/')
connected, subprotocol = await communicator.connect()
assert connected
await communicator.disconnect()
#database_sync_to_async
def get_user(querys):
print(User.objects.count()) #<======= this returns 0 while it should return 1
try:
token = parse_qs(querys.decode("utf8"))['token'][0]
token_data = UntypedToken(token)
user_id = token_data["user_id"]
except:
return 'token is invalid'
try:
return User.objects.get(id=user_id)
except User.DoesNotExist:
return 'AnonymousUser'
class QueryAuthMiddleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
scope['user'] = await get_user(scope["query_string"])
return await self.app(scope, receive, send)
application = ProtocolTypeRouter({
"http": django_asgi_app,
"websocket": QueryAuthMiddleware(
URLRouter(
websocket_urlpatterns
)
),
})
#settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'OPTIONS': {
'timeout': 20, # in seconds
# see also
# https://docs.python.org/3.7/library/sqlite3.html#sqlite3.connect
},
'TEST': {
'NAME': os.path.join(BASE_DIR, "db_test.sqlite3"),
},
}
}
I tride
replace APITestCase with django TestCase
switch to postgres
use from asgiref.sync import sync_to_async