Compare commits

...

2 Commits

Author SHA1 Message Date
jlj
83f8dd931e 合并 2025-05-20 12:40:54 +08:00
jlj
c6dbda5a88 添加部分token 2025-05-20 12:24:53 +08:00
13 changed files with 551 additions and 332 deletions

View File

@ -1373,7 +1373,6 @@ def get_creator_trends(request, creator_id=None):
(datetime.now().date() - timedelta(days=30 - i)).strftime('%Y-%m-%d')
for i in range(31)
]
# 设定随机的起始值和波动
import random
base_gmv = random.uniform(500, 3000)

View File

@ -0,0 +1,29 @@
# Generated by Django 5.1.5 on 2025-05-20 04:36
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('brands', '0002_alter_campaign_id'),
('daren_detail', '0001_initial'),
('expertproducts', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='negotiation',
name='creator',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='daren_detail.creatorprofile'),
),
migrations.AlterField(
model_name='negotiation',
name='product',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='brands.product'),
),
migrations.DeleteModel(
name='Creator',
),
]

View File

@ -0,0 +1,16 @@
# Generated by Django 5.1.5 on 2025-05-20 04:37
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('expertproducts', '0002_alter_negotiation_creator_alter_negotiation_product_and_more'),
]
operations = [
migrations.DeleteModel(
name='Product',
),
]

View File

@ -1,28 +1,12 @@
from django.db import models
from django.db.models import JSONField # 用于存储动态谈判条款
from django.utils import timezone # Import timezone for timestamping
from apps.daren_detail.models import CreatorProfile # 导入CreatorProfile模型
from apps.brands.models import Product # 导入Product模型
# Create your models here.
class Product(models.Model):
name = models.CharField(max_length=100) # 商品名称
category = models.CharField(max_length=50) # 商品类目
max_price = models.DecimalField(max_digits=10, decimal_places=2) # 最高价格(公开报价)
min_price = models.DecimalField(max_digits=10, decimal_places=2) # 最低价格(底线)
description = models.TextField(blank=True) # 商品描述(可选)
def __str__(self):
return f"{self.name} ({self.max_price}元)"
class Creator(models.Model):
name = models.CharField(max_length=100) # 达人名称
sex = models.CharField(max_length=10, default='') # 达人性别,设置默认值为未知
age = models.IntegerField(default=18) # 达人年龄设置默认值为18
category = models.CharField(max_length=50) # 达人类别(如带货类)
followers = models.IntegerField() # 粉丝数
class Negotiation(models.Model):
STATUS_CHOICES = [
('brand_review', '品牌回顾'),
@ -34,8 +18,8 @@ class Negotiation(models.Model):
('abandoned', '已放弃'),
]
creator = models.ForeignKey('daren_detail.CreatorProfile', on_delete=models.CASCADE)
product = models.ForeignKey('brands.Product', on_delete=models.CASCADE)
creator = models.ForeignKey(CreatorProfile, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='price_negotiation')
current_round = models.IntegerField(default=1) # 当前谈判轮次
context = models.JSONField(default=dict) # 存储谈判上下文(如当前报价)

View File

@ -2,8 +2,9 @@ from rest_framework import serializers
# from user_management.models import OperatorAccount, PlatformAccount, Video, KnowledgeBase, KnowledgeBaseDocument
import uuid
from django.db.models import Q
from .models import Product, Creator, Negotiation, Message
from apps.daren_detail.models import CreatorProfile
from apps.brands.models import Product
from .models import Negotiation, Message
#
# class OperatorAccountSerializer(serializers.ModelSerializer):
@ -155,16 +156,15 @@ class ProductSerializer(serializers.ModelSerializer):
fields = '__all__'
class CreatorSerializer(serializers.ModelSerializer):
class Meta:
model = Creator
fields = '__all__'
class NegotiationSerializer(serializers.ModelSerializer):
creator_name = serializers.CharField(source='creator.name', read_only=True)
creator_avatar = serializers.CharField(source='creator.avatar_url', read_only=True)
product_name = serializers.CharField(source='product.name', read_only=True)
product_category = serializers.CharField(source='product.category', read_only=True)
class Meta:
model = Negotiation
fields = '__all__'
fields = ['id', 'creator', 'creator_name', 'creator_avatar', 'product', 'product_name', 'product_category', 'status', 'current_round', 'context']
read_only_fields = ('status', 'current_round')

