tum 2 anni fa
commit
687bd14b20

+ 159 - 0
.gitignore

@@ -0,0 +1,159 @@
1
+# Created by https://www.toptal.com/developers/gitignore/api/django
2
+# Edit at https://www.toptal.com/developers/gitignore?templates=django
3
+
4
+### Django ###
5
+*.log
6
+*.pot
7
+*.pyc
8
+__pycache__/
9
+local_settings.py
10
+db.sqlite3
11
+db.sqlite3-journal
12
+#media
13
+
14
+# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/
15
+# in your Git repository. Update and uncomment the following line accordingly.
16
+# <django-project-name>/staticfiles/
17
+
18
+### Django.Python Stack ###
19
+# Byte-compiled / optimized / DLL files
20
+*.py[cod]
21
+*$py.class
22
+
23
+# C extensions
24
+*.so
25
+
26
+# Distribution / packaging
27
+.Python
28
+build/
29
+develop-eggs/
30
+#dist/
31
+downloads/
32
+eggs/
33
+.eggs/
34
+lib/
35
+lib64/
36
+parts/
37
+sdist/
38
+var/
39
+wheels/
40
+share/python-wheels/
41
+*.egg-info/
42
+.installed.cfg
43
+*.egg
44
+MANIFEST
45
+
46
+# PyInstaller
47
+#  Usually these files are written by a python script from a template
48
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
49
+*.manifest
50
+*.spec
51
+
52
+# Installer logs
53
+pip-log.txt
54
+pip-delete-this-directory.txt
55
+
56
+# Unit test / coverage reports
57
+htmlcov/
58
+.tox/
59
+.nox/
60
+.coverage
61
+.coverage.*
62
+.cache
63
+nosetests.xml
64
+coverage.xml
65
+*.cover
66
+*.py,cover
67
+.hypothesis/
68
+.pytest_cache/
69
+cover/
70
+
71
+# Translations
72
+*.mo
73
+
74
+# Django stuff:
75
+
76
+# Flask stuff:
77
+instance/
78
+.webassets-cache
79
+
80
+# Scrapy stuff:
81
+.scrapy
82
+
83
+# Sphinx documentation
84
+docs/_build/
85
+
86
+# PyBuilder
87
+.pybuilder/
88
+target/
89
+
90
+# Jupyter Notebook
91
+.ipynb_checkpoints
92
+
93
+# IPython
94
+profile_default/
95
+ipython_config.py
96
+
97
+# pyenv
98
+#   For a library or package, you might want to ignore these files since the code is
99
+#   intended to run in multiple environments; otherwise, check them in:
100
+# .python-version
101
+
102
+# pipenv
103
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
104
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
105
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
106
+#   install all needed dependencies.
107
+#Pipfile.lock
108
+
109
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
110
+__pypackages__/
111
+
112
+# Celery stuff
113
+celerybeat-schedule
114
+celerybeat.pid
115
+
116
+# SageMath parsed files
117
+*.sage.py
118
+
119
+# Environments
120
+.env
121
+.venv
122
+env/
123
+venv/
124
+ENV/
125
+env.bak/
126
+venv.bak/
127
+
128
+# Spyder project settings
129
+.spyderproject
130
+.spyproject
131
+
132
+# Rope project settings
133
+.ropeproject
134
+
135
+# mkdocs documentation
136
+/site
137
+
138
+# mypy
139
+.mypy_cache/
140
+.dmypy.json
141
+dmypy.json
142
+
143
+# Pyre type checker
144
+.pyre/
145
+
146
+# pytype static type analyzer
147
+.pytype/
148
+
149
+# Cython debug symbols
150
+cython_debug/
151
+
152
+# End of https://www.toptal.com/developers/gitignore/api/django
153
+data/
154
+media/
155
+mongodb/
156
+app/media/
157
+CACHE/
158
+media.zip
159
+data.zip

+ 23 - 0
Dockerfile

