Browse Source

админ панель для телеграм бота, отображение всех полей в админке #5

Anton 1 year ago
parent
commit
d8ab095f7b
  1. 6
      adminpanel/settings.py
  2. 2
      adminpanel/urls.py
  3. 33
      adminpanelapp/admin.py
  4. 137
      adminpanelapp/models.py
  5. 3
      adminpanelapp/urls.py
  6. 15
      adminpanelapp/views.py
  7. 75
      bot_modules/mod_table_operate.py
  8. 14
      bot_modules/orders.py
  9. 4
      bot_sys/config.py

6
adminpanel/settings.py

@ -37,7 +37,8 @@ INSTALLED_APPS = [
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'adminpanelapp' 'adminpanelapp',
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@ -129,6 +130,3 @@ ASYNC_MODE = 'django'
g_telegram_bot_api_token = '6212211018:AAEwcEN0NdjbhqDiClUk8vZkE_vfRUxsReU' g_telegram_bot_api_token = '6212211018:AAEwcEN0NdjbhqDiClUk8vZkE_vfRUxsReU'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

2
adminpanel/urls.py

@ -8,4 +8,4 @@ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('', include('adminpanelapp.urls')), path('', include('adminpanelapp.urls')),
path('', RedirectView.as_view(url='/admin/adminpanelapp/orders'), name='') path('', RedirectView.as_view(url='/admin/adminpanelapp/orders'), name='')
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ]

33
adminpanelapp/admin.py

@ -1,9 +1,6 @@
import requests
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.utils.html import format_html
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
from django.utils.safestring import mark_safe
from adminpanel.settings import g_telegram_bot_api_token
from .models import Orders from .models import Orders
@ -13,25 +10,23 @@ from django.urls import reverse
class OrdersAdmin(admin.ModelAdmin): class OrdersAdmin(admin.ModelAdmin):
list_display = ('orderName', 'orderCreateDateTime', 'show_orderPhoto', 'show_orderPhotoPay',) list_display = ('orderName', 'orderCreateDateTime', 'orderDesc', 'orderAddress', 'show_photo', 'show_photopay')
actions =['change_value_and_redirect', ] actions =['send_message']
readonly_fields = ['orderPhoto', 'orderPhotoPay'] exclude = ['orderAccess', 'userID', 'orderPhoto', 'orderPhotoPay']
def show_photo(self, obj):
html = obj.get_photo_html()
return mark_safe(html)
def show_orderPhoto(self, obj): show_photo.short_description = 'Фото'
if obj.orderPhoto and obj.orderPhoto.url:
return format_html('<img src="{}" width="100" height="100" />', obj.orderPhoto.url)
return "-"
show_orderPhoto.short_description = 'Фото заказа'
def show_orderPhotoPay(self, obj): def show_photopay(self, obj):
if obj.orderPhotoPay and obj.orderPhotoPay.url: html = obj.get_photopay_html()
return format_html('<img src="{}" width="100" height="100" />', obj.orderPhotoPay.url) return mark_safe(html)
return "-"
show_orderPhotoPay.short_description = 'Фото чека'
show_photopay.short_description = 'Чек'
def change_value_and_redirect(orders, request, queryset): def send_message(orders, request, queryset):
selected_objects = request.POST.getlist(ACTION_CHECKBOX_NAME) selected_objects = request.POST.getlist(ACTION_CHECKBOX_NAME)
if len(selected_objects) != 1: if len(selected_objects) != 1:
messages.error(request, "Выберите только один объект") messages.error(request, "Выберите только один объект")
@ -44,6 +39,6 @@ class OrdersAdmin(admin.ModelAdmin):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
change_value_and_redirect.short_description = 'Отправка сообщения' send_message.short_description = 'Отправка сообщения'
admin.site.register(Orders, OrdersAdmin) admin.site.register(Orders, OrdersAdmin)

137
adminpanelapp/models.py

