diff --git a/src/DjangoBlog-master(1)/DjangoBlog-master/comments/models.py b/src/DjangoBlog-master(1)/DjangoBlog-master/comments/models.py index 7c3bbc8..d7235ce 100644 --- a/src/DjangoBlog-master(1)/DjangoBlog-master/comments/models.py +++ b/src/DjangoBlog-master(1)/DjangoBlog-master/comments/models.py @@ -9,31 +9,63 @@ from blog.models import Article # Create your models here. class Comment(models.Model): + """ + 评论模型类 + 用于存储博客文章的评论信息,支持多级回复功能 + """ + + # 评论正文,最大长度300字符,在管理界面显示为'正文' body = models.TextField('正文', max_length=300) + + # 评论创建时间,默认值为当前时间,使用Django的国际化支持 creation_time = models.DateTimeField(_('creation time'), default=now) + + # 评论最后修改时间,默认值为当前时间 last_modify_time = models.DateTimeField(_('last modify time'), default=now) + + # 评论作者,关联用户模型,删除用户时级联删除其所有评论 author = models.ForeignKey( settings.AUTH_USER_MODEL, verbose_name=_('author'), on_delete=models.CASCADE) + + # 所属文章,关联文章模型,删除文章时级联删除所有相关评论 article = models.ForeignKey( Article, verbose_name=_('article'), on_delete=models.CASCADE) + + # 父级评论,支持评论回复功能,允许为空表示顶级评论 parent_comment = models.ForeignKey( - 'self', + 'self', # 自关联,指向同一个模型 verbose_name=_('parent comment'), - blank=True, - null=True, - on_delete=models.CASCADE) + blank=True, # 在表单中允许为空 + null=True, # 在数据库中允许为NULL + on_delete=models.CASCADE) # 删除父评论时级联删除子评论 + + # 评论是否启用(审核通过),默认未启用,不允许为空 is_enable = models.BooleanField(_('enable'), default=False, blank=False, null=False) class Meta: + """ + 模型的元数据配置 + """ + # 按ID降序排列,新的评论显示在前面 ordering = ['-id'] + + # 单数名称,在管理界面显示 verbose_name = _('comment') + + # 复数名称,与单数相同 verbose_name_plural = verbose_name + + # 指定获取最新记录时使用的字段 get_latest_by = 'id' def __str__(self): - return self.body + """ + 对象的字符串表示方法 + 在Django管理界面和其他显示对象的地方使用 + """ + return self.body # 直接返回评论正文作为显示内容 \ No newline at end of file diff --git a/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/admin.py b/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/admin.py index 57eab5f..9ec5080 100644 --- a/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/admin.py +++ b/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/admin.py @@ -5,50 +5,93 @@ from django.contrib import admin from django.urls import reverse from django.utils.html import format_html +# 获取当前模块的日志记录器 logger = logging.getLogger(__name__) class OAuthUserAdmin(admin.ModelAdmin): + """ + OAuth用户管理后台配置类 + 用于自定义Django Admin中OAuth用户模型的显示和行为 + """ + + # 搜索字段配置,支持按昵称和邮箱搜索 search_fields = ('nickname', 'email') + + # 每页显示的项目数量 list_per_page = 20 + + # 列表页显示的字段 list_display = ( 'id', 'nickname', - 'link_to_usermodel', - 'show_user_image', - 'type', + 'link_to_usermodel', # 自定义方法:链接到用户模型 + 'show_user_image', # 自定义方法:显示用户头像 + 'type', # OAuth类型 'email', ) + + # 可点击进入编辑页的字段 list_display_links = ('id', 'nickname') + + # 右侧筛选器配置 list_filter = ('author', 'type',) + + # 只读字段列表(初始为空) readonly_fields = [] def get_readonly_fields(self, request, obj=None): + """ + 动态获取只读字段 + 将所有模型字段和多对多字段设为只读 + """ return list(self.readonly_fields) + \ - [field.name for field in obj._meta.fields] + \ - [field.name for field in obj._meta.many_to_many] + [field.name for field in obj._meta.fields] + \ + [field.name for field in obj._meta.many_to_many] def has_add_permission(self, request): + """ + 禁用添加权限 + OAuth用户应该通过OAuth流程自动创建,而不是手动添加 + """ return False def link_to_usermodel(self, obj): + """ + 自定义方法:生成指向关联用户模型的链接 + """ if obj.author: + # 获取用户模型的app和模型名称信息 info = (obj.author._meta.app_label, obj.author._meta.model_name) + # 生成用户编辑页面的URL link = reverse('admin:%s_%s_change' % info, args=(obj.author.id,)) + # 返回HTML格式的链接 return format_html( u'%s' % (link, obj.author.nickname if obj.author.nickname else obj.author.email)) def show_user_image(self, obj): - img = obj.picture + """ + 自定义方法:在管理后台显示用户头像 + """ + img = obj.picture # 获取头像图片URL return format_html( u'' % (img)) + # 设置自定义方法在管理后台的显示名称 link_to_usermodel.short_description = '用户' show_user_image.short_description = '用户头像' class OAuthConfigAdmin(admin.ModelAdmin): + """ + OAuth配置管理后台配置类 + 用于管理不同OAuth服务的配置信息 + """ + + # 列表页显示的字段 list_display = ('type', 'appkey', 'appsecret', 'is_enable') + + # 右侧筛选器配置 list_filter = ('type',) diff --git a/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/apps.py b/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/apps.py index 17fcea2..12d7409 100644 --- a/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/apps.py +++ b/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/apps.py @@ -2,4 +2,14 @@ from django.apps import AppConfig class OauthConfig(AppConfig): - name = 'oauth' + """ + OAuth应用配置类 + 用于配置Django中OAuth应用的元数据和启动行为 + + 这个类继承自Django的AppConfig基类,用于定义 + OAuth应用在Django项目中的配置信息 + """ + + # 指定应用的Python路径,Django使用这个名称来识别应用 + # 这应该与应用目录的名称保持一致 + name = 'oauth' \ No newline at end of file diff --git a/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/forms.py b/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/forms.py index 0e4ede3..b7c9bf4 100644 --- a/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/forms.py +++ b/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/forms.py @@ -3,10 +3,32 @@ from django.forms import widgets class RequireEmailForm(forms.Form): + """ + 邮箱验证表单类 + 用于在OAuth登录过程中要求用户提供邮箱地址 + 通常在第三方OAuth服务没有返回邮箱信息时使用 + """ + + # 邮箱字段,标签显示为'电子邮箱',必填字段 email = forms.EmailField(label='电子邮箱', required=True) + + # OAuth用户ID隐藏字段,用于关联OAuth用户记录 oauthid = forms.IntegerField(widget=forms.HiddenInput, required=False) def __init__(self, *args, **kwargs): + """ + 初始化方法,自定义表单字段的显示属性 + + Args: + *args: 位置参数 + **kwargs: 关键字参数 + """ + # 调用父类的初始化方法 super(RequireEmailForm, self).__init__(*args, **kwargs) + + # 自定义邮箱字段的输入控件,添加占位符和CSS类 self.fields['email'].widget = widgets.EmailInput( - attrs={'placeholder': "email", "class": "form-control"}) + attrs={ + 'placeholder': "email", # 输入框内的提示文字 + "class": "form-control" # Bootstrap样式类 + }) \ No newline at end of file diff --git a/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/models.py b/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/models.py index be838ed..f9fe8be 100644 --- a/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/models.py +++ b/src/DjangoBlog-master(1)/DjangoBlog-master/oauth/models.py @@ -7,61 +7,113 @@ from django.utils.translation import gettext_lazy as _ class OAuthUser(models.Model): + """ + OAuth用户模型 + 用于存储通过第三方OAuth服务登录的用户信息 + """ + + # 关联到系统的本地用户,允许为空(初次OAuth登录时可能还未关联) author = models.ForeignKey( settings.AUTH_USER_MODEL, verbose_name=_('author'), blank=True, null=True, - on_delete=models.CASCADE) + on_delete=models.CASCADE) # 删除用户时级联删除OAuth记录 + + # OAuth服务提供的用户唯一标识 openid = models.CharField(max_length=50) + + # 用户在第三方平台的昵称 nickname = models.CharField(max_length=50, verbose_name=_('nick name')) + + # OAuth访问令牌,用于后续API调用 token = models.CharField(max_length=150, null=True, blank=True) + + # 用户在第三方平台的头像URL picture = models.CharField(max_length=350, blank=True, null=True) + + # OAuth服务类型(如github、weibo等) type = models.CharField(blank=False, null=False, max_length=50) + + # 用户在第三方平台的邮箱 email = models.CharField(max_length=50, null=True, blank=True) + + # 存储额外的OAuth返回数据(JSON格式) metadata = models.TextField(null=True, blank=True) + + # 记录创建时间 creation_time = models.DateTimeField(_('creation time'), default=now) + + # 最后修改时间 last_modify_time = models.DateTimeField(_('last modify time'), default=now) def __str__(self): + """返回对象的字符串表示,显示用户昵称""" return self.nickname class Meta: - verbose_name = _('oauth user') - verbose_name_plural = verbose_name - ordering = ['-creation_time'] + """模型元数据配置""" + verbose_name = _('oauth user') # 单数名称 + verbose_name_plural = verbose_name # 复数名称 + ordering = ['-creation_time'] # 按创建时间降序排列 class OAuthConfig(models.Model): + """ + OAuth服务配置模型 + 用于存储不同OAuth服务的应用配置信息 + """ + + # OAuth服务类型选择项 TYPE = ( - ('weibo', _('weibo')), - ('google', _('google')), - ('github', 'GitHub'), - ('facebook', 'FaceBook'), - ('qq', 'QQ'), + ('weibo', _('weibo')), # 微博 + ('google', _('google')), # 谷歌 + ('github', 'GitHub'), # GitHub + ('facebook', 'FaceBook'), # Facebook + ('qq', 'QQ'), # QQ ) + + # OAuth服务类型,从预定义选项中选择 type = models.CharField(_('type'), max_length=10, choices=TYPE, default='a') + + # OAuth应用的AppKey/Client ID appkey = models.CharField(max_length=200, verbose_name='AppKey') + + # OAuth应用的AppSecret/Client Secret appsecret = models.CharField(max_length=200, verbose_name='AppSecret') + + # OAuth回调URL callback_url = models.CharField( max_length=200, verbose_name=_('callback url'), blank=False, default='') + + # 是否启用该OAuth服务 is_enable = models.BooleanField( _('is enable'), default=True, blank=False, null=False) + + # 配置创建时间 creation_time = models.DateTimeField(_('creation time'), default=now) + + # 配置最后修改时间 last_modify_time = models.DateTimeField(_('last modify time'), default=now) def clean(self): + """ + 数据验证方法 + 确保同类型的OAuth配置只能有一个 + """ if OAuthConfig.objects.filter( type=self.type).exclude(id=self.id).count(): raise ValidationError(_(self.type + _('already exists'))) def __str__(self): + """返回对象的字符串表示,显示OAuth服务类型""" return self.type class Meta: - verbose_name = 'oauth配置' - verbose_name_plural = verbose_name - ordering = ['-creation_time'] + """模型元数据配置""" + verbose_name = 'oauth配置' # 单数名称(中文) + verbose_name_plural = verbose_name # 复数名称 + ordering = ['-creation_time'] # 按创建时间降序排列 \ No newline at end of file