@@ -0,0 +1,23 @@
1
+# syntax=docker/dockerfile:1
2
+FROM python:3
3
+ENV PYTHONDONTWRITEBYTECODE=1
4
+ENV PYTHONUNBUFFERED=1
5
+RUN apt-get update && apt-get install apt-transport-https
6
+RUN apt-get install -y libjpeg62 libjpeg62-turbo-dev  zlib1g-dev gettext entr
7
+RUN \
8
+        echo "Installing Node and Yarn" && \
9
+        echo "deb https://deb.nodesource.com/node_8.x jessie main" > /etc/apt/sources.list.d/nodesource.list && \
10
+        wget -qO- https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \
11
+        echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list && \
12
+        wget -qO- https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
13
+        apt-get update && \
14
+        apt-get install -yqq nodejs yarn npm && \
15
+        npm install -g nodemon && \ 
16
+        rm -rf /var/lib/apt/lists/* 
17
+WORKDIR /code
18
+COPY requirements.txt /code/
19
+RUN --mount=type=cache,target=/root/.cache pip install -r requirements.txt
20
+COPY app /code/
21
+RUN chmod a+x server-entrypoint.sh
22
+RUN chmod a+x worker-entrypoint.sh
23
+

+ 96 - 0
app/authentication.py

@@ -0,0 +1,96 @@
1
+#!/usr/bin/env python
2
+
3
+import asyncio
4
+import json
5
+
6
+#import aioredis
7
+from redis import asyncio as aioredis
8
+import django
9
+import websockets
10
+from pprint import pprint
11
+
12
+django.setup()
13
+
14
+from django.contrib.contenttypes.models import ContentType
15
+from sesame.utils import get_user
16
+
17
+
18
+CONNECTIONS = {}
19
+
20
+
21
+def get_content_types(user):
22
+    """Return the set of IDs of content types visible by user."""
23
+    # This does only three database queries because Django caches
24
+    # all permissions on the first call to user.has_perm(...).
25
+    return {
26
+        ct.id
27
+        for ct in ContentType.objects.all()
28
+        if user.has_perm(f"{ct.app_label}.view_{ct.model}")
29
+        or user.has_perm(f"{ct.app_label}.change_{ct.model}")
30
+    }
31
+
32
+
33
+async def handler(websocket):
34
+    """Authenticate user and register connection in CONNECTIONS."""
35
+    sesame = await websocket.recv()
36
+    user = await asyncio.to_thread(get_user, sesame)
37
+    if user is None:
38
+        await websocket.close(1011, "authentication failed")
39
+        return
40
+
41
+    ct_ids = await asyncio.to_thread(get_content_types, user)
42
+    CONNECTIONS[websocket] = {"content_type_ids": ct_ids}
43
+    pprint("Connections")
44
+    pprint(CONNECTIONS)
45
+    try:
46
+        await websocket.wait_closed()
47
+    finally:
48
+        del CONNECTIONS[websocket]
49
+
50
+
51
+async def process_events():
52
+    """Listen to events in Redis and process them."""
53
+    redis = aioredis.from_url("redis://redis:6379/1")
54
+    pubsub = redis.pubsub()
55
+    await pubsub.subscribe("events", "flash_sale")
56
+
57
+
58
+    async for message in pubsub.listen():
59
+        pprint("process events")
60
+        pprint(message)
61
+        if message["type"] != "message":
62
+            continue
63
+        payload = message["data"].decode()
64
+        # Broadcast event to all users who have permissions to see it.
65
+        event = json.loads(payload)
66
+        #pprint("current channel")
67
+        #pprint(str(message['channel']))
68
+        ch = message["channel"].decode()
69
+        if ch == "events":
70
+            pprint("event send ..")
71
+            recipients = (
72
+                websocket
73
+                for websocket, connection in CONNECTIONS.items()
74
+                if event["content_type_id"] in connection["content_type_ids"]
75
+            )
76
+            websockets.broadcast(recipients, payload)
77
+
78
+        if ch == "flash_sale":
79
+            pprint("flash sale send >> ..")
80
+            recipients = (
81
+                websocket
82
+                for websocket, connection in CONNECTIONS.items()
83
+            )
84
+            pprint("test msg >> ..")
85
+            websockets.broadcast(recipients, payload)
86
+
87
+
88
+
89
+async def main():
90
+    async with websockets.serve(handler, "0.0.0.0", 8888):
91
+        await process_events()  # runs forever
92
+        #process_flashsale()
93
+
94
+
95
+if __name__ == "__main__":
96
+    asyncio.run(main(), debug=True)

+ 22 - 0
app/manage.py

@@ -0,0 +1,22 @@
1
+#!/usr/bin/env python
2
+"""Django's command-line utility for administrative tasks."""
3
+import os
4
+import sys
5
+
6
+
7
+def main():
8
+    """Run administrative tasks."""
9
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tmt_learning.settings')
10
+    try:
11
+        from django.core.management import execute_from_command_line
12
+    except ImportError as exc:
13
+        raise ImportError(
14
+            "Couldn't import Django. Are you sure it's installed and "
15
+            "available on your PYTHONPATH environment variable? Did you "
16
+            "forget to activate a virtual environment?"
17
+        ) from exc
18
+    execute_from_command_line(sys.argv)
19
+
20
+
21
+if __name__ == '__main__':
22
+    main()

+ 2 - 0
app/server-entrypoint.sh

@@ -0,0 +1,2 @@
1
+#!/bin/bash
2
+python -X dev manage.py  runserver 0.0.0.0:8024

+ 0 - 0
app/tmt_learning/__init__.py


+ 16 - 0
app/tmt_learning/asgi.py

@@ -0,0 +1,16 @@
1
+"""
2
+ASGI config for tmt_learning project.
3
+
4
+It exposes the ASGI callable as a module-level variable named ``application``.
5
+
6
+For more information on this file, see
7
+https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
8
+"""
9
+
10
+import os
11
+
12
+from django.core.asgi import get_asgi_application
13
+
14
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tmt_learning.settings')
15
+
16
+application = get_asgi_application()

+ 123 - 0
app/tmt_learning/settings.py

@@ -0,0 +1,123 @@
1
+"""
2
+Django settings for tmt_learning project.
3
+
4
+Generated by 'django-admin startproject' using Django 4.1.5.
5
+
6
+For more information on this file, see
7
+https://docs.djangoproject.com/en/4.1/topics/settings/
8
+
9
+For the full list of settings and their values, see
10
+https://docs.djangoproject.com/en/4.1/ref/settings/
11
+"""
12
+
13
+from pathlib import Path
14
+
15
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
16
+BASE_DIR = Path(__file__).resolve().parent.parent
17
+
18
+
19
+# Quick-start development settings - unsuitable for production
20
+# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
21
+
22
+# SECURITY WARNING: keep the secret key used in production secret!
23
+SECRET_KEY = 'django-insecure-=itdty(p8!f1rbdmhh5+*7n%98ks8oh)l0x6%5!j7_c_&7o+gt'
24
+
25
+# SECURITY WARNING: don't run with debug turned on in production!
26
+DEBUG = True
27
+
28
+ALLOWED_HOSTS = []
29
+
30
+
31
+# Application definition
32
+
33
+INSTALLED_APPS = [
34
+    'django.contrib.admin',
35
+    'django.contrib.auth',
36
+    'django.contrib.contenttypes',
37
+    'django.contrib.sessions',
38
+    'django.contrib.messages',
39
+    'django.contrib.staticfiles',
40
+]
41
+
42
+MIDDLEWARE = [
43
+    'django.middleware.security.SecurityMiddleware',
44
+    'django.contrib.sessions.middleware.SessionMiddleware',
45
+    'django.middleware.common.CommonMiddleware',
46
+    'django.middleware.csrf.CsrfViewMiddleware',
47
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
48
+    'django.contrib.messages.middleware.MessageMiddleware',
49
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
50
+]
51
+
52
+ROOT_URLCONF = 'tmt_learning.urls'
53
+
54
+TEMPLATES = [
55
+    {
56
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
57
+        'DIRS': [],
58
+        'APP_DIRS': True,
59
+        'OPTIONS': {
60
+            'context_processors': [
61
+                'django.template.context_processors.debug',
62
+                'django.template.context_processors.request',
63
+                'django.contrib.auth.context_processors.auth',
64
+                'django.contrib.messages.context_processors.messages',
65
+            ],
66
+        },
67
+    },
68
+]
69
+
70
+WSGI_APPLICATION = 'tmt_learning.wsgi.application'
71
+
72
+
73
+# Database
74
+# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
75
+
76
+DATABASES = {
77
+    'default': {
78
+        'ENGINE': 'django.db.backends.sqlite3',
79
+        'NAME': BASE_DIR / 'db.sqlite3',
80
+    }
81
+}
82
+
83
+
84
+# Password validation
85
+# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators
86
+
87
+AUTH_PASSWORD_VALIDATORS = [
88
+    {
89
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
90
+    },
91
+    {
92
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
93
+    },
94
+    {
95
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
96
+    },
97
+    {
98
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
99
+    },
100
+]
101
+
102
+
103
+# Internationalization
104
+# https://docs.djangoproject.com/en/4.1/topics/i18n/
105
+
106
+LANGUAGE_CODE = 'en-us'
107
+
108
+TIME_ZONE = 'UTC'
109
+
110
+USE_I18N = True
111
+
112
+USE_TZ = True
113
+
114
+
115
+# Static files (CSS, JavaScript, Images)
116
+# https://docs.djangoproject.com/en/4.1/howto/static-files/
117
+
118
+STATIC_URL = 'static/'
119
+
120
+# Default primary key field type
121
+# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
122
+
123
+DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

+ 21 - 0
app/tmt_learning/urls.py

@@ -0,0 +1,21 @@
1
+"""tmt_learning URL Configuration
2
+
3
+The `urlpatterns` list routes URLs to views. For more information please see:
4
+    https://docs.djangoproject.com/en/4.1/topics/http/urls/
5
+Examples:
6
+Function views
7
+    1. Add an import:  from my_app import views
8
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
9
+Class-based views
10
+    1. Add an import:  from other_app.views import Home
11
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
12
+Including another URLconf
13
+    1. Import the include() function: from django.urls import include, path
14
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
15
+"""
16
+from django.contrib import admin
17
+from django.urls import path
18
+
19
+urlpatterns = [
20
+    path('admin/', admin.site.urls),
21
+]

+ 16 - 0
app/tmt_learning/wsgi.py

@@ -0,0 +1,16 @@
1
+"""
2
+WSGI config for tmt_learning project.
3
+
4
+It exposes the WSGI callable as a module-level variable named ``application``.
5
+
6
+For more information on this file, see
7
+https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/
8
+"""
9
+
10
+import os
11
+
12
+from django.core.wsgi import get_wsgi_application
13
+
14
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tmt_learning.settings')
15
+
16
+application = get_wsgi_application()

+ 3 - 0
app/worker-entrypoint.sh

@@ -0,0 +1,3 @@
1
+#!/bin/bash
2
+celery -A tmt_learning worker -B  -l info
3
+#celery -A kacee beat --detach -l info

+ 54 - 0
docker-compose.yml

@@ -0,0 +1,54 @@
1
+services:
2
+  redis:
3
+    restart: unless-stopped
4
+    image: redis:7.0.5-alpine
5
+    expose:
6
+      - 6379
7
+    ports:
8
+      - "127.0.0.1:6379:6379"
9
+  db:
10
+    image: postgres
11
+    volumes:
12
+      - ./data/db:/var/lib/postgresql/data
13
+    ports:
14
+      - "5432:5432"
15
+    environment:
16
+      - POSTGRES_DB=postgres
17
+      - POSTGRES_USER=postgres
18
+      - POSTGRES_PASSWORD=postgres
19
+  web:
20
+    build: .
21
+    command: python -X dev manage.py  runserver 0.0.0.0:8000
22
+    #entrypoint: ./server-entrypoint.sh
23
+    volumes:
24
+      - ./app:/code
25
+      - ./media:/code/media
26
+    ports:
27
+      - "127.0.0.1:8020:8000"
28
+    environment:
29
+      - POSTGRES_NAME=postgres
30
+      - POSTGRES_USER=postgres
31
+      - POSTGRES_PASSWORD=postgres
32
+      - PYTHONMALLOC=debug
33
+      - DJANGO_SETTINGS_MODULE=tmt_learning.settings
34
+    depends_on:
35
+      - db
36
+      - redis
37
+      #- rabbitmq
38
+  websocket:
39
+    build: .
40
+    #image: web
41
+    command: nodemon authentication.py
42
+    volumes:
43
+      - ./app:/code
44
+    ports:
45
+      - "127.0.0.1:8888:8888"
46
+    environment:
47
+      - POSTGRES_NAME=postgres
48
+      - POSTGRES_USER=postgres
49
+      - POSTGRES_PASSWORD=postgres
50
+      - PYTHONMALLOC=debug
51
+      - DJANGO_SETTINGS_MODULE=tmt_learning.settings
52
+    depends_on:
53
+      - db
54
+      - redis

+ 80 - 0
docker-compose.yml.old

@@ -0,0 +1,80 @@
1
+services:
2
+  redis:
3
+    restart: unless-stopped
4
+    image: redis:7.0.5-alpine
5
+    expose:
6
+      - 6379
7
+    ports:
8
+      - "127.0.0.1:6379:6379"
9
+  db:
10
+    image: postgres
11
+    volumes:
12
+      - ./data/db:/var/lib/postgresql/data
13
+    ports:
14
+      - "5432:5432"
15
+    environment:
16
+      - POSTGRES_DB=postgres
17
+      - POSTGRES_USER=postgres
18
+      - POSTGRES_PASSWORD=postgres
19
+  web:
20
+    build: .
21
+    command: python -X dev manage.py  runserver 0.0.0.0:8000
22
+    #entrypoint: ./server-entrypoint.sh
23
+    volumes:
24
+      - ./app:/code
25
+      - ./media:/code/media
26
+    ports:
27
+      - "127.0.0.1:8020:8000"
28
+    environment:
29
+      - POSTGRES_NAME=postgres
30
+      - POSTGRES_USER=postgres
31
+      - POSTGRES_PASSWORD=postgres
32
+      - PYTHONMALLOC=debug
33
+      - DJANGO_SETTINGS_MODULE=tmt_learning.settings
34
+    depends_on:
35
+      - db
36
+      - redis
37
+      - rabbitmq
38
+  worker:
39
+    restart: unless-stopped
40
+    build: .
41
+    #command: python -X dev manage.py  runserver 0.0.0.0:8000
42
+    entrypoint: ./worker-entrypoint.sh
43
+    volumes:
44
+      - ./app:/code
45
+    environment:
46
+      - POSTGRES_NAME=postgres
47
+      - POSTGRES_USER=postgres
48
+      - POSTGRES_PASSWORD=postgres
49
+      - PYTHONMALLOC=debug
50
+      - DJANGO_SETTINGS_MODULE=tmt_learning.settings
51
+    depends_on:
52
+      - web
53
+  websocket:
54
+    build: .
55
+    #image: web
56
+    command: nodemon authentication.py
57
+    volumes:
58
+      - ./app:/code
59
+    ports:
60
+      - "127.0.0.1:8888:8888"
61
+    environment:
62
+      - POSTGRES_NAME=postgres
63
+      - POSTGRES_USER=postgres
64
+      - POSTGRES_PASSWORD=postgres
65
+      - PYTHONMALLOC=debug
66
+      - DJANGO_SETTINGS_MODULE=tmt_learning.settings
67
+    depends_on:
68
+      - db
69
+      - redis
70
+  rabbitmq:
71
+    image: rabbitmq:3-management-alpine
72
+    #container_name: 'rabbitmq'
73
+    ports:
74
+        - 5672:5672
75
+        - 15672:15672
76
+    volumes:
77
+        - ./rabbitmq/data/:/var/lib/rabbitmq/
78
+        - ./rabbitmq/log/:/var/log/rabbitmq
79
+    #networks:
80
+        #- rabbitmq_go_net

+ 72 - 0
requirements.txt

@@ -0,0 +1,72 @@
1
+Django==4.1.5
2
+psycopg2>=2.8
3
+pycountry
4
+django-extensions
5
+ipython
6
+djangorestframework
7
+markdown
8
+django-filter
9
+django-extra-views
10
+django-crispy-forms
11
+django-environ
12
+django-smart-selects
13
+Pillow
14
+django-yarnpkg
15
+django-cors-headers
16
+django-storages
17
+django-debug-toolbar
18
+django-redis
19
+django-mptt
20
+django-taggit
21
+sorl-thumbnail
22
+redis
23
+django-address
24
+django-international
25
+django-embed-video
26
+django-better-admin-arrayfield
27
+crispy-bootstrap5
28
+django-browser-reload
29
+django-widget-tweaks
30
+django-autocomplete-light
31
+django-bootstrap-breadcrumbs
32
+django-tables2
33
+martor
34
+django-queryset-csv
35
+django-ajax-selects
36
+django-multiupload
37
+django-formset
38
+django-multiselectfield
39
+django_ace
40
+django-autoslug
41
+celery==5.2.7
42
+django-phonenumber-field[phonenumbers]
43
+django-credit-cards
44
+django-payments[stripe]
45
+django-google-maps
46
+django-rosetta
47
+django-parler
48
+forex-python
49
+django-model-import
50
+django-import-export
51
+tablib[all]
52
+pandas
53
+openpyxl
54
+xlsx2csv
55
+wget
56
+markdownify
57
+django-star-ratings
58
+requests
59
+py3dbp
60
+ksherpay
61
+django-sesame
62
+websockets
63
+aioredis
64
+matplotlib
65
+django_compressor
66
+django-libsass
67
+#django-utils-six
68
+django_otp
69
+pyotp
70
+django-url-filter
71
+sorl-thumbnail-serializer-field
72
+django-debug-permissions