This commit is contained in:
@@ -101,19 +101,7 @@ DATABASES = {
|
||||
|
||||
#从环境变量获取数据库配置 (Docker 环境会自动注入这些变量。
|
||||
|
||||
DB_HOST = os.environ.get('DB_HOST', '6.6.6.66')
|
||||
if DB_HOST:
|
||||
DATABASES['default'] = {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': os.environ.get('DB_NAME', 'market'),
|
||||
'USER': os.environ.get('DB_USER', 'market'),
|
||||
'PASSWORD': os.environ.get('DB_PASSWORD', '123market'),
|
||||
'HOST': DB_HOST,
|
||||
'PORT': os.environ.get('DB_PORT', '5432'),
|
||||
}
|
||||
|
||||
|
||||
# DB_HOST = os.environ.get('DB_HOST', '121.43.104.161')
|
||||
# DB_HOST = os.environ.get('DB_HOST', '6.6.6.66')
|
||||
# if DB_HOST:
|
||||
# DATABASES['default'] = {
|
||||
# 'ENGINE': 'django.db.backends.postgresql',
|
||||
@@ -121,10 +109,22 @@ if DB_HOST:
|
||||
# 'USER': os.environ.get('DB_USER', 'market'),
|
||||
# 'PASSWORD': os.environ.get('DB_PASSWORD', '123market'),
|
||||
# 'HOST': DB_HOST,
|
||||
# 'PORT': os.environ.get('DB_PORT', '6433'),
|
||||
# 'PORT': os.environ.get('DB_PORT', '5432'),
|
||||
# }
|
||||
|
||||
|
||||
DB_HOST = os.environ.get('DB_HOST', '121.43.104.161')
|
||||
if DB_HOST:
|
||||
DATABASES['default'] = {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': os.environ.get('DB_NAME', 'market'),
|
||||
'USER': os.environ.get('DB_USER', 'market'),
|
||||
'PASSWORD': os.environ.get('DB_PASSWORD', '123market'),
|
||||
'HOST': DB_HOST,
|
||||
'PORT': os.environ.get('DB_PORT', '6433'),
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators
|
||||
|
||||
|
||||
@@ -235,6 +235,10 @@ class VCCourseAdmin(OrderableAdminMixin, ModelAdmin):
|
||||
('基本信息', {
|
||||
'fields': ('title', 'description', 'course_type', 'tag', 'price')
|
||||
}),
|
||||
('课程安排', {
|
||||
'fields': ('is_fixed_schedule', 'start_time', 'end_time'),
|
||||
'description': '勾选“是否固定时间课程”后,请设置开始和结束时间'
|
||||
}),
|
||||
('讲师信息', {
|
||||
'fields': ('instructor', 'instructor_title', 'instructor_desc', 'instructor_avatar', 'instructor_avatar_url'),
|
||||
'description': '讲师头像上传和URL二选一,优先使用URL'
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 6.0.1 on 2026-02-23 15:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('shop', '0032_order_activity'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='vccourse',
|
||||
name='is_fixed_schedule',
|
||||
field=models.BooleanField(default=False, help_text='勾选后,前端将显示具体的开课时间', verbose_name='是否固定时间课程'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vccourse',
|
||||
name='schedule_time',
|
||||
field=models.CharField(blank=True, help_text='例如:每周六晚 20:00', max_length=100, null=True, verbose_name='课程具体时间'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,27 @@
|
||||
# Generated by Django 6.0.1 on 2026-02-23 16:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('shop', '0033_vccourse_is_fixed_schedule_vccourse_schedule_time'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='vccourse',
|
||||
name='schedule_time',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vccourse',
|
||||
name='end_time',
|
||||
field=models.DateTimeField(blank=True, null=True, verbose_name='结束时间'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vccourse',
|
||||
name='start_time',
|
||||
field=models.DateTimeField(blank=True, null=True, verbose_name='开始时间'),
|
||||
),
|
||||
]
|
||||
@@ -348,6 +348,11 @@ class VCCourse(models.Model):
|
||||
instructor_desc = models.TextField(blank=True, verbose_name="讲师简介", default="拥有多年开发经验,擅长...")
|
||||
|
||||
tag = models.CharField(max_length=20, blank=True, verbose_name="标签", help_text="例如: 热门, 推荐, 进阶")
|
||||
|
||||
# 课程时间安排
|
||||
is_fixed_schedule = models.BooleanField(default=False, verbose_name="是否固定时间课程", help_text="勾选后,前端将显示具体的开课时间")
|
||||
start_time = models.DateTimeField(blank=True, null=True, verbose_name="开始时间")
|
||||
end_time = models.DateTimeField(blank=True, null=True, verbose_name="结束时间")
|
||||
|
||||
price = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name="价格", help_text="0表示免费")
|
||||
content = models.TextField(blank=True, verbose_name="详细内容", help_text="支持Markdown或HTML")
|
||||
|
||||
@@ -92,7 +92,7 @@ class CourseEnrollmentSerializer(serializers.ModelSerializer):
|
||||
课程报名序列化器
|
||||
"""
|
||||
course_title = serializers.CharField(source='course.title', read_only=True)
|
||||
ref_code = serializers.CharField(write_only=True, required=False, allow_blank=True)
|
||||
ref_code = serializers.CharField(write_only=True, required=False, allow_blank=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = CourseEnrollment
|
||||
@@ -124,7 +124,7 @@ class ServiceOrderSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
service_name = serializers.CharField(source='service.title', read_only=True)
|
||||
# 接收前端传来的 ref_code
|
||||
ref_code = serializers.CharField(write_only=True, required=False, allow_blank=True)
|
||||
ref_code = serializers.CharField(write_only=True, required=False, allow_blank=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = ServiceOrder
|
||||
@@ -212,7 +212,7 @@ class OrderSerializer(serializers.ModelSerializer):
|
||||
salesperson_name = serializers.CharField(source='salesperson.name', read_only=True)
|
||||
salesperson_code = serializers.CharField(source='salesperson.code', read_only=True)
|
||||
# 接收前端传来的 ref_code,用于查找 Salesperson
|
||||
ref_code = serializers.CharField(write_only=True, required=False, allow_blank=True)
|
||||
ref_code = serializers.CharField(write_only=True, required=False, allow_blank=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
|
||||
@@ -268,8 +268,8 @@ def pay(request):
|
||||
product = None
|
||||
if order_type == 'course':
|
||||
try:
|
||||
product = VBCourse.objects.get(id=good_id)
|
||||
except VBCourse.DoesNotExist:
|
||||
product = VCCourse.objects.get(id=good_id)
|
||||
except VCCourse.DoesNotExist:
|
||||
print(f"课程不存在: {good_id}")
|
||||
return Response({'error': f'找不到 ID 为 {good_id} 的课程'}, status=status.HTTP_404_NOT_FOUND)
|
||||
else:
|
||||
@@ -355,7 +355,8 @@ def pay(request):
|
||||
print(f"微信支付 V3 Native 下单成功!")
|
||||
print(f"订单 ID: {order.id}")
|
||||
print(f"商户订单号: {out_trade_no}")
|
||||
print(f"商品: {product.name} x {quantity}")
|
||||
product_name = getattr(product, 'name', getattr(product, 'title', 'Unknown Product'))
|
||||
print(f"商品: {product_name} x {quantity}")
|
||||
print(f"总额: {total_price} 元")
|
||||
print(f"code_url: {code_url}")
|
||||
print(f"========================================")
|
||||
@@ -596,6 +597,16 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
return queryset.filter(wechat_user=user).order_by('-created_at')
|
||||
return queryset.order_by('-created_at')
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
print(f"Creating order with data: {request.data}")
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
if not serializer.is_valid():
|
||||
print(f"Order validation failed: {serializer.errors}")
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
self.perform_create(serializer)
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
"""
|
||||
创建订单时自动关联当前微信用户
|
||||
|
||||
Reference in New Issue
Block a user