View File

@ -17,15 +17,16 @@ import subprocess
import re
from django.db import connection
from django.core.mail import EmailMessage
from ollama import Client
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from .models import Product, Creator, Negotiation, Message
from .serializers import ProductSerializer, CreatorSerializer, NegotiationSerializer
import requests
from ollama import Client
from .models import Product, Negotiation, Message
from .serializers import NegotiationSerializer
from apps.daren_detail.models import CreatorProfile
from apps.brands.models import Product
client = Client(host="http://localhost:11434")
class ContentAnalysisAPI(APIView):
parser_classes = (MultiPartParser, FormParser)
@ -172,7 +173,7 @@ class NegotiationViewSet(viewsets.ModelViewSet):
product = serializer.validated_data['product']
# 检查该用户是否存在
if not Creator.objects.filter(id=creator.id).exists():
if not CreatorProfile.objects.filter(id=creator.id).exists():
return Response({
"code": 404,
"message": "未找到指定的达人",
@ -346,7 +347,7 @@ class NegotiationViewSet(viewsets.ModelViewSet):
})
# 获取所有相关的达人
creators = Creator.objects.filter(negotiation__in=negotiations).distinct()
creators = CreatorProfile.objects.filter(negotiation__in=negotiations).distinct()
if creators.exists():
# 序列化达人数据
creator_data = [{'name': creator.name, 'category': creator.category, 'followers': creator.followers} for
@ -362,6 +363,7 @@ class NegotiationViewSet(viewsets.ModelViewSet):
@action(detail=False, methods=['post'])
def offer_status(self, request):
"""获取谈判状态"""
# 获取请求参数
creator_id = request.data.get('creator_id')
product_id = request.data.get('product_id')
@ -374,7 +376,7 @@ class NegotiationViewSet(viewsets.ModelViewSet):
# 查找符合条件的谈判
try:
creator = Creator.objects.get(id=creator_id)
creator = CreatorProfile.objects.get(id=creator_id)
negotiation = Negotiation.objects.get(creator=creator, product_id=product_id)
return Response({
'code': 200,
@ -383,6 +385,12 @@ class NegotiationViewSet(viewsets.ModelViewSet):
'status': negotiation.status
}
})
except CreatorProfile.DoesNotExist:
return Response({
'code': 404,
'message': f'找不到ID为{creator_id}的达人',
'data': None
})
except Negotiation.DoesNotExist:
return Response({
'code': 404,

View File

@ -0,0 +1,42 @@
from rest_framework import authentication
from rest_framework import exceptions
from django.contrib.auth.models import AnonymousUser
from .models import User, UserToken
from django.utils import timezone
class CustomTokenAuthentication(authentication.BaseAuthentication):
keyword = 'Token' # 设置认证头关键字
def authenticate(self, request):
# 从请求头获取token
auth_header = request.META.get('HTTP_AUTHORIZATION')
if not auth_header:
return None
try:
# 提取token
parts = auth_header.split()
if len(parts) != 2 or parts[0] != self.keyword:
raise exceptions.AuthenticationFailed('无效的认证头格式,应为: Token <token>')
token = parts[1]
# 查找token记录并确保token存在且有效
try:
token_obj = UserToken.objects.select_related('user').get(
token=token,
expired_at__gt=timezone.now() # 确保token未过期
)
except UserToken.DoesNotExist:
raise exceptions.AuthenticationFailed('无效的token')
# 检查用户是否激活
if not token_obj.user.is_active:
raise exceptions.AuthenticationFailed('用户已被禁用')
return (token_obj.user, None)
except Exception as e:
raise exceptions.AuthenticationFailed(f'认证失败: {str(e)}')

View File

@ -0,0 +1,27 @@
# Generated by Django 5.1.5 on 2025-05-20 03:49
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('user', '0002_remove_user_is_active'),
]
operations = [
migrations.CreateModel(
name='UserToken',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('token', models.CharField(max_length=40, unique=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('expired_at', models.DateTimeField()),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tokens', to='user.user')),
],
options={
'db_table': 'user_token',
},
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 5.1.5 on 2025-05-20 03:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('user', '0003_usertoken'),
]
operations = [
migrations.AddField(
model_name='user',
name='is_active',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='user',
name='is_staff',
field=models.BooleanField(default=False),
),
]

View File

@ -1,23 +1,65 @@
from django.db import models
# Create your models here.
class User(models.Model):
"""用户模型,用于登录和账户管理"""
email = models.EmailField(max_length=255, unique=True, verbose_name="电子邮箱")
password = models.CharField(max_length=255, verbose_name="密码")
company = models.CharField(max_length=255, blank=True, null=True, verbose_name="公司名称")
name = models.CharField(max_length=255, blank=True, null=True, verbose_name="用户姓名")
is_first_login = models.BooleanField(default=True, verbose_name="是否首次登录")
last_login = models.DateTimeField(blank=True, null=True, verbose_name="最近登录时间")
# 时间戳
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
class Meta:
verbose_name = "用户"
verbose_name_plural = verbose_name
db_table = "users"
def __str__(self):
return self.email
from django.db import models
from django.utils import timezone
from datetime import timedelta
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('邮箱地址不能为空')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
if password:
user.set_password(password)
user.save(using=self._db)
return user
class User(AbstractBaseUser):
"""用户模型,用于登录和账户管理"""
email = models.EmailField(max_length=255, unique=True, verbose_name="电子邮箱")
password = models.CharField(max_length=255, verbose_name="密码")
company = models.CharField(max_length=255, blank=True, null=True, verbose_name="公司名称")
name = models.CharField(max_length=255, blank=True, null=True, verbose_name="用户姓名")
is_first_login = models.BooleanField(default=True, verbose_name="是否首次登录")
last_login = models.DateTimeField(blank=True, null=True, verbose_name="最近登录时间")
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
# 时间戳
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = "用户"
verbose_name_plural = verbose_name
db_table = "users"
def __str__(self):
return self.email
@property
def is_authenticated(self):
return True
class UserToken(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tokens')
token = models.CharField(max_length=40, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
expired_at = models.DateTimeField()
def save(self, *args, **kwargs):
if not self.expired_at:
# 设置token有效期为30天
self.expired_at = timezone.now() + timedelta(days=30)
super().save(*args, **kwargs)
def is_expired(self):
return timezone.now() > self.expired_at
class Meta:
db_table = 'user_token'

View File

@ -1,268 +1,281 @@
from django.http import JsonResponse
# from .models import TiktokUserVideos
import logging
import os
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render
import json
import requests
import concurrent.futures
import shutil
import dotenv
import random
dotenv.load_dotenv()
# 添加logger定义
logger = logging.getLogger(__name__)
directory_monitoring = {}
# 全局变量来控制检测线程
monitor_thread = None
is_monitoring = False
@csrf_exempt
@require_http_methods(["POST"])
def user_login(request):
"""用户登录接口,首次登录会返回需要填写信息的标志"""
try:
from .models import User
import json
from django.contrib.auth.hashers import check_password, make_password
from datetime import datetime
data = json.loads(request.body)
# 获取登录参数
email = data.get('email')
password = data.get('password')
if not email or not password:
return JsonResponse({
'code': 400,
'message': '缺少必要参数: email 或 password',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 查询用户
try:
user = User.objects.get(email=email)
# 验证密码
# 注意:这里假设密码已经进行了哈希存储,实际使用时需要采用适当的密码验证方法
# 如果密码未哈希存储,直接比较原始密码
password_valid = (user.password == password)
if not password_valid:
return JsonResponse({
'code': 401,
'message': '用户名或密码错误',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 检查是否首次登录
is_first_login = user.is_first_login
# 更新最后登录时间
user.last_login = datetime.now()
user.save()
# 构造返回数据
user_data = {
'user_id': user.id,
'email': user.email,
'is_first_login': is_first_login,
'name': user.name,
'company': user.company
}
return JsonResponse({
'code': 200,
'message': '登录成功',
'data': user_data
}, json_dumps_params={'ensure_ascii': False})
except User.DoesNotExist:
# 用户不存在,创建新用户
new_user = User.objects.create(
email=email,
password=password, # 注意:实际使用时应该哈希存储密码
is_first_login=True,
last_login=datetime.now()
)
return JsonResponse({
'code': 200,
'message': '登录成功',
'data': {
'user_id': new_user.id,
'email': new_user.email,
'is_first_login': True,
'name': None,
'company': None
}
}, json_dumps_params={'ensure_ascii': False})
except Exception as e:
logger.error(f"用户登录失败: {e}")
import traceback
logger.error(f"详细错误: {traceback.format_exc()}")
return JsonResponse({
'code': 500,
'message': f'登录失败: {str(e)}',
'data': None
}, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
@require_http_methods(["POST"])
def update_user_info(request):
"""更新用户信息,首次登录时填写公司和姓名"""
try:
from .models import User
import json
data = json.loads(request.body)
# 获取参数
user_id = data.get('user_id')
company = data.get('company')
name = data.get('name')
if not user_id:
return JsonResponse({
'code': 400,
'message': '缺少必要参数: user_id',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 如果是首次登录,需要填写公司和姓名
if not company or not name:
return JsonResponse({
'code': 400,
'message': '首次登录需要填写公司和姓名',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 查询用户并更新信息
try:
user = User.objects.get(id=user_id)
# 更新信息
user.company = company
user.name = name
user.is_first_login = False # 更新后不再是首次登录
user.save()
return JsonResponse({
'code': 200,
'message': '信息更新成功',
'data': {
'user_id': user.id,
'email': user.email,
'is_first_login': False,
'name': user.name,
'company': user.company
}
}, json_dumps_params={'ensure_ascii': False})
except User.DoesNotExist:
return JsonResponse({
'code': 404,
'message': f'找不到ID为 {user_id} 的用户',
'data': None
}, json_dumps_params={'ensure_ascii': False})
except Exception as e:
logger.error(f"更新用户信息失败: {e}")
import traceback
logger.error(f"详细错误: {traceback.format_exc()}")
return JsonResponse({
'code': 500,
'message': f'更新用户信息失败: {str(e)}',
'data': None
}, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
@require_http_methods(["POST"])
def user_register(request):
"""用户注册接口,允许用户创建新账户,可选填写公司和姓名"""
try:
from .models import User
import json
from datetime import datetime
data = json.loads(request.body)
# 获取注册参数
email = data.get('email')
password = data.get('password')
company = data.get('company') # 可选参数
name = data.get('name') # 可选参数
# 检查必要参数
if not email or not password:
return JsonResponse({
'code': 400,
'message': '缺少必要参数: email 或 password',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 检查邮箱是否已注册
if User.objects.filter(email=email).exists():
return JsonResponse({
'code': 409,
'message': '该邮箱已注册',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 创建用户
try:
# 根据是否提供公司和姓名决定是否为首次登录
is_first_login = not (company and name)
# 创建用户
user = User.objects.create(
email=email,
password=password, # 注意:实际使用时应该哈希存储密码
company=company,
name=name,
is_first_login=is_first_login,
last_login=datetime.now()
)
# 构造返回数据
user_data = {
'user_id': user.id,
'email': user.email,
'is_first_login': is_first_login,
'company': user.company,
'name': user.name
}
return JsonResponse({
'code': 200,
'message': '注册成功',
'data': user_data
}, json_dumps_params={'ensure_ascii': False})
except Exception as e:
logger.error(f"创建用户失败: {e}")
return JsonResponse({
'code': 500,
'message': f'注册失败: {str(e)}',
'data': None
}, json_dumps_params={'ensure_ascii': False})
except Exception as e:
logger.error(f"用户注册失败: {e}")
import traceback
logger.error(f"详细错误: {traceback.format_exc()}")
return JsonResponse({
'code': 500,
'message': f'注册失败: {str(e)}',
'data': None
}, json_dumps_params={'ensure_ascii': False})
from django.http import JsonResponse
# from .models import TiktokUserVideos
import logging
import os
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render
import json
import requests
import concurrent.futures
import shutil
import dotenv
import random
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated, AllowAny
import hashlib
import time
from django.contrib.auth.hashers import check_password
from django.utils import timezone
dotenv.load_dotenv()
# 添加logger定义
logger = logging.getLogger(__name__)
directory_monitoring = {}
# 全局变量来控制检测线程
monitor_thread = None
is_monitoring = False
def generate_token(user_id):
"""生成简单的token"""
# 使用用户ID和当前时间戳生成token
token_string = f"{user_id}:{time.time()}"
return hashlib.sha1(token_string.encode()).hexdigest()
def create_user_token(user):
"""创建并保存用户token"""
from .models import UserToken
# 删除该用户的所有旧token
UserToken.objects.filter(user=user).delete()
# 生成新token
token = generate_token(user.id)
# 保存到数据库
user_token = UserToken.objects.create(
user=user,
token=token
)
return token
@csrf_exempt
@api_view(['POST'])
@permission_classes([AllowAny])
def user_login(request):
"""
用户登录接口
返回的 token 使用格式
在请求头中添加
Authorization: Token <your_token>
例如
Authorization: Token fa6931ec4cf5bd46d8dc3a671fe9862c467426b3
"""
try:
from .models import User
import json
from django.contrib.auth.hashers import check_password
from datetime import datetime
data = json.loads(request.body)
# 获取登录参数
email = data.get('email')
password = data.get('password')
if not email or not password:
return JsonResponse({
'code': 400,
'message': '缺少必要参数: email 或 password',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 查询用户
try:
user = User.objects.get(email=email)
# 验证密码
if not user.check_password(password):
return JsonResponse({
'code': 401,
'message': '用户名或密码错误',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 生成并保存token
token = create_user_token(user)
# 检查是否首次登录
is_first_login = user.is_first_login
# 更新最后登录时间
user.last_login = timezone.now()
user.save()
# 构造返回数据
user_data = {
'user_id': user.id,
'email': user.email,
'is_first_login': is_first_login,
'name': user.name,
'company': user.company,
'token': token
}
return JsonResponse({
'code': 200,
'message': '登录成功',
'data': user_data
}, json_dumps_params={'ensure_ascii': False})
except User.DoesNotExist:
return JsonResponse({
'code': 404,
'message': '用户不存在',
'data': None
}, json_dumps_params={'ensure_ascii': False})
except Exception as e:
logger.error(f"用户登录失败: {e}")
import traceback
logger.error(f"详细错误: {traceback.format_exc()}")
return JsonResponse({
'code': 500,
'message': f'登录失败: {str(e)}',
'data': None
}, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def update_user_info(request):
"""更新用户信息,需要认证"""
try:
data = json.loads(request.body)
# 获取参数
company = data.get('company')
name = data.get('name')
# 获取当前认证用户
user = request.user
# 如果请求中包含 user_id 且与当前用户不匹配,返回错误
if 'user_id' in data and int(data['user_id']) != user.id:
return JsonResponse({
'code': 403,
'message': '您只能修改自己的信息',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 如果是首次登录,需要填写公司和姓名
if not company or not name:
return JsonResponse({
'code': 400,
'message': '首次登录需要填写公司和姓名',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 更新信息
user.company = company
user.name = name
user.is_first_login = False # 更新后不再是首次登录
user.save()
return JsonResponse({
'code': 200,
'message': '信息更新成功',
'data': {
'user_id': user.id,
'email': user.email,
'is_first_login': False,
'name': user.name,
'company': user.company
}
}, json_dumps_params={'ensure_ascii': False})
except Exception as e:
logger.error(f"更新用户信息失败: {e}")
import traceback
logger.error(f"详细错误: {traceback.format_exc()}")
return JsonResponse({
'code': 500,
'message': f'更新用户信息失败: {str(e)}',
'data': None
}, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
@api_view(['POST'])
@permission_classes([AllowAny])
def user_register(request):
"""用户注册接口"""
try:
from .models import User
import json
from datetime import datetime
data = json.loads(request.body)
# 获取注册参数
email = data.get('email')
password = data.get('password')
company = data.get('company') # 可选参数
name = data.get('name') # 可选参数
# 检查必要参数
if not email or not password:
return JsonResponse({
'code': 400,
'message': '缺少必要参数: email 或 password',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 检查邮箱是否已注册
if User.objects.filter(email=email).exists():
return JsonResponse({
'code': 409,
'message': '该邮箱已注册',
'data': None
}, json_dumps_params={'ensure_ascii': False})
# 创建用户
try:
# 根据是否提供公司和姓名决定是否为首次登录
is_first_login = not (company and name)
# 创建用户
user = User.objects.create_user(
email=email,
password=password,
company=company,
name=name,
is_first_login=is_first_login,
last_login=timezone.now()
)
# 构造返回数据
user_data = {
'user_id': user.id,
'email': user.email,
'is_first_login': is_first_login,
'company': user.company,
'name': user.name
}
return JsonResponse({
'code': 200,
'message': '注册成功',
'data': user_data
}, json_dumps_params={'ensure_ascii': False})
except Exception as e:
logger.error(f"创建用户失败: {e}")
return JsonResponse({
'code': 500,
'message': f'注册失败: {str(e)}',
'data': None
}, json_dumps_params={'ensure_ascii': False})
except Exception as e:
logger.error(f"用户注册失败: {e}")
import traceback
logger.error(f"详细错误: {traceback.format_exc()}")
return JsonResponse({
'code': 500,
'message': f'注册失败: {str(e)}',
'data': None
}, json_dumps_params={'ensure_ascii': False})

View File

@ -41,14 +41,14 @@ INSTALLED_APPS = [
'django_filters',
'django.contrib.staticfiles',
'channels',
'rest_framework',
'apps.user.apps.UserConfig',
"apps.expertproducts.apps.ExpertproductsConfig",
"apps.daren_detail.apps.DarenDetailConfig",
"apps.discovery.apps.DiscoveryConfig",
"apps.template.apps.TemplateConfig",
"apps.brands.apps.BrandsConfig",
'rest_framework',
'rest_framework_simplejwt',
]
MIDDLEWARE = [
@ -195,4 +195,34 @@ LOGGING = {
'propagate': True,
},
},
}
}
# 自定义用户模型
AUTH_USER_MODEL = 'user.User'
# REST Framework 设置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'apps.user.authentication.CustomTokenAuthentication',
),
}
# JWT 设置
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(days=1),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'AUTH_HEADER_TYPES': ('Bearer',),
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'UPDATE_LAST_LOGIN': False, # 不在 token 中记录最后登录时间
'TOKEN_TYPE_CLAIM': None, # 不在 token 中包含 token 类型
'JTI_CLAIM': None, # 不在 token 中包含 JWT ID
}
# JWT配置
JWT_SECRET_KEY = 'your-secret-key-here' # 建议使用更安全的密钥
JWT_EXPIRATION_DELTA = 24 * 60 * 60 # token有效期24小时

View File

@ -1,8 +1,14 @@
from django.contrib import admin
from django.urls import path, include
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('admin/', admin.site.urls),
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('api/user/', include('apps.user.urls')),
path('api/daren_detail/', include('apps.daren_detail.urls')),
path('api/operation/', include('apps.expertproducts.urls')),