@ -1,40 +1,139 @@
from django.db import models from urllib.parse import quote
import asyncio
import requests
from django.db import models
from adminpanel.settings import g_telegram_bot_api_token
class Orders(models.Model): class Orders(models.Model):
SEND_MESSAGE = (
(True, 'Написать'),
(False, 'Не отправлять'),
(None, 'Неизвестно'),
)
IS_APPROVED = (
(True, 'Заказ подтвержден'),
(False, 'Заказ не подтвержден'),
(None, 'Неизвестно'),
)
orderID = models.AutoField(primary_key=True, verbose_name='id заказа') orderID = models.AutoField(primary_key=True, verbose_name='id заказа')
userID = models.CharField(max_length=100, verbose_name='id пользователя в tg', null=True) userID = models.CharField(max_length=100, verbose_name='id пользователя в tg', null=True)
orderName = models.CharField(max_length=100, verbose_name='наименование', null=True) orderName = models.CharField(max_length=100, verbose_name='наименование', null=True)
orderDesc = models.TextField(verbose_name='описание', null=True) orderDesc = models.TextField(verbose_name='описание', null=True)
orderPhoto = models.ImageField(upload_to='photo/', verbose_name='фото') orderPhoto = models.ImageField(verbose_name='фото', null=True)
orderPhotoPay = models.ImageField(upload_to='photo/', verbose_name='чек') orderPhotoPay = models.ImageField(upload_to='photo/', verbose_name='чек')
orderAddress = models.CharField(max_length=100, verbose_name='адрес доставки', blank=True, null=True) orderAddress = models.CharField(max_length=100, verbose_name='адрес доставки', blank=True, null=True)
orderAccess = models.CharField(max_length=100, verbose_name='доступ', blank=True, null=True) orderAccess = models.CharField(max_length=100, verbose_name='доступ', blank=True, null=True)
orderCreateDateTime = models.DateTimeField(auto_now_add=True, null=True, verbose_name='дата и время создания') orderCreateDateTime = models.DateTimeField(auto_now_add=True, null=True, verbose_name='дата и время создания')
orderStatus = models.CharField(max_length=100, verbose_name='статус заказа', blank=True, null=True) orderStatus = models.CharField(max_length=100, verbose_name='статус заказа', blank=True, null=True)
def get_photo_html(self, width=100, height=100, large_width=400, large_height=400):
token = g_telegram_bot_api_token
file_id = self.orderPhoto
url = f"https://api.telegram.org/bot{token}/getFile?file_id={file_id}"
response = requests.get(url)
data = response.json()
if data['ok']:
file_path = data["result"]["file_path"]
photo_url = f"https://api.telegram.org/file/bot{token}/{quote(file_path, safe='')}"
html = f"""
<html>
<body>
<img src="{photo_url}" width="{width}" height="{height}" class="small-photo">
<img src="{photo_url}" width="{large_width}" height="{large_height}" class="large-photo">
<a href="#" onclick="togglePhoto()" id="toggle-button" class="button">Увеличить фото</a>
<script>
function togglePhoto() {{
var smallPhoto = document.getElementsByClassName("small-photo")[0];
var largePhoto = document.getElementsByClassName("large-photo")[0];
var toggleButton = document.getElementById("toggle-button");
if (smallPhoto.style.display === "none") {{
smallPhoto.style.display = "block";
largePhoto.style.display = "none";
toggleButton.innerHTML = "Увеличить фото";
}} else {{
smallPhoto.style.display = "none";
largePhoto.style.display = "block";
toggleButton.innerHTML = "Уменьшить фото";
}}
}}
</script>
<style>
.large-photo {{
display: none;
}}
.button {{
display: inline-block;
padding: 10px 20px;
background-color: #4CAF50;
color: white;
text-align: center;
text-decoration: none;
font-size: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
}}
</style>
</body>
</html>
"""
return html
def get_photopay_html(self, width=100, height=100, large_width=400, large_height=400):
token = g_telegram_bot_api_token
file_id = self.orderPhotoPay
url = f"https://api.telegram.org/bot{token}/getFile?file_id={file_id}"
response = requests.get(url)
data = response.json()
if data['ok']:
file_path = data["result"]["file_path"]
photo_url = f"https://api.telegram.org/file/bot{token}/{quote(file_path, safe='')}"
html = f"""
<html>
<body>
<img src="{photo_url}" width="{width}" height="{height}" class="small-photo">
<img src="{photo_url}" width="{large_width}" height="{large_height}" class="large-photo">
<a href="#" onclick="togglePhotoPay()" id="toggle-button" class="button">Увеличить фото</a>
<script>
function togglePhotoPay() {{
var smallPhotoPay = document.getElementsByClassName("small-photo")[1];
var largePhotoPay = document.getElementsByClassName("large-photo")[1];
var toggleButton = document.getElementById("toggle-button");
if (smallPhotoPay.style.display === "none") {{
smallPhotoPay.style.display = "block";
largePhotoPay.style.display = "none";
toggleButton.innerHTML = "Увеличить фото";
}} else {{
smallPhotoPay.style.display = "none";
largePhotoPay.style.display = "block";
toggleButton.innerHTML = "Уменьшить фото";
}}
}}
</script>
<style>
.large-photo {{
display: none;
}}
.button {{
display: inline-block;
padding: 10px 20px;
background-color: #4CAF50;
color: white;
text-align: center;
text-decoration: none;
font-size: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
}}
</style>
</body>
</html>
"""
return html
class Meta: class Meta:
# app_label = 'adminpanel'
verbose_name_plural = 'Заказы' verbose_name_plural = 'Заказы'
managed = False managed = False
db_table = 'orders' db_table = 'orders'
# def __str__(self):
# return self.name

