ai_admin/WebAdmin/models.py

235 lines
13 KiB
Python
Raw Permalink Normal View History

2024-09-20 12:29:09 +08:00
from datetime import datetime, timedelta
import random
import string
from django.contrib.auth.models import AbstractUser
from django.db import models
from datetime import datetime
def generate_unique_referral_code():
while True:
referral_code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=8))
if not User.objects.filter(referral_code=referral_code).exists():
return referral_code
class User(AbstractUser):
phone = models.CharField(max_length=20, unique=True, null=True, blank=True) # 手机号,唯一,可以为空
google_id = models.CharField(max_length=50, unique=True, null=True, blank=True) # Google ID唯一可以为空
is_member = models.BooleanField(default=False) # 是否是会员
points = models.IntegerField(default=0) # 用户积分
invited_by = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='invitees') # 邀请人
referral_code = models.CharField(max_length=50, unique=True) # 推荐码,唯一
commission_rate = models.DecimalField(max_digits=5, decimal_places=2, default=0.00) # 返佣比例
created_at = models.DateTimeField(default=datetime.now) # 创建时间
updated_at = models.DateTimeField(auto_now=True) # 更新时间
login_count = models.IntegerField(default=0) # 登录次数
last_login_ip = models.GenericIPAddressField(null=True, blank=True) # 最后登录IP
membership_start = models.DateTimeField(null=True, blank=True) # 会员开始时间
membership_end = models.DateTimeField(null=True, blank=True) # 会员到期时间
openid_used = models.CharField(max_length=150, null=True, blank=True, unique=True) # 已用的 openid确保每个 openid 只能使用一次
source = models.CharField(max_length=50, default='web') # 用户来源,默认为 'web'
def save(self, *args, **kwargs):
if not self.referral_code:
self.referral_code = generate_unique_referral_code()
super().save(*args, **kwargs)
def __str__(self):
return self.username
class Referral(models.Model):
referrer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='referrals_made') # 邀请人ID外键引用User模型
referee = models.ForeignKey(User, on_delete=models.CASCADE, related_name='referrals_received') # 被邀请人ID外键引用User模型
commission_amount = models.DecimalField(max_digits=10, decimal_places=2) # 返佣金额最大值为99999999.99
created_at = models.DateTimeField(default=datetime.now) # 创建时间,默认当前时间
def __str__(self):
return f'{self.referrer} invited {self.referee}'
class UserSource(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE) # 用户ID外键引用User模型
source = models.CharField(max_length=50) # 用户来源最大长度50
created_at = models.DateTimeField(default=datetime.now) # 创建时间,默认当前时间
def __str__(self):
return f'{self.user} - {self.source}'
class SMSVerificationCode(models.Model):
phone_number = models.CharField(max_length=15) # 手机号
code = models.CharField(max_length=6) # 验证码
created_at = models.DateTimeField(auto_now_add=True) # 创建时间,自动设置为当前时间
is_used = models.BooleanField(default=False) # 是否已使用
def is_expired(self):
return self.created_at < datetime.now() - timedelta(minutes=5) # 判断验证码是否已过期
def __str__(self):
return f"{self.phone_number} - {self.code}"
class EmailVerificationCode(models.Model):
email = models.EmailField() # 邮箱地址
code = models.CharField(max_length=6) # 验证码
created_at = models.DateTimeField(auto_now_add=True) # 创建时间,自动设置为当前时间
is_used = models.BooleanField(default=False) # 是否已使用
def is_expired(self):
return self.created_at < datetime.now() - timedelta(minutes=5) # 判断验证码是否已过期
def __str__(self):
return f"{self.email} - {self.code}"
class VideoGeneration(models.Model):
STATUS_CHOICES = [
('pending', 'Pending'),
('in_progress', 'In Progress'),
('completed', 'Completed'),
('failed', 'Failed'),
]
video_id = models.CharField(max_length=255, unique=True, default='')
user = models.ForeignKey(User, on_delete=models.CASCADE) # 生成请求的用户
text = models.TextField(null=True) # 输入文本
voice_name = models.CharField(max_length=50, null=True) # 选择的语音
style = models.CharField(max_length=50, default='general', null=True) # 语音风格
rate = models.IntegerField(default=0, null=True) # 语速
media_type = models.CharField(max_length=50, null=True) # 媒体类型
ratio = models.CharField(max_length=10) # 视频比例
audio_url = models.URLField(null=True, blank=True) # 生成的音频URL
video_url = models.URLField(null=True, blank=True) # 生成的视频URL
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending') # 生成状态
created_at = models.DateTimeField(default=datetime.now) # 创建时间
updated_at = models.DateTimeField(auto_now=True) # 更新时间
slug = models.CharField(max_length=50) # 生成视频的类型
pid = models.CharField(max_length=50, null=True, default='') # 生成视频的ID
extension_count = models.IntegerField(default=0) # 延长次数最多3次
time_duration = models.IntegerField(default=0) # 生成时长
def __str__(self):
return f'{self.video_id} - {self.user.username} - {self.status} - {self.created_at}'
class Plan(models.Model):
"""
存放套餐信息的数据库模型
"""
title = models.CharField(max_length=100, unique=True) # 套餐标题,标识套餐的名称(如 HOBBY、GROWTH、GROWTH PLUS
description = models.TextField() # 套餐描述,详细说明套餐中包含的所有功能和服务
price = models.DecimalField(max_digits=10, decimal_places=2) # 套餐价格,表示套餐的费用,保留两位小数
credits_per_month = models.IntegerField(default=0) # 每月积分,套餐中包含的每月 AI 积分数
created_at = models.DateTimeField(default=datetime.now) # 创建时间,记录套餐的创建时间
updated_at = models.DateTimeField(auto_now=True) # 更新时间,记录套餐信息的最后更新时间
is_promotional = models.BooleanField(default=False) # 是否为促销活动,用于标识该套餐是否属于促销套餐
unlimited_exports = models.BooleanField(default=False) # 是否允许无限导出功能,适用于一些高级套餐
smart_music_sync = models.BooleanField(default=False) # 是否包含智能音乐同步功能,用于标识该套餐是否包含此项服务
def __str__(self):
return self.title
class Order(models.Model):
PAYMENT_METHOD_CHOICES = [
('alipay', 'Alipay'),
('paypal', 'PayPal'),
]
ORDER_STATUS_CHOICES = [
('pending', 'Pending'),
('completed', 'Completed'),
('canceled', 'Canceled'),
('failed', 'Failed'),
]
order_id = models.CharField(max_length=100, unique=True) # 订单唯一标识符
user = models.ForeignKey('User', on_delete=models.CASCADE) # 用户外键
username = models.CharField(max_length=150) # 用户名(邮箱或手机号)
plan = models.ForeignKey('Plan', on_delete=models.CASCADE) # 关联套餐
amount = models.DecimalField(max_digits=10, decimal_places=2,default=0.00) # 订单金额
payment_method = models.CharField(max_length=10, choices=PAYMENT_METHOD_CHOICES) # 支付方式
status = models.CharField(max_length=10, choices=ORDER_STATUS_CHOICES, default='pending') # 订单状态
created_at = models.DateTimeField(default=datetime.now) # 创建时间
updated_at = models.DateTimeField(auto_now=True) # 更新时间
def __str__(self):
return f"Order {self.order_id} - {self.status}"
class Meta:
verbose_name = 'Order'
verbose_name_plural = 'Orders'
ordering = ['-created_at']
class TransactionHistory(models.Model):
"""
记录用户的积分消费明细
"""
FEATURE_CHOICES = [
('text-to-video', 'AI文生视频'),
('img-to-video', 'AI图生视频'),
('create-tiktok-video', 'AI长视频生成'),
('music-to-video', '音乐视频生成'),
('create-avatar-video', '虚拟形象视频生成'),
]
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='transactions', verbose_name='用户') # 关联用户
feature = models.CharField(max_length=50, choices=FEATURE_CHOICES, verbose_name='功能类型') # 功能类型
points_spent = models.IntegerField(verbose_name='消费积分') # 消费的积分数量
char_count = models.IntegerField(blank=True, null=True, verbose_name='字符数量') # 记录字符数量(如果是文本相关的功能)
description = models.TextField(blank=True, null=True, verbose_name='操作描述') # 记录操作的详细描述
transaction_date = models.DateTimeField(default=datetime.now, verbose_name='消费时间') # 消费时间
previous_points_balance = models.IntegerField(verbose_name='消费前积分') # 用户消费前的积分余额
new_points_balance = models.IntegerField(verbose_name='消费后积分') # 用户消费后的积分余额
success = models.BooleanField(default=True, verbose_name='是否成功') # 记录是否成功扣费
class Meta:
db_table = 'transaction_history'
verbose_name = '消费明细'
verbose_name_plural = '消费明细'
ordering = ['-transaction_date'] # 按消费时间倒序排列
def __str__(self):
return f'用户 {self.user.username} 消费 {self.points_spent} 积分 ({self.feature})'
class WebsiteInfo(models.Model):
"""
用于存储网站的域名标题关键词和描述包括中英文版本
"""
domain_en = models.CharField(max_length=255,default=True, verbose_name='域名') # 网站域名
domain_zh = models.CharField(max_length=255,default=True, verbose_name='域名') # 网站域名
title_en = models.CharField(max_length=255,default=True, verbose_name='英文标题') # 英文标题
title_zh = models.CharField(max_length=255,default=True, verbose_name='中文标题') # 中文标题
keywords_en = models.TextField(verbose_name='英文关键词',default=True) # 英文关键词
keywords_zh = models.TextField(verbose_name='中文关键词',default=True) # 中文关键词
description_en = models.TextField(verbose_name='英文描述',default=True) # 英文描述
description_zh = models.TextField(verbose_name='中文描述',default=True) # 中文描述
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') # 创建时间
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') # 更新时间
class Meta:
db_table = 'website_info'
verbose_name = '网站信息'
verbose_name_plural = '网站信息'
ordering = ['-created_at'] # 按照创建时间倒序排列
class WebsiteAccessLog(models.Model):
"""
用于记录网站访问的IP浏览器语言来源URL请求路径访问时间等信息
"""
ip_address = models.GenericIPAddressField(verbose_name='访问IP')
browser_language = models.CharField(max_length=200, verbose_name='浏览器语言', blank=True, null=True)
referrer = models.TextField(verbose_name='来源URL', blank=True, null=True)
request_path = models.CharField(max_length=255, verbose_name='请求路径')
request_method = models.CharField(max_length=10, verbose_name='请求方法')
user_agent = models.TextField(verbose_name='用户代理', blank=True, null=True)
device_type = models.CharField(max_length=50, verbose_name='设备类型', blank=True, null=True)
access_time = models.DateTimeField(verbose_name='访问时间', auto_now_add=True)
access_time_bj = models.DateTimeField(verbose_name='北京时间', blank=True, null=True)
access_date = models.DateField(verbose_name='访问日期', blank=True, null=True)
class Meta:
db_table = 'website_access_log'
verbose_name = '网站访问日志'
verbose_name_plural = '网站访问日志'
unique_together = ('ip_address', 'access_date') # 确保同一IP在同一天只能记录一次
def __str__(self):
access_time_str = self.access_time_bj.strftime('%Y-%m-%d %H:%M:%S') if self.access_time_bj else 'N/A'
return f"{self.ip_address} - {access_time_str}"