File size: 3,223 Bytes
b4f2238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
"""
Schema 基类和 Mixin
提供通用的字段解析方法,减少重复代码
"""

from datetime import datetime
from typing import Any, cast

from django.utils import timezone


class TimestampMixin:
    """
    时间戳字段解析 Mixin
    为 Schema 提供统一的时间字段处理
    """

    @classmethod
    def _resolve_datetime(cls, value: Any) -> datetime | None:
        """
        统一处理 datetime 字段,转换为本地时间

        Args:
            value: datetime 对象或 None

        Returns:
            本地化的 datetime 或 None
        """
        if value is None:
            return None
        try:
            return timezone.localtime(value)
        except (TypeError, AttributeError, ValueError):
            return cast(datetime | None, value)

    @classmethod
    def _resolve_datetime_iso(cls, value: Any) -> str | None:
        """
        统一处理 datetime 字段,转换为 ISO 格式字符串

        Args:
            value: datetime 对象或 None

        Returns:
            ISO 格式字符串或 None
        """
        if value is None:
            return None
        try:
            local_time = timezone.localtime(value)
            return local_time.isoformat()
        except (TypeError, AttributeError, ValueError):
            return value.isoformat() if hasattr(value, "isoformat") else str(value)


class DisplayLabelMixin:
    """
    显示标签解析 Mixin
    为 choices 字段提供统一的 label 获取方法
    """

    @classmethod
    def _get_display(cls, obj: Any, field_name: str) -> str | None:
        """
        获取 choices 字段的显示值

        Args:
            obj: Model 实例
            field_name: 字段名

        Returns:
            显示值或 None
        """
        try:
            getter = getattr(obj, f"get_{field_name}_display", None)
            if getter:
                return cast(str | None, getter())
            return getattr(obj, field_name, None)
        except AttributeError:
            return None


class FileFieldMixin:
    """
    文件字段解析 Mixin
    为 FileField 提供统一的 URL 和路径获取方法
    """

    @classmethod
    def _get_file_url(cls, file_field: Any) -> str | None:
        """
        获取文件的 URL

        Args:
            file_field: FileField 实例

        Returns:
            文件 URL 或 None
        """
        if not file_field:
            return None
        try:
            return cast(str | None, file_field.url)
        except (AttributeError, ValueError):
            return None

    @classmethod
    def _get_file_path(cls, file_field: Any) -> str | None:
        """
        获取文件的路径

        Args:
            file_field: FileField 实例

        Returns:
            文件路径或 None
        """
        if not file_field:
            return None
        try:
            return cast(str | None, file_field.path)
        except (AttributeError, ValueError):
            return None


# 组合所有 Mixin 的基类
class SchemaMixin(TimestampMixin, DisplayLabelMixin, FileFieldMixin):
    """
    Schema 通用 Mixin
    组合所有常用的字段解析方法
    """

    pass