3
adminpanelapp/urls.py

@ -4,4 +4,7 @@ from .views import send_telegram_message
urlpatterns = [ urlpatterns = [
path('send_telegram_message/<int:chat_id>/', send_telegram_message, name='send_telegram_message'), path('send_telegram_message/<int:chat_id>/', send_telegram_message, name='send_telegram_message'),
] ]

15
adminpanelapp/views.py

@ -1,10 +1,8 @@
from django.contrib import messages from django.contrib import messages
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render, HttpResponse
import requests import requests
from django.urls import reverse from django.urls import reverse
from django.shortcuts import render
from adminpanelapp.models import Orders
from bot_sys.config import g_telegram_bot_api_token from bot_sys.config import g_telegram_bot_api_token
@ -25,4 +23,13 @@ def send_telegram_message(request, chat_id):
back_url = reverse('') back_url = reverse('')
return HttpResponseRedirect(back_url) return HttpResponseRedirect(back_url)
else: else:
return render(request, 'send_telegram_message.html') return render(request, 'send_telegram_message.html')

75
bot_modules/mod_table_operate.py

@ -1,17 +1,10 @@
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> # Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru>
import os
import sqlite3
import requests
from aiogram.dispatcher.storage import FSMContextProxy
from asgiref.sync import sync_to_async
from adminpanelapp.models import Orders
# Модуль для редактирования и просмотра таблицы в БД # Модуль для редактирования и просмотра таблицы в БД
from bot_sys import keyboard, user_access, bd_table, bot_bd, bot_subscribes from bot_sys import keyboard, user_access, bd_table, bot_bd, bot_subscribes
from bot_modules import access_utils, mod_simple_message from bot_modules import access_utils, mod_simple_message
from bot_sys.config import g_telegram_bot_api_token
from template import simple_message, bd_item, bd_item_select, bd_item_view, bd_item_delete, bd_item_add, bd_item_edit from template import simple_message, bd_item, bd_item_select, bd_item_view, bd_item_delete, bd_item_add, bd_item_edit
from aiogram.dispatcher import FSMContext from aiogram.dispatcher import FSMContext
@ -266,42 +259,6 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule):
print('request', request, param) print('request', request, param)
res, error = self.m_Bot.SQLRequest(request, commit = True, return_error = True, param = param) res, error = self.m_Bot.SQLRequest(request, commit = True, return_error = True, param = param)
async def create_order():
# получаю orderID
conn = sqlite3.connect('bot.db')
cursor = conn.cursor()
query = f"SELECT orderID FROM orders WHERE orderDesc = '{param[1]}'"
cursor.execute(query)
result = cursor.fetchone()
order_id = result[0] if result else None
conn.close()
token = g_telegram_bot_api_token
file_id = param[2]
url = f"https://api.telegram.org/bot{token}/getFile?file_id={file_id}&upload.auto_scale=true"
response = requests.get(url)
data = response.json()
if data['ok']:
file_path = data["result"]["file_path"]
file_url = f"https://api.telegram.org/file/bot{token}/{file_path}"
file_name = os.path.basename(file_path)
save_path = f"media/photo/{file_name}" # Полный путь для сохранения файла
response = requests.get(file_url)
if response.status_code == 200:
with open(save_path, 'wb') as file:
file.write(response.content)
order = await sync_to_async(Orders.objects.get)(orderID=order_id)
with open(save_path, 'rb') as file:
await sync_to_async(order.orderPhoto.save)(file_name, file)
await create_order()
self.OnChange() self.OnChange()
if error: if error:
@ -397,36 +354,6 @@ class TableOperateModule(mod_simple_message.SimpleMessageModule):
async def OnChange(a_ItemID, a_ItemData, a_EditUserID): async def OnChange(a_ItemID, a_ItemData, a_EditUserID):
await self.OnChangeField(a_Field, a_ItemID, a_ItemData, a_EditUserID) await self.OnChangeField(a_Field, a_ItemID, a_ItemData, a_EditUserID)
async def my_handler(fsm: FSMContextProxy):
order_id = fsm.get('orderID')
cheque = fsm.get('orderPhotoPay')
item = await sync_to_async(Orders.objects.get)(orderID=order_id)
if cheque != None:
token = g_telegram_bot_api_token
url = f"https://api.telegram.org/bot{token}/getFile?file_id={cheque}"
response = requests.get(url)
data = response.json()
if data['ok']:
file_path = data["result"]["file_path"]
file_url = f"https://api.telegram.org/file/bot{token}/{file_path}"
file_name = os.path.basename(file_path)
save_path = f"media/photo/{file_name}"
response = requests.get(file_url)
if response.status_code == 200:
with open(save_path, 'wb') as file:
file.write(response.content)
order = await sync_to_async(Orders.objects.get)(orderID=order_id)
with open(save_path, 'rb') as file:
await sync_to_async(order.orderPhotoPay.save)(file_name, file)
await my_handler(a_ItemData)
return self.OnChange() return self.OnChange()
table_name = self.m_Table.GetName() table_name = self.m_Table.GetName()

