merge origin/main: adopt env-var secrets fix, keep no-SQLite structure
This commit is contained in:
+7
-5
@@ -417,8 +417,9 @@ class ArticleLikeToggleView(APIView):
|
||||
like, created = ArticleLike.objects.get_or_create(user=request.user, article=article)
|
||||
if not created:
|
||||
like.delete()
|
||||
article.likes = max(0, article.likes - 1)
|
||||
article.save(update_fields=['likes'])
|
||||
Article.objects.filter(pk=pk).update(likes=F("likes") - 1)
|
||||
article.refresh_from_db()
|
||||
article.likes = max(0, article.likes)
|
||||
return create_standardized_response(
|
||||
data={'liked': False, 'likes_count': article.likes},
|
||||
code=ResponseCode.SUCCESS
|
||||
@@ -498,8 +499,9 @@ class ArticleCommentLikeToggleView(APIView):
|
||||
like, created = ArticleCommentLike.objects.get_or_create(user=request.user, comment=comment)
|
||||
if not created:
|
||||
like.delete()
|
||||
comment.likes = max(0, comment.likes - 1)
|
||||
comment.save(update_fields=['likes'])
|
||||
ArticleComment.objects.filter(pk=pk).update(likes=F("likes") - 1)
|
||||
comment.refresh_from_db()
|
||||
comment.likes = max(0, comment.likes)
|
||||
return create_standardized_response(
|
||||
data={'liked': False, 'likes_count': comment.likes},
|
||||
code=ResponseCode.SUCCESS
|
||||
@@ -626,4 +628,4 @@ class ArticleToggleTopView(APIView):
|
||||
data={'is_top': article.is_top},
|
||||
code=ResponseCode.SUCCESS,
|
||||
message='置顶状态已更新'
|
||||
)
|
||||
)
|
||||
@@ -21,7 +21,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'django-insecure-j+-psq=m++l7hup73k1eg+wm-b&2_)!+_^o=6(=xc$1px*kqt@'
|
||||
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'django-insecure-dev-only-key-change-in-production')
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = os.environ.get('DJANGO_DEBUG', 'True') == 'True'
|
||||
@@ -66,7 +66,7 @@ CORS_ALLOWED_ORIGINS = [
|
||||
]
|
||||
CORS_ALLOW_ALL_ORIGINS = False
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
ALLOWED_HOSTS = os.environ.get('DJANGO_ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')
|
||||
|
||||
CORS_ALLOW_CREDENTIALS = True
|
||||
CORS_ALLOW_HEADERS = [
|
||||
@@ -127,7 +127,7 @@ EMAIL_HOST = 'smtp.qq.com'
|
||||
EMAIL_PORT = 465
|
||||
EMAIL_USE_SSL = True
|
||||
EMAIL_HOST_USER = 'cs10086086@qq.com'
|
||||
EMAIL_HOST_PASSWORD = 'ldzpymytsinkfjhb'
|
||||
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD', '')
|
||||
EMAIL_USE_TLS = False
|
||||
|
||||
AUTH_USER_MODEL = 'user.FUser'
|
||||
@@ -173,7 +173,7 @@ DATABASES = {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': 'chunyu_project',
|
||||
'USER': 'root',
|
||||
'PASSWORD': 'mysql_NpyMCS',
|
||||
'PASSWORD': os.environ.get('MYSQL_PASSWORD', ''),
|
||||
'HOST': '192.168.5.7',
|
||||
'PORT': '3306',
|
||||
'OPTIONS': {
|
||||
@@ -189,7 +189,7 @@ DATABASES = {
|
||||
REDIS_HOST = '192.168.5.7'
|
||||
REDIS_PORT = 6379
|
||||
REDIS_DB = 0
|
||||
REDIS_PASSWORD = 'jhkdjhkjdhsIUTYURTU_sx86Jf'
|
||||
REDIS_PASSWORD = os.environ.get('REDIS_PASSWORD', '')
|
||||
SESSION_DB = 1
|
||||
CELERY_BROKER_DB = 2
|
||||
CELERY_RESULT_BACKEND_DB = 2
|
||||
|
||||
+13
-6
@@ -500,10 +500,14 @@ class CDNStaticFileView(APIView):
|
||||
)
|
||||
if not os.path.exists(file_path):
|
||||
raise Http404
|
||||
response = FileResponse(open(file_path, 'rb'), content_type='text/markdown; charset=utf-8')
|
||||
response['Cache-Control'] = 'max-age=86400'
|
||||
return response
|
||||
|
||||
fh = open(file_path, "rb")
|
||||
try:
|
||||
response = FileResponse(fh, content_type="text/markdown; charset=utf-8")
|
||||
response["Cache-Control"] = "max-age=86400"
|
||||
return response
|
||||
except Exception:
|
||||
fh.close()
|
||||
raise
|
||||
|
||||
class CourseFavoriteToggleView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
@@ -745,7 +749,10 @@ class MyProgressView(APIView):
|
||||
'last_studied_at': read.completed_at,
|
||||
}
|
||||
course_map[course_id]['completed_chapters'] += 1
|
||||
if read.completed_at > course_map[course_id]['last_studied_at']:
|
||||
if read.completed_at and (
|
||||
not course_map[course_id]['last_studied_at'] or
|
||||
read.completed_at > course_map[course_id]['last_studied_at']
|
||||
):
|
||||
course_map[course_id]['last_studied_at'] = read.completed_at
|
||||
|
||||
courses = []
|
||||
@@ -765,4 +772,4 @@ class MyProgressView(APIView):
|
||||
'total_courses': len(courses),
|
||||
'total_completed': total_completed,
|
||||
}
|
||||
)
|
||||
)
|
||||
+10
-16
@@ -67,8 +67,8 @@ class GlobalSearchView(APIView):
|
||||
|
||||
for article in articles:
|
||||
cover_url = ''
|
||||
if article.cover and hasattr(article.cover, 'url'):
|
||||
cover_url = request.build_absolute_uri(article.cover.url)
|
||||
if article.cover_image and hasattr(article.cover_image, 'url'):
|
||||
cover_url = request.build_absolute_uri(article.cover_image.url)
|
||||
|
||||
excerpt = article.excerpt or ''
|
||||
if not excerpt and article.content:
|
||||
@@ -91,21 +91,16 @@ class GlobalSearchView(APIView):
|
||||
).order_by('-created_at')[:100]
|
||||
|
||||
for tool in tools:
|
||||
cover_url = ''
|
||||
if tool.icon and hasattr(tool.icon, 'url'):
|
||||
cover_url = request.build_absolute_uri(tool.icon.url)
|
||||
|
||||
results.append({
|
||||
'id': tool.id,
|
||||
'type': '工具',
|
||||
'title': tool.name,
|
||||
'desc': tool.description or '',
|
||||
'cover': cover_url,
|
||||
'views': tool.views or 0,
|
||||
'likes': tool.likes or 0,
|
||||
'cover': '',
|
||||
'views': tool.usage_count or 0,
|
||||
'likes': 0,
|
||||
'url': f'/use?tool={tool.id}',
|
||||
})
|
||||
|
||||
if content_type == 'all' or content_type == 'course':
|
||||
courses = Course.objects.filter(
|
||||
Q(title__icontains=q) | Q(description__icontains=q)
|
||||
@@ -113,8 +108,8 @@ class GlobalSearchView(APIView):
|
||||
|
||||
for course in courses:
|
||||
cover_url = ''
|
||||
if course.cover and hasattr(course.cover, 'url'):
|
||||
cover_url = request.build_absolute_uri(course.cover.url)
|
||||
if course.cover_image and hasattr(course.cover_image, 'url'):
|
||||
cover_url = request.build_absolute_uri(course.cover_image.url)
|
||||
|
||||
results.append({
|
||||
'id': course.id,
|
||||
@@ -122,9 +117,8 @@ class GlobalSearchView(APIView):
|
||||
'title': course.title,
|
||||
'desc': course.description or '',
|
||||
'cover': cover_url,
|
||||
'views': course.views or 0,
|
||||
'likes': course.likes or 0,
|
||||
'url': f'/courses/{course.id}',
|
||||
'views': 0,
|
||||
'likes': 0,
|
||||
})
|
||||
|
||||
if content_type == 'all' or content_type == 'api':
|
||||
@@ -236,4 +230,4 @@ class HotKeywordsView(APIView):
|
||||
'Vue3',
|
||||
'Python',
|
||||
]
|
||||
return create_standardized_response(data=hot_keywords, code=ResponseCode.SUCCESS)
|
||||
return create_standardized_response(data=hot_keywords, code=ResponseCode.SUCCESS)
|
||||
+1
-1
@@ -17,7 +17,7 @@ from django.core.cache import caches
|
||||
default_cache = caches['default']
|
||||
session_cache = caches['session']
|
||||
celery_cache = caches['celery']
|
||||
from ..models import FUser, LoginRecord
|
||||
from ..models import FUser, LoginRecord, Follow
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
from ..serializers.user_serializers import UserSerializer, ChangePasswordSerializer, UserUpdateSerializer
|
||||
from ..tasks import send_verification_email_task, send_reset_password_email_task
|
||||
|
||||
Reference in New Issue
Block a user