Allow unsafe async and make more things async
This commit is contained in:
parent
5bf65e3c90
commit
22df27178b
|
@ -0,0 +1,160 @@
|
||||||
|
# ---> Python
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
# lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
stack.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
env-glibc/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
.bash_history
|
||||||
|
.vscode/
|
||||||
|
core/static/admin
|
||||||
|
core/static/debug_toolbar
|
|
@ -0,0 +1,31 @@
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 22.6.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
exclude: ^core/migrations
|
||||||
|
- repo: https://github.com/PyCQA/isort
|
||||||
|
rev: 5.10.1
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
args: ["--profile", "black"]
|
||||||
|
- repo: https://github.com/PyCQA/flake8
|
||||||
|
rev: 4.0.1
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
args: [--max-line-length=88]
|
||||||
|
exclude: ^core/migrations
|
||||||
|
- repo: https://github.com/rtts/djhtml
|
||||||
|
rev: 'v1.5.2' # replace with the latest tag on GitHub
|
||||||
|
hooks:
|
||||||
|
- id: djhtml
|
||||||
|
args: [-t 2]
|
||||||
|
- id: djcss
|
||||||
|
exclude : ^core/static/css # slow
|
||||||
|
- id: djjs
|
||||||
|
exclude: ^core/static/js # slow
|
||||||
|
# - repo: https://github.com/thibaudcolas/curlylint
|
||||||
|
# rev: v0.13.1
|
||||||
|
# hooks:
|
||||||
|
# - id: curlylint
|
||||||
|
# files: \.(html|sls)$
|
|
@ -1,6 +1,9 @@
|
||||||
|
import os
|
||||||
|
|
||||||
import stripe
|
import stripe
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
|
||||||
# from redis import StrictRedis
|
# from redis import StrictRedis
|
||||||
|
|
||||||
# r = StrictRedis(unix_socket_path="/var/run/redis/redis.sock", db=0)
|
# r = StrictRedis(unix_socket_path="/var/run/redis/redis.sock", db=0)
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
|
from asgiref.sync import sync_to_async
|
||||||
|
|
||||||
from core.models import Plan
|
from core.models import Plan
|
||||||
|
|
||||||
|
|
||||||
def assemble_plan_map(product_id_filter=None):
|
async def assemble_plan_map(product_id_filter=None):
|
||||||
"""
|
"""
|
||||||
Get all the plans from the database and create an object Stripe wants.
|
Get all the plans from the database and create an object Stripe wants.
|
||||||
"""
|
"""
|
||||||
line_items = []
|
line_items = []
|
||||||
for plan in Plan.objects.all():
|
for plan in await sync_to_async(list)(Plan.objects.all()):
|
||||||
if product_id_filter:
|
if product_id_filter:
|
||||||
if plan.product_id != product_id_filter:
|
if plan.product_id != product_id_filter:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -31,16 +31,6 @@
|
||||||
Subscription management
|
Subscription management
|
||||||
</a>
|
</a>
|
||||||
</article>
|
</article>
|
||||||
<div class="box">
|
{% include "partials/product-list.html" %}
|
||||||
<h1 class="subtitle">
|
|
||||||
This product is currently free. You may cancel any plans above.
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div class="box">
|
|
||||||
<h1 class="subtitle">
|
|
||||||
You cannot pay for access to the raw data. It is hashed to preserve privacy.
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
{# {% include "partials/product-list.html" %} #}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
from asyncio import sleep
|
|
||||||
|
|
||||||
import stripe
|
import stripe
|
||||||
|
from asgiref.sync import sync_to_async
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
|
@ -23,34 +23,37 @@ class Home(View):
|
||||||
template_name = "index.html"
|
template_name = "index.html"
|
||||||
|
|
||||||
async def get(self, request):
|
async def get(self, request):
|
||||||
await sleep(1)
|
|
||||||
return render(request, self.template_name)
|
return render(request, self.template_name)
|
||||||
|
|
||||||
|
|
||||||
class Billing(LoginRequiredMixin, View):
|
class Billing(LoginRequiredMixin, View):
|
||||||
template_name = "billing.html"
|
template_name = "billing.html"
|
||||||
|
|
||||||
def get(self, request):
|
async def get(self, request):
|
||||||
context = {"plans": Plan.objects.all(), "user_plans": request.user.plans.all()}
|
plans = await sync_to_async(list)(Plan.objects.all())
|
||||||
|
user_plans = await sync_to_async(list)(request.user.plans.all())
|
||||||
|
context = {"plans": plans, "user_plans": user_plans}
|
||||||
return render(request, self.template_name, context)
|
return render(request, self.template_name, context)
|
||||||
|
|
||||||
|
|
||||||
class Order(LoginRequiredMixin, View):
|
class Order(LoginRequiredMixin, View):
|
||||||
def get(self, request, plan_name):
|
async def get(self, request, plan_name):
|
||||||
plan = Plan.objects.get(name=plan_name)
|
plan = Plan.objects.get(name=plan_name)
|
||||||
try:
|
try:
|
||||||
cast = {
|
cast = {
|
||||||
"payment_method_types": settings.ALLOWED_PAYMENT_METHODS,
|
"payment_method_types": settings.ALLOWED_PAYMENT_METHODS,
|
||||||
"mode": "subscription",
|
"mode": "subscription",
|
||||||
"customer": request.user.stripe_id,
|
"customer": request.user.stripe_id,
|
||||||
"line_items": assemble_plan_map(product_id_filter=plan.product_id),
|
"line_items": await assemble_plan_map(
|
||||||
|
product_id_filter=plan.product_id
|
||||||
|
),
|
||||||
"success_url": request.build_absolute_uri(reverse("success")),
|
"success_url": request.build_absolute_uri(reverse("success")),
|
||||||
"cancel_url": request.build_absolute_uri(reverse("cancel")),
|
"cancel_url": request.build_absolute_uri(reverse("cancel")),
|
||||||
}
|
}
|
||||||
if request.user.is_superuser:
|
if request.user.is_superuser:
|
||||||
cast["discounts"] = [{"coupon": settings.STRIPE_ADMIN_COUPON}]
|
cast["discounts"] = [{"coupon": settings.STRIPE_ADMIN_COUPON}]
|
||||||
session = stripe.checkout.Session.create(**cast)
|
session = stripe.checkout.Session.create(**cast)
|
||||||
Session.objects.create(user=request.user, session=session.id)
|
await Session.objects.acreate(user=request.user, session=session.id)
|
||||||
return redirect(session.url)
|
return redirect(session.url)
|
||||||
# return JsonResponse({'id': session.id})
|
# return JsonResponse({'id': session.id})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -59,7 +62,7 @@ class Order(LoginRequiredMixin, View):
|
||||||
|
|
||||||
|
|
||||||
class Cancel(LoginRequiredMixin, View):
|
class Cancel(LoginRequiredMixin, View):
|
||||||
def get(self, request, plan_name):
|
async def get(self, request, plan_name):
|
||||||
plan = Plan.objects.get(name=plan_name)
|
plan = Plan.objects.get(name=plan_name)
|
||||||
try:
|
try:
|
||||||
subscriptions = stripe.Subscription.list(
|
subscriptions = stripe.Subscription.list(
|
||||||
|
@ -84,7 +87,7 @@ class Signup(CreateView):
|
||||||
|
|
||||||
|
|
||||||
class Portal(LoginRequiredMixin, View):
|
class Portal(LoginRequiredMixin, View):
|
||||||
def get(self, request):
|
async def get(self, request):
|
||||||
session = stripe.billing_portal.Session.create(
|
session = stripe.billing_portal.Session.create(
|
||||||
customer=request.user.stripe_id,
|
customer=request.user.stripe_id,
|
||||||
return_url=request.build_absolute_uri(reverse("billing")),
|
return_url=request.build_absolute_uri(reverse("billing")),
|
||||||
|
|
|
@ -16,6 +16,7 @@ logger = logging.getLogger(__name__)
|
||||||
class Callback(APIView):
|
class Callback(APIView):
|
||||||
parser_classes = [JSONParser]
|
parser_classes = [JSONParser]
|
||||||
|
|
||||||
|
# TODO: make async
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
payload = request.body
|
payload = request.body
|
||||||
|
|
|
@ -7,14 +7,14 @@ from django.views import View
|
||||||
class DemoModal(View):
|
class DemoModal(View):
|
||||||
template_name = "modals/modal.html"
|
template_name = "modals/modal.html"
|
||||||
|
|
||||||
def get(self, request):
|
async def get(self, request):
|
||||||
return render(request, self.template_name)
|
return render(request, self.template_name)
|
||||||
|
|
||||||
|
|
||||||
class DemoWidget(View):
|
class DemoWidget(View):
|
||||||
template_name = "widgets/widget.html"
|
template_name = "widgets/widget.html"
|
||||||
|
|
||||||
def get(self, request):
|
async def get(self, request):
|
||||||
unique = str(uuid.uuid4())[:8]
|
unique = str(uuid.uuid4())[:8]
|
||||||
return render(request, self.template_name, {"unique": unique})
|
return render(request, self.template_name, {"unique": unique})
|
||||||
|
|
||||||
|
@ -22,5 +22,5 @@ class DemoWidget(View):
|
||||||
class DemoWindow(View):
|
class DemoWindow(View):
|
||||||
template_name = "windows/window.html"
|
template_name = "windows/window.html"
|
||||||
|
|
||||||
def get(self, request):
|
async def get(self, request):
|
||||||
return render(request, self.template_name)
|
return render(request, self.template_name)
|
||||||
|
|
Loading…
Reference in New Issue