14
bot_modules/orders.py

@ -1,6 +1,10 @@
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
# Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru> # Общественное достояние, 2023, Алексей Безбородов (Alexei Bezborodov) <AlexeiBv+mirocod_platform_bot@narod.ru>
import aiohttp
import requests
from asgiref.sync import sync_to_async
from adminpanelapp.models import Orders
# Заказы # Заказы
from bot_sys import bot_bd, keyboard, user_access, bd_table, bot_subscribes from bot_sys import bot_bd, keyboard, user_access, bd_table, bot_subscribes
@ -217,6 +221,8 @@ class ModuleOrders(mod_table_operate.TableOperateModule):
a_ItemData[status_field] = str(OrderStatus.NEW) a_ItemData[status_field] = str(OrderStatus.NEW)
a_ItemData[address_field] = '' a_ItemData[address_field] = ''
a_ItemData[photo_pay_field] = '0' a_ItemData[photo_pay_field] = '0'
return super().AddBDItemFunc(a_ItemData, a_UserID) return super().AddBDItemFunc(a_ItemData, a_UserID)
def GetStartKeyboardButtons(self, a_Message, a_UserGroups): def GetStartKeyboardButtons(self, a_Message, a_UserGroups):
@ -266,3 +272,9 @@ class ModuleUserOrders(ModuleOrders):
def GetName(self): def GetName(self):
return module_name return module_name

4
bot_sys/config.py

@ -6,11 +6,11 @@
# --------------------------------------------------------- # ---------------------------------------------------------
# API токен телеграмм бота. Создаётся с помощью @BotFather # API токен телеграмм бота. Создаётся с помощью @BotFather
# Задаётся либо прямо тут в коде, либо в файле telegram_bot_api_token_file_name # Задаётся либо прямо тут в коде, либо в файле telegram_bot_api_token_file_name
g_telegram_bot_api_token = '' g_telegram_bot_api_token = '6212211018:AAEwcEN0NdjbhqDiClUk8vZkE_vfRUxsReU'
# Пользователи имеющие полный доступ, ID можно узнать например у этого бота @GetMyIDBot # Пользователи имеющие полный доступ, ID можно узнать например у этого бота @GetMyIDBot
# Задаётся либо прямо тут в коде, либо в файле root_ids_file_name # Задаётся либо прямо тут в коде, либо в файле root_ids_file_name
g_root_ids = [] g_root_ids = [1221909008]
# Логирование событий в файл # Логирование событий в файл
g_log_to_file = True g_log_to_file = True

Loading…
Cancel
Save