parent
77aff56530
commit
d91da23a3f
24 changed files with 868 additions and 1 deletions
@ -0,0 +1,3 @@ |
|||||||
|
from django.contrib import admin |
||||||
|
|
||||||
|
# Register your models here. |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
from django.apps import AppConfig |
||||||
|
|
||||||
|
|
||||||
|
class ShowAiConfig(AppConfig): |
||||||
|
default_auto_field = 'django.db.models.BigAutoField' |
||||||
|
name = 'ai' |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
# Generated by Django 4.2.7 on 2026-06-08 07:20 |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
initial = True |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.CreateModel( |
||||||
|
name='AiShow', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(primary_key=True, serialize=False)), |
||||||
|
('cinema', models.CharField(max_length=50)), |
||||||
|
('zz_code', models.CharField(max_length=50)), |
||||||
|
('show_date', models.DateField()), |
||||||
|
('is_ai_show', models.BooleanField(default=True)), |
||||||
|
('show', models.TextField()), |
||||||
|
('sales', models.CharField(max_length=50)), |
||||||
|
('prompt', models.TextField()), |
||||||
|
('result', models.TextField()), |
||||||
|
('message', models.TextField()), |
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'AI排片数据', |
||||||
|
'verbose_name_plural': 'AI排片数据', |
||||||
|
'db_table': 'ai_show_result', |
||||||
|
}, |
||||||
|
), |
||||||
|
migrations.CreateModel( |
||||||
|
name='TestCinema', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(primary_key=True, serialize=False)), |
||||||
|
('name', models.CharField(max_length=50)), |
||||||
|
('zz_code', models.CharField(max_length=50)), |
||||||
|
('db_config', models.TextField()), |
||||||
|
('user_config', models.TextField()), |
||||||
|
('is_active', models.BooleanField(default=True)), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': '测试影院', |
||||||
|
'verbose_name_plural': '测试影院', |
||||||
|
'db_table': 'ai_show_cinema', |
||||||
|
}, |
||||||
|
), |
||||||
|
] |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
# Generated by Django 4.2.7 on 2026-06-08 10:37 |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('ai', '0001_initial'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.AddField( |
||||||
|
model_name='aishow', |
||||||
|
name='take_times', |
||||||
|
field=models.IntegerField(default=0), |
||||||
|
), |
||||||
|
migrations.AddField( |
||||||
|
model_name='aishow', |
||||||
|
name='take_tokens', |
||||||
|
field=models.CharField(default='', max_length=2000), |
||||||
|
), |
||||||
|
] |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
# Generated by Django 4.2.7 on 2026-06-09 02:00 |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('ai', '0002_aishow_take_times_aishow_take_tokens'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.CreateModel( |
||||||
|
name='PromptTemplate', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(primary_key=True, serialize=False)), |
||||||
|
('prompt_type', models.CharField(max_length=50)), |
||||||
|
('prompt_key', models.CharField(max_length=50)), |
||||||
|
('prompt_val', models.TextField()), |
||||||
|
('del_flag', models.BooleanField(default=False)), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': '提示词', |
||||||
|
'verbose_name_plural': '提示词', |
||||||
|
'db_table': 'ai_prompt_template', |
||||||
|
}, |
||||||
|
), |
||||||
|
] |
||||||
@ -0,0 +1,59 @@ |
|||||||
|
from django.db import models |
||||||
|
|
||||||
|
|
||||||
|
# Create your models here. |
||||||
|
class TestCinema(models.Model): |
||||||
|
id = models.AutoField(primary_key=True) |
||||||
|
name = models.CharField(max_length=50) |
||||||
|
zz_code = models.CharField(max_length=50) |
||||||
|
db_config = models.TextField() |
||||||
|
user_config = models.TextField() |
||||||
|
is_active = models.BooleanField(default=True) |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return self.name |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = '测试影院' |
||||||
|
verbose_name_plural = '测试影院' |
||||||
|
db_table = 'ai_show_cinema' |
||||||
|
|
||||||
|
|
||||||
|
class PromptTemplate(models.Model): |
||||||
|
id = models.AutoField(primary_key=True) |
||||||
|
prompt_type = models.CharField(max_length=50) |
||||||
|
prompt_key = models.CharField(max_length=50) |
||||||
|
prompt_val = models.TextField() |
||||||
|
del_flag = models.BooleanField(default=False) |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return self.prompt_key |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = '提示词' |
||||||
|
verbose_name_plural = '提示词' |
||||||
|
db_table = 'ai_prompt_template' |
||||||
|
|
||||||
|
|
||||||
|
class AiShow(models.Model): |
||||||
|
id = models.AutoField(primary_key=True) |
||||||
|
cinema = models.CharField(max_length=50) |
||||||
|
zz_code = models.CharField(max_length=50) |
||||||
|
show_date = models.DateField() |
||||||
|
is_ai_show = models.BooleanField(default=True) |
||||||
|
show = models.TextField() |
||||||
|
sales = models.CharField(max_length=50) |
||||||
|
prompt = models.TextField() |
||||||
|
result = models.TextField() |
||||||
|
message = models.TextField() |
||||||
|
created_at = models.DateTimeField(auto_now_add=True) |
||||||
|
take_times = models.IntegerField(default=0) |
||||||
|
take_tokens = models.CharField(default='', max_length=2000) |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return self.cinema |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'AI排片数据' |
||||||
|
verbose_name_plural = 'AI排片数据' |
||||||
|
db_table = 'ai_show_result' |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
from rest_framework import serializers |
||||||
|
|
||||||
|
from ai.models import * |
||||||
|
|
||||||
|
|
||||||
|
class TestCinemaSerializer(serializers.ModelSerializer): |
||||||
|
class Meta: |
||||||
|
model = TestCinema |
||||||
|
fields = '__all__' |
||||||
|
|
||||||
|
|
||||||
|
class PromptTemplateSerializer(serializers.ModelSerializer): |
||||||
|
class Meta: |
||||||
|
model = PromptTemplate |
||||||
|
fields = '__all__' |
||||||
|
|
||||||
|
|
||||||
|
class AiShowSerializer(serializers.ModelSerializer): |
||||||
|
class Meta: |
||||||
|
model = AiShow |
||||||
|
fields = '__all__' |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
from celery import shared_task |
||||||
|
from ai.utils.show_process import show_main_process |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task |
||||||
|
def ai_show_general(): |
||||||
|
show_main_process() |
||||||
|
print("task success") |
||||||
|
return True |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
from django.test import TestCase |
||||||
|
|
||||||
|
# Create your tests here. |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
""" |
||||||
|
URL configuration for dingxin_toolbox_drf project. |
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see: |
||||||
|
https://docs.djangoproject.com/en/4.2/topics/http/urls/ |
||||||
|
Examples: |
||||||
|
Function views |
||||||
|
1. Add an import: from my_app import views |
||||||
|
2. Add a URL to urlpatterns: path('', views.home, name='home') |
||||||
|
Class-based views |
||||||
|
1. Add an import: from other_app.views import Home |
||||||
|
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') |
||||||
|
Including another URLconf |
||||||
|
1. Import the include() function: from django.urls import include, path |
||||||
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) |
||||||
|
""" |
||||||
|
from django.contrib import admin |
||||||
|
from django.urls import path, include |
||||||
|
from ai.views import * |
||||||
|
|
||||||
|
urlpatterns = [ |
||||||
|
path('manual_general_show', manual_general_show), |
||||||
|
path('get_cinema_show_result', get_cinema_show_result), |
||||||
|
path('clear', clear_lock), |
||||||
|
] |
||||||
@ -0,0 +1,37 @@ |
|||||||
|
import datetime |
||||||
|
from chinese_calendar import (is_holiday, is_workday) |
||||||
|
|
||||||
|
|
||||||
|
def get_data_datetime(show_date): |
||||||
|
show_date_obj = datetime.datetime.strptime(show_date, '%Y-%m-%d') |
||||||
|
target_start_datetime_obj = show_date_obj + datetime.timedelta(hours=6) |
||||||
|
target_end_datetime_obj = show_date_obj + datetime.timedelta(hours=29, minutes=59, seconds=59) |
||||||
|
data_start_datetime_obj = show_date_obj + datetime.timedelta(days=-7) + datetime.timedelta(hours=6) |
||||||
|
data_end_datetime_obj = show_date_obj + datetime.timedelta(hours=5, minutes=59, seconds=59) |
||||||
|
history_start = datetime.datetime.strftime(data_start_datetime_obj, '%Y-%m-%d %H:%M:%S') |
||||||
|
history_end = datetime.datetime.strftime(data_end_datetime_obj, '%Y-%m-%d %H:%M:%S') |
||||||
|
target_start = datetime.datetime.strftime(target_start_datetime_obj, '%Y-%m-%d %H:%M:%S') |
||||||
|
target_end = datetime.datetime.strftime(target_end_datetime_obj, '%Y-%m-%d %H:%M:%S') |
||||||
|
return history_start, history_end, target_start, target_end |
||||||
|
|
||||||
|
|
||||||
|
def get_date_type(show_date, template_date): |
||||||
|
show_date_obj = datetime.datetime.strptime(show_date, '%Y-%m-%d') |
||||||
|
template_date_obj = datetime.datetime.strptime(template_date, '%Y-%m-%d') |
||||||
|
result = dict() |
||||||
|
# 处理参考数据日期 |
||||||
|
history_date_list = [(show_date_obj - datetime.timedelta(days=i)) for i in range(7, 0, -1)] |
||||||
|
history_date = '、'.join( |
||||||
|
[f'{datetime.date.strftime(d, "%Y-%m-%d")}({"节假日" if is_holiday(d) else "工作日"})' for d in |
||||||
|
history_date_list]) |
||||||
|
# 处理目标日期 |
||||||
|
show_date = f'{datetime.date.strftime(show_date_obj, "%Y-%m-%d")}({"节假日" if is_holiday(show_date_obj) else "工作日"})' |
||||||
|
show_date_is_holiday = is_holiday(show_date_obj) |
||||||
|
# 处理模板日期 |
||||||
|
template_date = f'{datetime.date.strftime(template_date_obj, "%Y-%m-%d")}({"节假日" if is_holiday(template_date_obj) else "工作日"})' |
||||||
|
template_date_is_holiday = is_holiday(template_date_obj) |
||||||
|
return history_date, show_date, show_date_is_holiday, template_date, template_date_is_holiday |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
get_date_type("2026-06-13", "2026-06-01") |
||||||
@ -0,0 +1,136 @@ |
|||||||
|
import pymysql |
||||||
|
from pymysql.cursors import DictCursor |
||||||
|
from ai.utils.sql import * |
||||||
|
import datetime |
||||||
|
import pandas as pd |
||||||
|
|
||||||
|
|
||||||
|
class GetData: |
||||||
|
def __init__(self, db_config): |
||||||
|
self.conn = pymysql.connect(**db_config) |
||||||
|
self.cur = self.conn.cursor(cursor=DictCursor) |
||||||
|
|
||||||
|
def exit(self): |
||||||
|
try: |
||||||
|
self.cur.close() |
||||||
|
self.conn.close() |
||||||
|
except Exception as e: |
||||||
|
print(e) |
||||||
|
|
||||||
|
# 获取指定日期范围的排片数据 |
||||||
|
def get_show_data(self, start_datetime, end_datetime): |
||||||
|
# print(self.cur.mogrify(GET_SHOW_DATA, (start_datetime, end_datetime))) |
||||||
|
self.cur.execute(GET_SHOW_DATA, (start_datetime, end_datetime)) |
||||||
|
show_data = self.cur.fetchall() |
||||||
|
show_data_mapping = { |
||||||
|
'hall_name': '影厅别名', |
||||||
|
'hall_id': '影厅id', |
||||||
|
'movie_name': '影片别名', |
||||||
|
'movie_id': '本地影片id', |
||||||
|
'language': '语言', |
||||||
|
'show_date': '放映日期', |
||||||
|
'start_time': '开始时间', |
||||||
|
'end_time': '结束时间', |
||||||
|
'length': '片长', |
||||||
|
'duration': '场间', |
||||||
|
} |
||||||
|
return self.format_to_csv(show_data, show_data_mapping) |
||||||
|
|
||||||
|
# 获取指定范围的影片销售数据 |
||||||
|
def get_sell_data(self, start_datetime, end_datetime): |
||||||
|
# print(self.cur.mogrify(GET_SELL_DATA, (start_datetime, end_datetime))) |
||||||
|
self.cur.execute(GET_SELL_DATA, (start_datetime, end_datetime, start_datetime, end_datetime)) |
||||||
|
sell_data = self.cur.fetchall() |
||||||
|
sell_data_mapping = { |
||||||
|
'movie_name': '影片别名', |
||||||
|
'movie_id': '本地影片id', |
||||||
|
'show_date': '放映日期', |
||||||
|
'start_time': '开始时间', |
||||||
|
'hall_name': '影厅别名', |
||||||
|
'hall_id': '影厅id', |
||||||
|
'total_count': '场次观影人数', |
||||||
|
'total_income': '场次收入', |
||||||
|
'seat_num': '影厅座位数', |
||||||
|
'average_price': '平均价', |
||||||
|
'rate': '上座率(单位%)', |
||||||
|
} |
||||||
|
return self.format_to_csv(sell_data, sell_data_mapping) |
||||||
|
|
||||||
|
# 获取指定范围的影片销售数据 |
||||||
|
def get_total_income(self, start_datetime, end_datetime): |
||||||
|
# print(self.cur.mogrify(GET_SELL_DATA, (start_datetime, end_datetime))) |
||||||
|
self.cur.execute(GET_TOTAL_INCOME, (start_datetime, end_datetime, start_datetime, end_datetime)) |
||||||
|
return self.cur.fetchone()['total_income'] |
||||||
|
|
||||||
|
# 获取指定日期的可放映影片 |
||||||
|
def get_available_movie(self, date): |
||||||
|
start_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=6) |
||||||
|
end_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=29, minutes=59, |
||||||
|
seconds=59) |
||||||
|
self.cur.execute(GET_AVAILABLE_MOVIE, (start_datetime, end_datetime)) |
||||||
|
available_movie = self.cur.fetchall() |
||||||
|
available_movie_list = [ |
||||||
|
f"\t《{m['cinema_movie_alias']}》 - 影片id:{m['cinema_movie_id']},影片时长:{m['cinema_movie_time']},语言:{m['language']},制式:{m['media_type']}, 最早排片开始时间:{m['cinema_movie_start_datetime']}, 最晚排片截止时间:{m['cinema_movie_end_datetime']};" |
||||||
|
for m in available_movie] |
||||||
|
return '\n'.join(available_movie_list) |
||||||
|
|
||||||
|
# 获取新上映的影片 |
||||||
|
def get_new_movie(self, date): |
||||||
|
start_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') |
||||||
|
end_datetime = datetime.datetime.strptime(date, '%Y-%m-%d') + datetime.timedelta(hours=29, minutes=59, |
||||||
|
seconds=59) |
||||||
|
self.cur.execute(GET_NEW_MOVIE, (start_datetime, end_datetime)) |
||||||
|
new = self.cur.fetchall() |
||||||
|
new_list = [f"《{m['cinema_movie_alias']}》" for m in new] |
||||||
|
return new_list |
||||||
|
|
||||||
|
# 获取影厅支持的制式 |
||||||
|
def get_hall_media_type(self): |
||||||
|
self.cur.execute(GET_HALL_MEDIA_TYPE) |
||||||
|
hall_data = self.cur.fetchall() |
||||||
|
# print(hall_data) |
||||||
|
hall_dict = dict() |
||||||
|
|
||||||
|
# 处理成对应的字典格式 {"影厅别名": {"hall_id":影厅id,"media_type": 影片制式列表}} |
||||||
|
for hall in hall_data: |
||||||
|
if hall['cinema_hall_name'] not in hall_dict.keys(): |
||||||
|
hall_dict[hall['cinema_hall_name']] = { |
||||||
|
'hall_id': hall['cinema_hall_id'], |
||||||
|
'media_type': [hall['media_type'], ] |
||||||
|
} |
||||||
|
else: |
||||||
|
hall_dict[hall['cinema_hall_name']]['media_type'].append(hall['media_type']) |
||||||
|
# 拼装字符串 |
||||||
|
hall_str_list = [] |
||||||
|
for hall, val in hall_dict.items(): |
||||||
|
hall_str_list.append(f"\t{hall} - 影厅id:{val['hall_id']},支持制式:{','.join(val['media_type'])};") |
||||||
|
return '\n'.join(hall_str_list) |
||||||
|
|
||||||
|
# 获取模板日期 |
||||||
|
def get_template_date(self, start_datetime, end_datetime): |
||||||
|
basic_val = 4 |
||||||
|
self.cur.execute(GET_TEMPLATE_DATE, (start_datetime, end_datetime, basic_val)) |
||||||
|
template_date = self.cur.fetchall()[0]['template_date'] |
||||||
|
return template_date |
||||||
|
|
||||||
|
# 数据转csv格式字符串 |
||||||
|
@staticmethod |
||||||
|
def format_to_csv(dict_data, mapping): |
||||||
|
# print(dict_data) |
||||||
|
new_dict = [{mapping[k]: v for k, v in d.items()} for d in dict_data] |
||||||
|
return pd.DataFrame(new_dict).to_csv(index=False) |
||||||
|
|
||||||
|
def get_media_type(self): |
||||||
|
self.cur.execute(GET_HALL_MEDIA_TYPE) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
from main import cinema_list |
||||||
|
|
||||||
|
data = GetData(cinema_list[0]['db']) |
||||||
|
# print(data.get_show_data('2026-05-28 06:00:00', '2026-06-04 05:59:59')) |
||||||
|
# print(data.get_sell_data('2026-05-28 06:00:00', '2026-06-04 05:59:59')) |
||||||
|
# print(data.get_available_movie('2026-06-05')) |
||||||
|
print(data.get_new_movie('2026-06-05')) |
||||||
|
# print(data.get_hall_media_type()) |
||||||
|
# print(data.get_template_date('2026-05-28 06:00:00', '2026-06-04 05:59:59')) |
||||||
@ -0,0 +1,54 @@ |
|||||||
|
from ai.models import * |
||||||
|
from ai.utils.show_prompt import * |
||||||
|
import datetime |
||||||
|
from django_redis import get_redis_connection |
||||||
|
|
||||||
|
# ai排片主流程 |
||||||
|
def show_main_process(): |
||||||
|
# 查看状态 |
||||||
|
redis_conn = get_redis_connection() |
||||||
|
redis_key = f'ai_show{datetime.date.today().strftime("%Y%m%d")}' |
||||||
|
if redis_conn.exists(redis_key): |
||||||
|
return False |
||||||
|
# 获取影院列表 |
||||||
|
redis_conn.set(redis_key, 1, ex=60*60*20) |
||||||
|
test_cinema_list = TestCinema.objects.filter(is_active=True).all() |
||||||
|
# 生成目标日期 |
||||||
|
show_date = datetime.date.strftime(datetime.date.today() + datetime.timedelta(days=3), '%Y-%m-%d') |
||||||
|
for cinema in test_cinema_list: |
||||||
|
print(cinema.name) |
||||||
|
show_ai = ShowAI(cinema, show_date) |
||||||
|
prompt = show_ai.general_prompt() |
||||||
|
start = datetime.datetime.now() |
||||||
|
result, message, tokens = show_ai.get_show_result_ai() |
||||||
|
end = datetime.datetime.now() |
||||||
|
print('prompt:', prompt) |
||||||
|
print('result:', result) |
||||||
|
print('message:', message) |
||||||
|
print('tokens:', tokens) |
||||||
|
# 获取排片数据 |
||||||
|
_show = next((s for s in result.split('------') if s.startswith('\n影厅别名,影厅id')), '') |
||||||
|
_show = _show.strip() |
||||||
|
print('_show:', _show) |
||||||
|
# 获取销售额 |
||||||
|
_sales = next((s for s in result.split('\n') if s.startswith('预估销售数据')), '').replace('预估销售数据:', '') |
||||||
|
_sales = _sales.replace('约', '').replace('元', '') |
||||||
|
print('_sales:', _sales) |
||||||
|
# 处理返回结果 |
||||||
|
try: |
||||||
|
AiShow.objects.create( |
||||||
|
cinema=cinema.name, |
||||||
|
zz_code=cinema.zz_code, |
||||||
|
show_date=show_date, |
||||||
|
is_ai_show=True, |
||||||
|
show=_show, |
||||||
|
sales=_sales, |
||||||
|
prompt=prompt, |
||||||
|
result=result, |
||||||
|
message=message, |
||||||
|
take_times=int((end - start).seconds), |
||||||
|
take_tokens=tokens |
||||||
|
) |
||||||
|
except Exception as e: |
||||||
|
print(e) |
||||||
|
return True |
||||||
@ -0,0 +1,130 @@ |
|||||||
|
from django.db.models import Q |
||||||
|
from ai.models import PromptTemplate |
||||||
|
from ai.utils.show_database import GetData |
||||||
|
from ai.utils.datetime_format import (get_data_datetime, get_date_type) |
||||||
|
import datetime |
||||||
|
import random |
||||||
|
import json |
||||||
|
from openai import OpenAI |
||||||
|
|
||||||
|
|
||||||
|
class ShowAI: |
||||||
|
def __init__(self, cinema_info, show_date): |
||||||
|
self.cinema_name = cinema_info.name |
||||||
|
self.cinema_zz_code = cinema_info.zz_code |
||||||
|
self.cinema_db_config = json.loads(cinema_info.db_config) |
||||||
|
self.user_config = json.loads(cinema_info.user_config) |
||||||
|
self.show_date = show_date |
||||||
|
self.prompt = "" |
||||||
|
self.client = OpenAI( |
||||||
|
api_key='sk-b7993bf4c8844e79bf84f08f07ff86d9', |
||||||
|
base_url='https://api.deepseek.com', |
||||||
|
) |
||||||
|
|
||||||
|
# 生成提示词 |
||||||
|
def general_prompt(self): |
||||||
|
data = GetData(self.cinema_db_config) |
||||||
|
# 准备各种日期时间 |
||||||
|
history_start, history_end, target_start, target_end = get_data_datetime(self.show_date) |
||||||
|
temp = datetime.datetime.strftime(data.get_template_date(history_start, history_end), '%Y-%m-%d') |
||||||
|
history_date, target_date, target_date_is_holiday, template_date, template_date_is_holiday = get_date_type( |
||||||
|
self.show_date, temp) |
||||||
|
# print(history_start, history_end, target_start, target_end, history_date, show_date, template_date) |
||||||
|
|
||||||
|
# 开始处理提示词 |
||||||
|
prompt_list = [] |
||||||
|
# 处理排片数据 |
||||||
|
pre_data = PromptTemplate.objects.filter( |
||||||
|
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='PreData')).first().prompt_val # 获取提示词模板 |
||||||
|
pre_data = pre_data.replace('{history_show}', data.get_show_data(history_start, history_end)) # 处理排片数据 |
||||||
|
pre_data = pre_data.replace('{history_sales}', data.get_sell_data(history_start, history_end)) # 处理销售数据 |
||||||
|
pre_data = pre_data.replace('{target_already_show}', |
||||||
|
data.get_show_data(target_start, target_end)) # 处理目标日期已排场次数据 |
||||||
|
pre_data = pre_data.replace('{reference_date}', history_date) # 处理参考日期 |
||||||
|
pre_data = pre_data.replace('{template_date}', template_date) # 处理模板日期 |
||||||
|
pre_data = pre_data.replace('{target_date}', target_date) # 处理目标日期 |
||||||
|
prompt_list.append(pre_data) |
||||||
|
|
||||||
|
# 处理角色说明 |
||||||
|
role = PromptTemplate.objects.filter( |
||||||
|
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Role')).first().prompt_val # 获取提示词模板 |
||||||
|
role = role.replace('{template_date}', template_date) |
||||||
|
prompt_list.append(role) |
||||||
|
|
||||||
|
# 处理影片和影厅信息 |
||||||
|
movie_hall = PromptTemplate.objects.filter( |
||||||
|
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='MovieHall')).first().prompt_val # 获取提示词模板 |
||||||
|
movie_hall = movie_hall.replace('{available_movie}', data.get_available_movie(self.show_date)) # 处理可排影片 |
||||||
|
movie_hall = movie_hall.replace('{hall_info}', data.get_hall_media_type()) # 处理影厅信息 |
||||||
|
free_hall = self.user_config['holiday_date_free_hall'] if target_date_is_holiday else self.user_config[ |
||||||
|
'holiday_date_free_hall'] |
||||||
|
movie_hall = movie_hall.replace('{free_hall}', |
||||||
|
'\t无' if len(free_hall) == 0 else '\n'.join( |
||||||
|
f'\t{h};' for h in free_hall)) # 处理不可排片影厅 |
||||||
|
prompt_list.append(movie_hall) |
||||||
|
|
||||||
|
# 处理具体要求 |
||||||
|
rules = PromptTemplate.objects.filter( |
||||||
|
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Rules')).first().prompt_val # 获取提示词模板 |
||||||
|
rules = rules.replace('{template_date}', template_date) # 处理模板日期 |
||||||
|
# 获取新片 |
||||||
|
new_movie_str_list = [] |
||||||
|
new_movie = data.get_new_movie(self.show_date) |
||||||
|
for new in new_movie: |
||||||
|
new_movie_str_list.append( |
||||||
|
f"\t增加{new}的场次,建议排{str(random.randint(2, 4))}场,可根据影片热度和口碑适当增加;") |
||||||
|
rules = rules.replace('{new_movie}', |
||||||
|
'\t无新片上映' if len(new_movie_str_list) == 0 else '\n'.join(new_movie_str_list)) # 处理新片数据 |
||||||
|
prompt_list.append(rules) |
||||||
|
|
||||||
|
# 处理基本规则 |
||||||
|
basic = PromptTemplate.objects.filter( |
||||||
|
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Basic')).first().prompt_val # 获取提示词模板 |
||||||
|
start = self.user_config['holiday_date_start'] if target_date_is_holiday else self.user_config[ |
||||||
|
'work_date_start'] |
||||||
|
end = self.user_config['holiday_date_end'] if target_date_is_holiday else self.user_config['work_date_end'] |
||||||
|
basic = basic.replace('{start}', start) |
||||||
|
basic = basic.replace('{end}', end) |
||||||
|
prompt_list.append(basic) |
||||||
|
|
||||||
|
# 处理增减场次规则 |
||||||
|
add_reduce = PromptTemplate.objects.filter( |
||||||
|
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='AddReduce')).first().prompt_val # 获取提示词模板 |
||||||
|
prompt_list.append(add_reduce) |
||||||
|
|
||||||
|
# 处理黄金时段 |
||||||
|
prime_time = PromptTemplate.objects.filter( |
||||||
|
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='PrimeTime')).first().prompt_val # 获取提示词模板 |
||||||
|
prompt_list.append(prime_time) |
||||||
|
|
||||||
|
# 处理输出目标 |
||||||
|
output = PromptTemplate.objects.filter( |
||||||
|
Q(del_flag=False) & Q(prompt_type='show') & Q(prompt_key='Output')).first().prompt_val # 获取提示词模板 |
||||||
|
prompt_list.append(output) |
||||||
|
|
||||||
|
# 打印提示词 |
||||||
|
self.prompt = '\n'.join(prompt_list) |
||||||
|
print(self.prompt) |
||||||
|
# 关闭数据库连接 |
||||||
|
data.exit() |
||||||
|
return self.prompt |
||||||
|
|
||||||
|
# 请求AI |
||||||
|
def get_show_result_ai(self): |
||||||
|
# 生成提示词 |
||||||
|
# self.general_prompt() |
||||||
|
# 与DeepSeek开始对话 |
||||||
|
print("与DeepSeek开始对话") |
||||||
|
response = self.client.chat.completions.create( |
||||||
|
model='deepseek-v4-pro', |
||||||
|
messages=[ |
||||||
|
{'role': 'system', 'content': 'You are a helpful assistant'}, |
||||||
|
{'role': 'user', 'content': self.prompt}, |
||||||
|
], |
||||||
|
stream=False, |
||||||
|
reasoning_effort="high", |
||||||
|
extra_body={"thinking": {"type": "enabled"}} |
||||||
|
) |
||||||
|
# print(dict(response)) |
||||||
|
# print(response.choices[0].message.content) |
||||||
|
return response.choices[0].message.content, response.model_dump_json(), response.usage.model_dump_json() |
||||||
@ -0,0 +1,182 @@ |
|||||||
|
# 排片数据 |
||||||
|
GET_SHOW_DATA = """ |
||||||
|
SELECT hi.cinema_hall_name as hall_name, |
||||||
|
hi.cinema_hall_id as hall_id, |
||||||
|
mi.cinema_movie_alias as movie_name, |
||||||
|
mi.cinema_movie_id as movie_id, |
||||||
|
mlt.cinema_movie_lang_type_desc as language, |
||||||
|
DATE_FORMAT(ms.cinema_movie_show_start_time, '%%Y-%%m-%%d') as show_date, |
||||||
|
DATE_FORMAT(ms.cinema_movie_show_start_time, '%%H:%%i') as start_time, |
||||||
|
DATE_FORMAT(ms.cinema_movie_show_end_time, '%%H:%%i') as end_time, |
||||||
|
CAST(TIME_TO_SEC(TIMEDIFF(ms.cinema_movie_show_end_time, ms.cinema_movie_show_start_time)) / |
||||||
|
60 AS UNSIGNED) as length, |
||||||
|
IFNULL(MINUTE(TIMEDIFF(ms.cinema_movie_show_start_time, (SELECT MAX(cinema_movie_show_end_time) |
||||||
|
FROM cinema_movie_show t |
||||||
|
WHERE t.cinema_hall_id = ms.cinema_hall_id |
||||||
|
AND t.cinema_movie_show_start_date = ms.cinema_movie_show_start_date |
||||||
|
AND t.cinema_del_flag = 1 |
||||||
|
AND ms.cinema_movie_show_start_time >= t.cinema_movie_show_end_time))), |
||||||
|
0) as duration |
||||||
|
FROM cinema_movie_show ms |
||||||
|
LEFT JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id |
||||||
|
LEFT JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id |
||||||
|
LEFT JOIN cinema_movie_lang_type mlt ON mi.cinema_movie_lang_id = mlt.cinema_movie_lang_type_id |
||||||
|
WHERE ms.cinema_del_flag = 1 |
||||||
|
AND ms.cinema_movie_show_start_time >= %s |
||||||
|
AND ms.cinema_movie_show_start_time <= %s |
||||||
|
ORDER BY show_date, hall_id, start_time; |
||||||
|
""" |
||||||
|
|
||||||
|
# 获取销售数据 |
||||||
|
GET_SELL_DATA = """ |
||||||
|
SELECT md.movie_name, |
||||||
|
md.movie_id, |
||||||
|
md.show_date, |
||||||
|
md.start_time, |
||||||
|
md.hall_name, |
||||||
|
md.hall_id, |
||||||
|
SUM(md.count) as total_count, |
||||||
|
SUM(md.income) as total_income, |
||||||
|
md.seat_num, |
||||||
|
ROUND(IF(SUM(md.income) = 0, 0.0, SUM(md.income) / SUM(md.count)), 2) as average_price, |
||||||
|
ROUND(SUM(md.count) / md.seat_num * 100, 2) as rate |
||||||
|
FROM ( |
||||||
|
-- 售票 |
||||||
|
SELECT ms.cinema_movie_show_id as cinema_movie_show_id, |
||||||
|
mi.cinema_movie_alias as movie_name, |
||||||
|
mi.cinema_movie_id as movie_id, |
||||||
|
DATE_FORMAT(ms.cinema_movie_show_start_time, '%%Y-%%m-%%d') as show_date, |
||||||
|
CAST(TIME(ms.cinema_movie_show_start_time) AS CHAR) as start_time, |
||||||
|
hi.cinema_hall_name as hall_name, |
||||||
|
hi.cinema_hall_id as hall_id, |
||||||
|
SUM(IF(sl.cinema_ticket_status <> 3, 1, 0)) as count, |
||||||
|
SUM(IF(sl.cinema_ticket_status <> 3, sl.cinema_ticket_income, 0)) as income, |
||||||
|
ms.cinema_hall_seat_num as seat_num |
||||||
|
FROM cinema_movie_show ms |
||||||
|
LEFT JOIN cinema_sell_log sl ON ms.cinema_movie_show_id = sl.cinema_movie_show_id |
||||||
|
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id |
||||||
|
JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id |
||||||
|
WHERE ms.cinema_movie_show_joinflg = 0 |
||||||
|
AND ms.cinema_movie_show_start_time >= %s |
||||||
|
AND ms.cinema_movie_show_start_time <= %s |
||||||
|
AND ms.cinema_del_flag = 1 |
||||||
|
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1) |
||||||
|
GROUP BY ms.cinema_movie_show_id, CAST(ms.cinema_movie_show_id AS CHAR) |
||||||
|
UNION |
||||||
|
-- 补登 |
||||||
|
SELECT ms.cinema_movie_show_id as cinema_movie_show_id, |
||||||
|
mi.cinema_movie_alias as movie_name, |
||||||
|
mi.cinema_movie_id as movie_id, |
||||||
|
DATE_FORMAT(ms.cinema_movie_show_start_time, '%%Y-%%m-%%d') as show_date, |
||||||
|
CAST(TIME(ms.cinema_movie_show_start_time) AS CHAR) as start_time, |
||||||
|
hi.cinema_hall_name as hall_name, |
||||||
|
hi.cinema_hall_id as hall_id, |
||||||
|
SUM(sa.cinema_sell_add_num) as count, |
||||||
|
SUM(sa.cinema_sell_add_total) as income, |
||||||
|
ms.cinema_hall_seat_num as seat_num |
||||||
|
FROM cinema_sell_add sa |
||||||
|
LEFT JOIN cinema_movie_show ms ON sa.cinema_sell_add_showid = ms.cinema_movie_show_id |
||||||
|
LEFT JOIN cinema_hall_info hall ON ms.cinema_hall_id = hall.cinema_hall_id |
||||||
|
LEFT JOIN cinema_show_policy_map spm ON sa.cinema_sell_add_showid = spm.cinema_movie_show_id AND |
||||||
|
sa.cinema_sell_add_policy = spm.cinema_show_policy_map_id |
||||||
|
JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id |
||||||
|
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id |
||||||
|
WHERE ms.cinema_movie_show_joinflg = 0 |
||||||
|
AND ms.cinema_movie_show_start_time >= %s |
||||||
|
AND ms.cinema_movie_show_start_time <= %s |
||||||
|
AND ms.cinema_del_flag = 1 |
||||||
|
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1) |
||||||
|
GROUP BY ms.cinema_movie_show_id, CAST(ms.cinema_movie_show_id AS CHAR)) as md |
||||||
|
GROUP BY md.cinema_movie_show_id, CAST(md.cinema_movie_show_id AS CHAR) |
||||||
|
ORDER BY md.show_date, md.hall_id, md.start_time; |
||||||
|
""" |
||||||
|
|
||||||
|
# 获取指定日期的可放映影片 |
||||||
|
GET_AVAILABLE_MOVIE = """ |
||||||
|
SELECT cmi.cinema_movie_alias, |
||||||
|
cmi.cinema_movie_id, |
||||||
|
cmi.cinema_movie_time, |
||||||
|
cmlt.cinema_movie_lang_type_desc as language, |
||||||
|
scvm.system_const_val_desc as media_type, |
||||||
|
cmi.cinema_movie_start_datetime, |
||||||
|
cmi.cinema_movie_end_datetime |
||||||
|
FROM cinema_movie_info cmi |
||||||
|
JOIN cinema_movie_lang_type cmlt ON cmi.cinema_movie_lang_id = cmlt.cinema_movie_lang_type_id |
||||||
|
JOIN system_const_val_map scvm ON cmi.cinema_movie_media_type = scvm.system_const_val_value |
||||||
|
WHERE scvm.system_const_sub_module = 'new_media_type' |
||||||
|
AND cmi.cinema_movie_start_datetime <= %s |
||||||
|
AND cmi.cinema_movie_end_datetime > %s; |
||||||
|
""" |
||||||
|
|
||||||
|
# 获取新上映的影片 |
||||||
|
GET_NEW_MOVIE = """SELECT cmi.cinema_movie_alias, |
||||||
|
cmi.cinema_movie_id, |
||||||
|
cmi.cinema_movie_time, |
||||||
|
cmlt.cinema_movie_lang_type_desc as language, |
||||||
|
scvm.system_const_val_desc as media_type, |
||||||
|
cmi.cinema_movie_start_datetime, |
||||||
|
cmi.cinema_movie_end_datetime |
||||||
|
FROM cinema_movie_info cmi |
||||||
|
JOIN cinema_movie_lang_type cmlt ON cmi.cinema_movie_lang_id = cmlt.cinema_movie_lang_type_id |
||||||
|
JOIN system_const_val_map scvm ON cmi.cinema_movie_media_type = scvm.system_const_val_value |
||||||
|
WHERE scvm.system_const_sub_module = 'new_media_type' |
||||||
|
AND cmi.cinema_movie_start_datetime >= %s |
||||||
|
AND cmi.cinema_movie_start_datetime <= %s;""" |
||||||
|
|
||||||
|
# 获取影厅支持的制式 |
||||||
|
GET_HALL_MEDIA_TYPE = """ |
||||||
|
SELECT chi.cinema_hall_name, cms.cinema_hall_id, scvm.system_const_val_desc as media_type |
||||||
|
FROM cinema_movie_show cms |
||||||
|
JOIN cinema_movie_info cmi ON cms.cinema_movie_id = cmi.cinema_movie_id |
||||||
|
JOIN cinema_hall_info chi ON cms.cinema_hall_id = chi.cinema_hall_id |
||||||
|
JOIN system_const_val_map scvm ON cmi.cinema_movie_media_type = scvm.system_const_val_value |
||||||
|
WHERE scvm.system_const_sub_module = 'new_media_type' |
||||||
|
AND chi.cinema_delete_flag = 0 |
||||||
|
GROUP BY chi.cinema_hall_id, media_type; |
||||||
|
""" |
||||||
|
|
||||||
|
# 获取模板日期 |
||||||
|
GET_TEMPLATE_DATE = """ |
||||||
|
SELECT cms.cinema_movie_show_start_date as template_date, COUNT(cinema_movie_show_id) as show_count |
||||||
|
FROM cinema_movie_show cms |
||||||
|
WHERE cms.cinema_del_flag = 1 |
||||||
|
AND cms.cinema_movie_show_start_time >= %s |
||||||
|
AND cms.cinema_movie_show_start_time <= %s |
||||||
|
GROUP BY cms.cinema_movie_show_start_date |
||||||
|
HAVING show_count > (SELECT COUNT(chi.cinema_hall_id) FROM cinema_hall_info chi WHERE chi.cinema_delete_flag = 0) * %s |
||||||
|
ORDER BY template_date DESC |
||||||
|
LIMIT 1; |
||||||
|
""" |
||||||
|
|
||||||
|
|
||||||
|
# 获取目标日期的销售总额 |
||||||
|
GET_TOTAL_INCOME = """ |
||||||
|
SELECT SUM(md.income) as total_income |
||||||
|
FROM ( |
||||||
|
-- 售票 |
||||||
|
SELECT SUM(IF(sl.cinema_ticket_status <> 3, sl.cinema_ticket_income, 0)) as income |
||||||
|
FROM cinema_movie_show ms |
||||||
|
LEFT JOIN cinema_sell_log sl ON ms.cinema_movie_show_id = sl.cinema_movie_show_id |
||||||
|
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id |
||||||
|
JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id |
||||||
|
WHERE ms.cinema_movie_show_joinflg = 0 |
||||||
|
AND ms.cinema_movie_show_start_time >= %s |
||||||
|
AND ms.cinema_movie_show_start_time <= %s |
||||||
|
AND ms.cinema_del_flag = 1 |
||||||
|
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1) |
||||||
|
UNION |
||||||
|
-- 补登 |
||||||
|
SELECT SUM(sa.cinema_sell_add_total) as income |
||||||
|
FROM cinema_sell_add sa |
||||||
|
LEFT JOIN cinema_movie_show ms ON sa.cinema_sell_add_showid = ms.cinema_movie_show_id |
||||||
|
LEFT JOIN cinema_hall_info hall ON ms.cinema_hall_id = hall.cinema_hall_id |
||||||
|
LEFT JOIN cinema_show_policy_map spm ON sa.cinema_sell_add_showid = spm.cinema_movie_show_id AND |
||||||
|
sa.cinema_sell_add_policy = spm.cinema_show_policy_map_id |
||||||
|
JOIN cinema_hall_info hi ON ms.cinema_hall_id = hi.cinema_hall_id |
||||||
|
JOIN cinema_movie_info mi ON ms.cinema_movie_id = mi.cinema_movie_id |
||||||
|
WHERE ms.cinema_movie_show_joinflg = 0 |
||||||
|
AND ms.cinema_movie_show_start_time >= %s |
||||||
|
AND ms.cinema_movie_show_start_time <= %s |
||||||
|
AND ms.cinema_del_flag = 1 |
||||||
|
AND NOT (ms.cinema_movie_show_sold_num = 0 AND ms.cinema_movie_show_status <> 1)) md |
||||||
|
""" |
||||||
@ -0,0 +1,75 @@ |
|||||||
|
from django.http import JsonResponse |
||||||
|
from django.views.decorators.csrf import csrf_exempt |
||||||
|
from ai.models import * |
||||||
|
import datetime |
||||||
|
import json |
||||||
|
from ai.utils.show_database import GetData |
||||||
|
from ai.utils.show_process import show_main_process |
||||||
|
from django_redis import get_redis_connection |
||||||
|
|
||||||
|
|
||||||
|
# Create your views here. |
||||||
|
|
||||||
|
|
||||||
|
# 手动触发ai排片 |
||||||
|
@csrf_exempt |
||||||
|
def manual_general_show(request): |
||||||
|
result = show_main_process() |
||||||
|
result_dict = { |
||||||
|
'status': 'success' if result else 'fail', |
||||||
|
'message': '生成成功' if result else '生成失败', |
||||||
|
} |
||||||
|
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False}) |
||||||
|
|
||||||
|
|
||||||
|
# 更新指定日期的排片 |
||||||
|
@csrf_exempt |
||||||
|
def get_cinema_show_result(request): |
||||||
|
zz_code = request.GET.dict().get('cinema_code') |
||||||
|
show_date = request.GET.dict().get('show_date') |
||||||
|
print(zz_code, show_date) |
||||||
|
cinema = TestCinema.objects.filter(zz_code=zz_code).first() |
||||||
|
start = datetime.datetime.strftime(datetime.datetime.strptime(show_date, '%Y-%m-%d') + datetime.timedelta(hours=6), |
||||||
|
'%Y-%m-%d %H:%M:%S') |
||||||
|
end = datetime.datetime.strftime( |
||||||
|
datetime.datetime.strptime(show_date, '%Y-%m-%d') + datetime.timedelta(hours=29, minutes=59, seconds=59), |
||||||
|
'%Y-%m-%d %H:%M:%S') |
||||||
|
if cinema: |
||||||
|
data = GetData(json.loads(cinema.db_config)) |
||||||
|
show = data.get_show_data(start, end) |
||||||
|
income = data.get_total_income(start, end) |
||||||
|
try: |
||||||
|
AiShow.objects.create( |
||||||
|
cinema=cinema.name, |
||||||
|
zz_code=cinema.zz_code, |
||||||
|
show_date=show_date, |
||||||
|
is_ai_show=False, |
||||||
|
show=show, |
||||||
|
sales=income, |
||||||
|
prompt='', |
||||||
|
result='', |
||||||
|
message='', |
||||||
|
take_time=0, |
||||||
|
take_tokens='0' |
||||||
|
) |
||||||
|
except Exception as e: |
||||||
|
print(e) |
||||||
|
result_dict = { |
||||||
|
'status': 'success', |
||||||
|
'message': '生成成功', |
||||||
|
} |
||||||
|
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False}) |
||||||
|
|
||||||
|
|
||||||
|
# 清除redis锁 |
||||||
|
@csrf_exempt |
||||||
|
def clear_lock(request): |
||||||
|
redis_conn = get_redis_connection() |
||||||
|
redis_key = f'ai_show{datetime.date.today().strftime("%Y%m%d")}' |
||||||
|
if redis_conn.exists(redis_key): |
||||||
|
redis_conn.delete(redis_key) |
||||||
|
result_dict = { |
||||||
|
'status': 'success', |
||||||
|
'message': '完成', |
||||||
|
} |
||||||
|
return JsonResponse(result_dict, json_dumps_params={'ensure_ascii': False}) |
||||||
Binary file not shown.
@ -0,0 +1,18 @@ |
|||||||
|
# Generated by Django 4.2.7 on 2026-05-15 03:15 |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('update', '0033_alter_clientrelease_md5'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.AddField( |
||||||
|
model_name='cinema', |
||||||
|
name='url', |
||||||
|
field=models.CharField(default=models.CharField(help_text='影院ip', max_length=20, verbose_name='影院ip'), help_text='影院url', max_length=50, verbose_name='影院url'), |
||||||
|
), |
||||||
|
] |
||||||
Loading…
Reference in new issue