0.12.36 pays and subscribes
This commit is contained in:
@@ -18,7 +18,7 @@ from django.contrib.contenttypes.fields import GenericRelation
|
|||||||
# add_introspection_rules([], ["^tinymce\.models\.HTMLField"])
|
# add_introspection_rules([], ["^tinymce\.models\.HTMLField"])
|
||||||
|
|
||||||
class BaseModel(models.Model):
|
class BaseModel(models.Model):
|
||||||
name = models.TextField(verbose_name=_('Название'),
|
name = models.TextField(verbose_name=_("Название"),
|
||||||
help_text=_('Название'), null=True, blank=True)
|
help_text=_('Название'), null=True, blank=True)
|
||||||
name_plural = models.TextField(verbose_name=_('Название (множественное число)'),
|
name_plural = models.TextField(verbose_name=_('Название (множественное число)'),
|
||||||
null=True, blank=True)
|
null=True, blank=True)
|
||||||
|
|||||||
@@ -1,20 +1,100 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from requests_pkcs12 import get,post
|
||||||
|
pkcs12_filename = 'dvldigitalprojects.p12'
|
||||||
|
pkcs12_password = 'QNlhRStcY7mB'
|
||||||
|
|
||||||
|
|
||||||
|
def get_domain_url():
|
||||||
|
return 'https://sandboxapi.paymtech.kz/'
|
||||||
|
|
||||||
|
def get_kwargs_for_request():
|
||||||
|
return {
|
||||||
|
'headers': {
|
||||||
|
'content-type': 'application/json',
|
||||||
|
},
|
||||||
|
'auth': ('dvldigitalprojects', 'aPqSRVZhxFjjSqbB'),
|
||||||
|
'pkcs12_filename': pkcs12_filename,
|
||||||
|
'pkcs12_password': pkcs12_password
|
||||||
|
}
|
||||||
|
|
||||||
def ping():
|
def ping():
|
||||||
|
|
||||||
req_str = f'https://developerhub.alfabank.by:8273/partner/1.0.1/public/nationalRates{code_str}{date_str}'
|
url = f'{get_domain_url()}ping'
|
||||||
data = {}
|
data = {}
|
||||||
headers = {
|
|
||||||
'content-type': 'application/json'
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
msg = f'GET {req_str}'
|
msg = f'GET {url}'
|
||||||
print(msg)
|
print(msg)
|
||||||
res = requests.get(req_str, data=data, headers=headers)
|
res = get(
|
||||||
|
url,
|
||||||
|
**get_kwargs_for_request()
|
||||||
|
)
|
||||||
|
|
||||||
msg = f'answer received = {str(res)}'
|
msg = f'answer received = {str(res)}'
|
||||||
print(msg)
|
print(msg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
msg = f'Exception GET {req_str} = {str(e)} ({str(res)})'
|
msg = f'Exception GET {url} = {str(e)} ({str(res)})'
|
||||||
print(msg)
|
print(msg)
|
||||||
res = None
|
res = None
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_order_status(bank_order_id):
|
||||||
|
|
||||||
|
url = f'{get_domain_url()}orders/{str(bank_order_id)}'
|
||||||
|
|
||||||
|
res = None
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'expand': [
|
||||||
|
'card', 'client', 'location', 'custom_fields',
|
||||||
|
'issuer', 'secure3d', 'operations', 'cashflow'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
msg = f'GET {url}'
|
||||||
|
print(msg)
|
||||||
|
res = get(
|
||||||
|
url,
|
||||||
|
data=json.dumps(data),
|
||||||
|
**get_kwargs_for_request()
|
||||||
|
)
|
||||||
|
|
||||||
|
msg = f'create_order answer received = {str(res)}'
|
||||||
|
print(msg)
|
||||||
|
except Exception as e:
|
||||||
|
msg = f'Exception create_order GET {url} = {str(e)} ({str(res)})'
|
||||||
|
print(msg)
|
||||||
|
res = None
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def create_order(data):
|
||||||
|
|
||||||
|
url = f'{get_domain_url()}orders/create'
|
||||||
|
|
||||||
|
res = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
msg = f'POST {url}'
|
||||||
|
print(msg)
|
||||||
|
res = post(
|
||||||
|
url,
|
||||||
|
data=json.dumps(data),
|
||||||
|
**get_kwargs_for_request()
|
||||||
|
)
|
||||||
|
|
||||||
|
msg = f'create_order answer received = {str(res)}'
|
||||||
|
print(msg)
|
||||||
|
except Exception as e:
|
||||||
|
msg = f'Exception create_order POST {url} = {str(e)} ({str(res)})'
|
||||||
|
print(msg)
|
||||||
|
res = None
|
||||||
|
|
||||||
|
return res
|
||||||
0
BillingApp/__init__.py
Normal file
0
BillingApp/__init__.py
Normal file
37
BillingApp/admin.py
Normal file
37
BillingApp/admin.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from sets.admin import *
|
||||||
|
from .models import *
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
class Admin_SubscribeOrder(Admin_BaseModel):
|
||||||
|
|
||||||
|
fieldsets = (
|
||||||
|
(None, {
|
||||||
|
'classes': ['wide'],
|
||||||
|
'fields': (
|
||||||
|
('user', 'subscribe', 'subscribe_for_user'),
|
||||||
|
('enable', 'order'),
|
||||||
|
('sum', 'currency'),
|
||||||
|
('status', 'last_operation_status'),
|
||||||
|
('bank_order_id', 'pay_page'),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
list_display = [
|
||||||
|
'id', 'enable',
|
||||||
|
'user', 'subscribe', 'subscribe_for_user',
|
||||||
|
'sum', 'currency',
|
||||||
|
'status', 'last_operation_status',
|
||||||
|
'order', 'modifiedDT', 'createDT'
|
||||||
|
]
|
||||||
|
|
||||||
|
list_display_links = ['id', 'user', 'subscribe']
|
||||||
|
list_editable = ['enable']
|
||||||
|
|
||||||
|
readonly_fields = ['subscribe_for_user', 'sum', 'currency', 'modifiedDT', 'createDT']
|
||||||
|
|
||||||
|
list_filter = ['enable', 'status', 'modifiedDT', 'createDT']
|
||||||
|
search_fields = ['id', 'last_operation_status', 'status']
|
||||||
|
# filter_horizontal = ['options']
|
||||||
|
|
||||||
|
admin.site.register(SubscribeOrder, Admin_SubscribeOrder)
|
||||||
6
BillingApp/apps.py
Normal file
6
BillingApp/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class BillingappConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'BillingApp'
|
||||||
88
BillingApp/funcs.py
Normal file
88
BillingApp/funcs.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from .models import *
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
def get_order_status(order):
|
||||||
|
from BaseModels.pay_systems.DVL_Group_kaz.api.funcs import get_order_status
|
||||||
|
res_status = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
res_data = get_order_status(order.bank_order_id)
|
||||||
|
|
||||||
|
res = json.loads(res_data.text)
|
||||||
|
order.json_data['status'] = res
|
||||||
|
res = res['orders'][0]
|
||||||
|
|
||||||
|
order.status = res['status']
|
||||||
|
|
||||||
|
|
||||||
|
# if res['amount'] == res['amount_charged'] and res['status'] == 'charged':
|
||||||
|
order.save()
|
||||||
|
return order.status
|
||||||
|
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
msg = f'Exception get_order_status = {str(e)}'
|
||||||
|
if order:
|
||||||
|
msg = f'Exception get_order_status (data = {str(order.id)}) = {str(e)}'
|
||||||
|
print(msg)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_orders_for_user(user):
|
||||||
|
|
||||||
|
orders = SubscribeOrder.objects.filter(
|
||||||
|
enable=True,
|
||||||
|
user=user,
|
||||||
|
subscribe_for_user=None
|
||||||
|
).order_by('-modifiedDT')
|
||||||
|
return orders
|
||||||
|
|
||||||
|
|
||||||
|
def create_subscribe_order(data):
|
||||||
|
order = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
order = SubscribeOrder.objects.create(**data)
|
||||||
|
|
||||||
|
from GeneralApp.funcs_options import get_options_by_opt_types, get_mail_send_options
|
||||||
|
sets = get_options_by_opt_types(['domain', 'project_name'], only_vals=True)
|
||||||
|
|
||||||
|
from BaseModels.pay_systems.DVL_Group_kaz.api.funcs import create_order
|
||||||
|
data = {
|
||||||
|
'currency': data['currency'],
|
||||||
|
'amount': data['sum'],
|
||||||
|
'description': f'Заказ {order.id} на подписку '
|
||||||
|
f'{data["subscribe"].name} '
|
||||||
|
f'для пользователя {data["user"].username}',
|
||||||
|
'options': {
|
||||||
|
'auto_charge': 1,
|
||||||
|
'return_url': f'{sets["domain"]}/profile/page/my_subscribe/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res_data = create_order(data)
|
||||||
|
|
||||||
|
order.pay_page = res_data.headers.get('location')
|
||||||
|
|
||||||
|
res = json.loads(res_data.text)
|
||||||
|
order.json_data['create_order'] = res
|
||||||
|
res = res['orders'][0]
|
||||||
|
order.modifiedDT = datetime.strptime(res['updated'], '%Y-%m-%d %H:%M:%S')
|
||||||
|
order.status = res['status']
|
||||||
|
order.bank_order_id = res['id']
|
||||||
|
if 'segment' in res:
|
||||||
|
order.segment = res['segment']
|
||||||
|
if 'merchant_order_id' in res:
|
||||||
|
order.merchant_order_id = res['merchant_order_id']
|
||||||
|
order.save()
|
||||||
|
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
msg = f'Exception create_subscribe_order (data = {str(data)}) = {str(e)}'
|
||||||
|
print(msg)
|
||||||
|
|
||||||
|
return order
|
||||||
0
BillingApp/migrations/__init__.py
Normal file
0
BillingApp/migrations/__init__.py
Normal file
51
BillingApp/models.py
Normal file
51
BillingApp/models.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
from django.db import models
|
||||||
|
from BaseModels.base_models import BaseModel
|
||||||
|
from SubscribesApp.models import Subscribe, SubscribeForUser
|
||||||
|
from AuthApp.models import User
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
class SubscribeOrder(BaseModel):
|
||||||
|
|
||||||
|
subscribe = models.ForeignKey(
|
||||||
|
Subscribe, verbose_name=_('Подписка'),
|
||||||
|
on_delete=models.SET_NULL, blank=True, null=True,
|
||||||
|
related_name='subscribe_orders_for_subscribe'
|
||||||
|
)
|
||||||
|
|
||||||
|
user = models.ForeignKey(
|
||||||
|
User, verbose_name=_('Пользователь'),
|
||||||
|
on_delete=models.SET_NULL, blank=True, null=True,
|
||||||
|
related_name='subscribe_orders_for_user'
|
||||||
|
)
|
||||||
|
|
||||||
|
subscribe_for_user = models.OneToOneField(
|
||||||
|
SubscribeForUser, verbose_name=_('Подписка пользователя'),
|
||||||
|
on_delete=models.SET_NULL, blank=True, null=True,
|
||||||
|
related_name='subscribe_orders_for_user_subscribe'
|
||||||
|
)
|
||||||
|
|
||||||
|
sum = models.PositiveSmallIntegerField(verbose_name=_('Сумма'), default=0)
|
||||||
|
currency = models.CharField(verbose_name=_('Валюта'), max_length=3, default='USD')
|
||||||
|
segment = models.CharField(verbose_name=_('ID Сегмента'), null=True, default=None)
|
||||||
|
merchant_order_id = models.CharField(verbose_name=_('merchant_order_id'), null=True, default=None)
|
||||||
|
bank_order_id = models.CharField(verbose_name=_('ID заказа в банке'), null=True, default=None)
|
||||||
|
|
||||||
|
status = models.CharField(verbose_name=_('Статус заказа в банке'), null=True, default=None)
|
||||||
|
last_operation_status = models.CharField(verbose_name=_('Статус последней операции'), null=True, default=None)
|
||||||
|
|
||||||
|
pay_page = models.URLField(verbose_name=_('Ссылка на страницу оплаты'), null=True, blank=True, default=None)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('Заказ на подписку')
|
||||||
|
verbose_name_plural = _('Заказы на подписки')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
res = 'Заказ'
|
||||||
|
if self.subscribe:
|
||||||
|
res += f' на подписку {self.subscribe.name}'
|
||||||
|
if self.user:
|
||||||
|
res += f' для {self.user.username}'
|
||||||
|
|
||||||
|
if not res:
|
||||||
|
res += f' {str(self.id)}'
|
||||||
|
return res
|
||||||
3
BillingApp/tests.py
Normal file
3
BillingApp/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
3
BillingApp/views.py
Normal file
3
BillingApp/views.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
@@ -24,8 +24,11 @@ def test_code(request):
|
|||||||
# apps = SocialApp.objects.all()
|
# apps = SocialApp.objects.all()
|
||||||
# apps.delete()
|
# apps.delete()
|
||||||
|
|
||||||
from PushMessages.views import send_push
|
# from PushMessages.views import send_push
|
||||||
send_push(request.user, 'test_title', 'test_content')
|
# send_push(request.user, 'test_title', 'test_content')
|
||||||
|
|
||||||
|
from BaseModels.pay_systems.DVL_Group_kaz.api.funcs import create_order
|
||||||
|
create_order()
|
||||||
|
|
||||||
# from RoutesApp.search_matches import search_matches
|
# from RoutesApp.search_matches import search_matches
|
||||||
# search_matches()
|
# search_matches()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from .models import *
|
from .models import *
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.translation import get_language, activate
|
from django.utils.translation import get_language, activate
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
def get_cur_user_subscribe(user):
|
def get_cur_user_subscribe(user):
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ def get_cur_user_subscribe(user):
|
|||||||
return user_subscribe
|
return user_subscribe
|
||||||
|
|
||||||
|
|
||||||
def get_subsribes_w_options():
|
def get_subscribes_w_options():
|
||||||
all_options = SubscribeOption.objects.filter(enable=True)
|
all_options = SubscribeOption.objects.filter(enable=True)
|
||||||
subscribes = Subscribe.objects.filter(enable=True)
|
subscribes = Subscribe.objects.filter(enable=True)
|
||||||
for subscribe in subscribes:
|
for subscribe in subscribes:
|
||||||
@@ -23,6 +24,28 @@ def get_subsribes_w_options():
|
|||||||
return subscribes, all_options
|
return subscribes, all_options
|
||||||
|
|
||||||
|
|
||||||
|
def check_n_enable_subscribe_by_order(order):
|
||||||
|
|
||||||
|
subscribes_for_user = SubscribeForUser.objects.filter(user=order.user)
|
||||||
|
|
||||||
|
if order and order.enable and order.status == 'charged':
|
||||||
|
kwargs = {
|
||||||
|
'user': order.user,
|
||||||
|
'subscribe': order.subscribe,
|
||||||
|
'last_paid_DT': datetime.now(),
|
||||||
|
'paid_period_from_DT': datetime.now(),
|
||||||
|
'paid_period_to_DT': datetime.now() + timedelta(hours=order.subscribe.period),
|
||||||
|
'receive_finish_subscribe_msg': True,
|
||||||
|
}
|
||||||
|
subscribe_for_user = SubscribeForUser.objects.create(**kwargs)
|
||||||
|
order.subscribe_for_user = subscribe_for_user
|
||||||
|
order.save()
|
||||||
|
|
||||||
|
subscribes_for_user = [subscribe_for_user]
|
||||||
|
|
||||||
|
return subscribes_for_user
|
||||||
|
|
||||||
|
|
||||||
def get_profile_subscribe_page_content_html(request):
|
def get_profile_subscribe_page_content_html(request):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -32,9 +55,20 @@ def get_profile_subscribe_page_content_html(request):
|
|||||||
|
|
||||||
# data = json.loads(request.body)
|
# data = json.loads(request.body)
|
||||||
# all_options = SubscribeOption.objects.filter(enable=True)
|
# all_options = SubscribeOption.objects.filter(enable=True)
|
||||||
subscribes, all_options = get_subsribes_w_options()
|
subscribes, all_options = get_subscribes_w_options()
|
||||||
|
|
||||||
|
subscribe_for_user = None
|
||||||
|
|
||||||
|
if request.user and request.user.is_authenticated:
|
||||||
|
from BillingApp.funcs import get_orders_for_user, get_order_status
|
||||||
|
orders = get_orders_for_user(request.user)
|
||||||
|
for order in orders:
|
||||||
|
res = get_order_status(order)
|
||||||
|
subscribe_for_user = check_n_enable_subscribe_by_order(order)
|
||||||
|
|
||||||
|
if not subscribe_for_user:
|
||||||
subscribe_for_user = SubscribeForUser.objects.filter(user=request.user)
|
subscribe_for_user = SubscribeForUser.objects.filter(user=request.user)
|
||||||
|
|
||||||
if not subscribe_for_user:
|
if not subscribe_for_user:
|
||||||
tpl_name = 'blocks/profile/b_subscribe_variants.html'
|
tpl_name = 'blocks/profile/b_subscribe_variants.html'
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from django.shortcuts import render
|
|||||||
from uuid import uuid1
|
from uuid import uuid1
|
||||||
from .models import *
|
from .models import *
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.http import HttpResponse, Http404, JsonResponse
|
from django.http import HttpResponse, Http404, JsonResponse, HttpResponseRedirect
|
||||||
from django.template import loader, RequestContext
|
from django.template import loader, RequestContext
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from BaseModels.mailSender import techSendMail
|
from BaseModels.mailSender import techSendMail
|
||||||
@@ -17,6 +17,7 @@ from datetime import datetime, time, timedelta
|
|||||||
from channels.layers import get_channel_layer
|
from channels.layers import get_channel_layer
|
||||||
from asgiref.sync import async_to_sync
|
from asgiref.sync import async_to_sync
|
||||||
from GeneralApp.funcs import get_and_set_lang
|
from GeneralApp.funcs import get_and_set_lang
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
|
||||||
|
|
||||||
@login_required()#login_url='/profile/login/')
|
@login_required()#login_url='/profile/login/')
|
||||||
@@ -33,6 +34,18 @@ def subscribe_now_ajax(request):
|
|||||||
|
|
||||||
subscribe = Subscribe.objects.get(id=data['subscribe_id'])
|
subscribe = Subscribe.objects.get(id=data['subscribe_id'])
|
||||||
|
|
||||||
|
kwargs_for_order = {
|
||||||
|
'user': request.user,
|
||||||
|
'subscribe': subscribe,
|
||||||
|
'currency': 'USD',
|
||||||
|
'sum': subscribe.price,
|
||||||
|
}
|
||||||
|
|
||||||
|
from BillingApp.funcs import create_subscribe_order
|
||||||
|
order = create_subscribe_order(kwargs_for_order)
|
||||||
|
if order:
|
||||||
|
return JsonResponse({'redirect': order.pay_page})
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'user': request.user,
|
'user': request.user,
|
||||||
'subscribe': subscribe,
|
'subscribe': subscribe,
|
||||||
@@ -41,13 +54,10 @@ def subscribe_now_ajax(request):
|
|||||||
'paid_period_to_DT': datetime.now() + timedelta(hours=subscribe.period),
|
'paid_period_to_DT': datetime.now() + timedelta(hours=subscribe.period),
|
||||||
'receive_finish_subscribe_msg': True,
|
'receive_finish_subscribe_msg': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe_for_user = SubscribeForUser.objects.filter(user=request.user)
|
subscribe_for_user = SubscribeForUser.objects.filter(user=request.user)
|
||||||
if subscribe_for_user:
|
if subscribe_for_user:
|
||||||
subscribe_for_user.update(**kwargs)
|
subscribe_for_user.update(**kwargs)
|
||||||
subscribe_for_user = subscribe_for_user[0]
|
subscribe_for_user = subscribe_for_user[0]
|
||||||
else:
|
|
||||||
subscribe_for_user = SubscribeForUser.objects.create(**kwargs)
|
|
||||||
|
|
||||||
if not subscribe_for_user:
|
if not subscribe_for_user:
|
||||||
tpl_name = 'blocks/profile/b_subscribe_variants.html'
|
tpl_name = 'blocks/profile/b_subscribe_variants.html'
|
||||||
|
|||||||
@@ -50,3 +50,14 @@ class SubscribeForUser(BaseModel):
|
|||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('Пользовательская подписка')
|
verbose_name = _('Пользовательская подписка')
|
||||||
verbose_name_plural = _('Пользовательские подписки')
|
verbose_name_plural = _('Пользовательские подписки')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
res = 'Подписка'
|
||||||
|
if self.subscribe:
|
||||||
|
res += f' {self.subscribe.name}'
|
||||||
|
if self.user:
|
||||||
|
res += f' для {self.user.username}'
|
||||||
|
|
||||||
|
if not res:
|
||||||
|
res += f' {str(self.id)}'
|
||||||
|
return res
|
||||||
@@ -118,6 +118,7 @@ INSTALLED_APPS = [
|
|||||||
'ArticlesApp',
|
'ArticlesApp',
|
||||||
'SubscribesApp',
|
'SubscribesApp',
|
||||||
'PushMessages',
|
'PushMessages',
|
||||||
|
'BillingApp',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|||||||
BIN
dvldigitalprojects.p12
Normal file
BIN
dvldigitalprojects.p12
Normal file
Binary file not shown.
@@ -13,5 +13,6 @@ django-colorfield
|
|||||||
django-webpush==0.3.5
|
django-webpush==0.3.5
|
||||||
django-allauth==0.60.0
|
django-allauth==0.60.0
|
||||||
pytz==2024.1
|
pytz==2024.1
|
||||||
|
requests-pkcs12==1.24
|
||||||
#django-tz-detect==0.4.0
|
#django-tz-detect==0.4.0
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user