[0;34m========================================[0m [0;34mISO 27001 系統完整測試[0m [0;34m========================================[0m [1;33m[階段 1] 環境檢查[0m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 測試 1: Docker Compose 運行中 ... [0;32m✓ 通過[0m 測試 2: Backend 容器運行中 ... [0;32m✓ 通過[0m 測試 3: Database 容器運行中 ... [0;32m✓ 通過[0m 測試 4: Redis 容器運行中 ... [0;32m✓ 通過[0m 測試 5: Backend API 可存取 ... [0;32m✓ 通過[0m [1;33m[階段 2] 資料庫測試[0m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 測試 6: PostgreSQL 可連線 ... [0;32m✓ 通過[0m 測試 7: 使用者資料存在 ... [0;32m✓ 通過[0m 測試 8: 資產資料存在 ... [0;32m✓ 通過[0m 測試 9: 資產關係資料存在 ... [0;32m✓ 通過[0m [1;33m[階段 3] API 認證測試[0m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 測試 10: 登入 API ... [0;32m✓ 通過[0m 已取得 Token: eyJhbGciOiJIUzI1NiIs... [1;33m[階段 4] 資產管理 API 測試[0m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 測試 11: 取得資產列表 ... [0;32m✓ 通過[0m 測試 12: 取得資產統計 ... [0;32m✓ 通過[0m 測試 13: 搜尋資產 (Server) ... [0;32m✓ 通過[0m 測試 14: 篩選硬體資產 ... [0;32m✓ 通過[0m 測試 15: 篩選使用中資產 ... [0;32m✓ 通過[0m 測試 16: 取得資產詳情 ... [0;31m✗ 失敗[0m 預期包含: "asset_number" 實際輸出:
'str' object has no attribute '_meta'
| Request Method: | GET |
|---|---|
| Request URL: | http://localhost:8000/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/ |
| Django Version: | 4.2.7 |
| Exception Type: | AttributeError |
| Exception Value: | 'str' object has no attribute '_meta' |
| Exception Location: | /usr/local/lib/python3.11/site-packages/rest_framework/utils/model_meta.py, line 35, in get_field_info |
| Raised during: | assets.views.AssetViewSet |
| Python Executable: | /usr/local/bin/python |
| Python Version: | 3.11.13 |
| Python Path: | ['/app', '/usr/local/lib/python311.zip', '/usr/local/lib/python3.11', '/usr/local/lib/python3.11/lib-dynload', '/usr/local/lib/python3.11/site-packages'] |
| Server time: | Fri, 31 Oct 2025 23:13:18 +0800 |
/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py, line 55, in inner
return inner
else:
@wraps(get_response)
def inner(request):
try:
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^ …except Exception as exc:
response = response_for_exception(request, exc)
return response
return inner
| Variable | Value |
|---|---|
| exc | AttributeError("'str' object has no attribute '_meta'") |
| get_response | <bound method BaseHandler._get_response of <django.core.handlers.wsgi.WSGIHandler object at 0x7fcc2dd6de90>> |
| request | <WSGIRequest: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'> |
/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py, line 197, in _get_response
if response is None:
wrapped_callback = self.make_view_atomic(callback)
# If it is an asynchronous view, run it in a subthread.
if iscoroutinefunction(wrapped_callback):
wrapped_callback = async_to_sync(wrapped_callback)
try:
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ …except Exception as e:
response = self.process_exception_by_middleware(e, request)
if response is None:
raise
# Complain if the view returned None (a common error).
| Variable | Value |
|---|---|
| callback | <function AssetViewSet at 0x7fcc2e1e82c0> |
| callback_args | () |
| callback_kwargs | {'pk': '1d35714a-c0fe-4feb-b45e-1ab34c4b291d'} |
| middleware_method | <bound method CsrfViewMiddleware.process_view of <CsrfViewMiddleware get_response=convert_exception_to_response.<locals>.inner>> |
| request | <WSGIRequest: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'> |
| response | None |
| self | <django.core.handlers.wsgi.WSGIHandler object at 0x7fcc2dd6de90> |
| wrapped_callback | <function AssetViewSet at 0x7fcc2e1e82c0> |
/usr/local/lib/python3.11/site-packages/django/views/decorators/csrf.py, line 56, in wrapper_view
def csrf_exempt(view_func):
"""Mark a view function as being exempt from the CSRF view protection."""
# view_func.csrf_exempt = True would also work, but decorators are nicer
# if they don't have side effects, so return a new function.
@wraps(view_func)
def wrapper_view(*args, **kwargs):
return view_func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^ …wrapper_view.csrf_exempt = True
return wrapper_view
| Variable | Value |
|---|---|
| args | (<WSGIRequest: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'>,) |
| kwargs | {'pk': '1d35714a-c0fe-4feb-b45e-1ab34c4b291d'} |
| view_func | <function AssetViewSet at 0x7fcc2e1e8220> |
/usr/local/lib/python3.11/site-packages/rest_framework/viewsets.py, line 125, in view
setattr(self, method, handler)
self.request = request
self.args = args
self.kwargs = kwargs
# And continue as usual
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ …# take name and docstring from class
update_wrapper(view, cls, updated=())
# and possible attributes set by decorators
# like csrf_exempt from dispatch
| Variable | Value |
|---|---|
| action | 'retrieve' |
| actions | {'delete': 'destroy',
'get': 'retrieve',
'head': 'retrieve',
'patch': 'partial_update',
'put': 'update'} |
| args | () |
| cls | <class 'assets.views.AssetViewSet'> |
| handler | <bound method RetrieveModelMixin.retrieve of <assets.views.AssetViewSet object at 0x7fcc2c51fe10>> |
| initkwargs | {'basename': 'asset', 'detail': True, 'suffix': 'Instance'} |
| kwargs | {'pk': '1d35714a-c0fe-4feb-b45e-1ab34c4b291d'} |
| method | 'head' |
| request | <WSGIRequest: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'> |
| self | <assets.views.AssetViewSet object at 0x7fcc2c51fe10> |
/usr/local/lib/python3.11/site-packages/rest_framework/views.py, line 509, in dispatch
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
^^^^^^^^^^^^^^^^^^^^^^^^^^ …self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
def options(self, request, *args, **kwargs):
"""
| Variable | Value |
|---|---|
| args | () |
| handler | <bound method RetrieveModelMixin.retrieve of <assets.views.AssetViewSet object at 0x7fcc2c51fe10>> |
| kwargs | {'pk': '1d35714a-c0fe-4feb-b45e-1ab34c4b291d'} |
| request | <rest_framework.request.Request: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'> |
| self | <assets.views.AssetViewSet object at 0x7fcc2c51fe10> |
/usr/local/lib/python3.11/site-packages/rest_framework/views.py, line 469, in handle_exception
exception_handler = self.get_exception_handler()
context = self.get_exception_handler_context()
response = exception_handler(exc, context)
if response is None:
self.raise_uncaught_exception(exc)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ …response.exception = True
return response
def raise_uncaught_exception(self, exc):
if settings.DEBUG:
| Variable | Value |
|---|---|
| context | {'args': (),
'kwargs': {'pk': '1d35714a-c0fe-4feb-b45e-1ab34c4b291d'},
'request': <rest_framework.request.Request: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'>,
'view': <assets.views.AssetViewSet object at 0x7fcc2c51fe10>} |
| exc | AttributeError("'str' object has no attribute '_meta'") |
| exception_handler | <function exception_handler at 0x7fcc2e13ef20> |
| response | None |
| self | <assets.views.AssetViewSet object at 0x7fcc2c51fe10> |
/usr/local/lib/python3.11/site-packages/rest_framework/views.py, line 480, in raise_uncaught_exception
def raise_uncaught_exception(self, exc):
if settings.DEBUG:
request = self.request
renderer_format = getattr(request.accepted_renderer, 'format')
use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')request.force_plaintext_errors(use_plaintext_traceback)
raise exc
^^^^^^^^^ …# Note: Views are made CSRF exempt from within `as_view` as to prevent
# accidental removal of this exemption in cases where `dispatch` needs to
# be overridden.
def dispatch(self, request, *args, **kwargs):
"""
| Variable | Value |
|---|---|
| exc | AttributeError("'str' object has no attribute '_meta'") |
| renderer_format | 'json' |
| request | <rest_framework.request.Request: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'> |
| self | <assets.views.AssetViewSet object at 0x7fcc2c51fe10> |
| use_plaintext_traceback | True |
/usr/local/lib/python3.11/site-packages/rest_framework/views.py, line 506, in dispatch
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ …except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
| Variable | Value |
|---|---|
| args | () |
| handler | <bound method RetrieveModelMixin.retrieve of <assets.views.AssetViewSet object at 0x7fcc2c51fe10>> |
| kwargs | {'pk': '1d35714a-c0fe-4feb-b45e-1ab34c4b291d'} |
| request | <rest_framework.request.Request: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'> |
| self | <assets.views.AssetViewSet object at 0x7fcc2c51fe10> |
/usr/local/lib/python3.11/site-packages/rest_framework/mixins.py, line 56, in retrieve
class RetrieveModelMixin:
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
^^^^^^^^^^^^^^^ …class UpdateModelMixin:
"""
Update a model instance.
"""
| Variable | Value |
|---|---|
| args | () |
| instance | <Asset: DAT-SRC-001 - 原始程式碼倉庫> |
| kwargs | {'pk': '1d35714a-c0fe-4feb-b45e-1ab34c4b291d'} |
| request | <rest_framework.request.Request: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'> |
| self | <assets.views.AssetViewSet object at 0x7fcc2c51fe10> |
| serializer | AssetSerializer(<Asset: DAT-SRC-001 - 原始程式碼倉庫>, context={'request': <rest_framework.request.Request: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'>, 'format': None, 'view': <assets.views.AssetViewSet object>}):
id = UUIDField(read_only=True)
asset_number = CharField(help_text='例如: AST-001', label='資產編號', max_length=50, validators=[<UniqueValidator(queryset=Asset.objects.all())>])
name = CharField(label='資產名稱', max_length=200)
description = CharField(allow_blank=True, label='描述', required=False, style={'base_template': 'textarea.html'})
asset_type = ChoiceField(choices=[('hardware', '硬體'), ('software', '軟體'), ('data', '資料'), ('people', '人員'), ('facility', '設施')], label='資產類型')
asset_type_display = CharField(read_only=True, source='get_asset_type_display')
asset_subtype = CharField(allow_blank=True, help_text='例如: 伺服器、工作站、資料庫等', label='資產子類型', max_length=50, required=False)
owner = PrimaryKeyRelatedField(allow_null=True, label='資產擁有者', queryset=User.objects.all(), required=False)
owner_detail = UserSimpleSerializer(read_only=True, source='owner')
custodian = PrimaryKeyRelatedField(allow_null=True, label='資產管理者', queryset=User.objects.all(), required=False)
custodian_detail = UserSimpleSerializer(read_only=True, source='custodian')
location = CharField(allow_blank=True, help_text='例如: 機房A-機櫃3', label='所在位置', max_length=200, required=False)
network_segment = CharField(allow_blank=True, label='網路區段', max_length=100, required=False)
confidentiality = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='機密性等級', required=False)
confidentiality_display = CharField(read_only=True, source='get_confidentiality_display')
integrity = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='完整性等級', required=False)
integrity_display = CharField(read_only=True, source='get_integrity_display')
availability = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='可用性等級', required=False)
availability_display = CharField(read_only=True, source='get_availability_display')
status = ChoiceField(choices=[('active', '使用中'), ('inactive', '閒置'), ('maintenance', '維護中'), ('decommissioned', '已報廢')], label='狀態', required=False)
status_display = CharField(read_only=True, source='get_status_display')
risk_level = ReadOnlyField()
technical_details = JSONField(decoder=None, encoder=None, help_text='例如: {"os": "Ubuntu 22.04", "ip": "192.168.1.10", "cpu": "8 cores"}', label='技術細節', required=False, style={'base_template': 'textarea.html'})
acquisition_date = DateField(allow_null=True, label='取得日期', required=False)
created_at = DateTimeField(label='建立時間', read_only=True)
updated_at = DateTimeField(label='更新時間', read_only=True) |
/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py, line 555, in data
return BoundField(field, value, error)
# Include a backlink to the serializer class on return objects.
# Allows renderers such as HTMLFormRenderer to get the full field info.
@property
def data(self):
ret = super().data
^^^^^^^^^^^^ …return ReturnDict(ret, serializer=self)
@property
def errors(self):
ret = super().errors
if isinstance(ret, list) and len(ret) == 1 and getattr(ret[0], 'code', None) == 'null':
| Variable | Value |
|---|---|
| __class__ | <class 'rest_framework.serializers.Serializer'> |
| self | AssetSerializer(<Asset: DAT-SRC-001 - 原始程式碼倉庫>, context={'request': <rest_framework.request.Request: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'>, 'format': None, 'view': <assets.views.AssetViewSet object>}):
id = UUIDField(read_only=True)
asset_number = CharField(help_text='例如: AST-001', label='資產編號', max_length=50, validators=[<UniqueValidator(queryset=Asset.objects.all())>])
name = CharField(label='資產名稱', max_length=200)
description = CharField(allow_blank=True, label='描述', required=False, style={'base_template': 'textarea.html'})
asset_type = ChoiceField(choices=[('hardware', '硬體'), ('software', '軟體'), ('data', '資料'), ('people', '人員'), ('facility', '設施')], label='資產類型')
asset_type_display = CharField(read_only=True, source='get_asset_type_display')
asset_subtype = CharField(allow_blank=True, help_text='例如: 伺服器、工作站、資料庫等', label='資產子類型', max_length=50, required=False)
owner = PrimaryKeyRelatedField(allow_null=True, label='資產擁有者', queryset=User.objects.all(), required=False)
owner_detail = UserSimpleSerializer(read_only=True, source='owner')
custodian = PrimaryKeyRelatedField(allow_null=True, label='資產管理者', queryset=User.objects.all(), required=False)
custodian_detail = UserSimpleSerializer(read_only=True, source='custodian')
location = CharField(allow_blank=True, help_text='例如: 機房A-機櫃3', label='所在位置', max_length=200, required=False)
network_segment = CharField(allow_blank=True, label='網路區段', max_length=100, required=False)
confidentiality = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='機密性等級', required=False)
confidentiality_display = CharField(read_only=True, source='get_confidentiality_display')
integrity = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='完整性等級', required=False)
integrity_display = CharField(read_only=True, source='get_integrity_display')
availability = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='可用性等級', required=False)
availability_display = CharField(read_only=True, source='get_availability_display')
status = ChoiceField(choices=[('active', '使用中'), ('inactive', '閒置'), ('maintenance', '維護中'), ('decommissioned', '已報廢')], label='狀態', required=False)
status_display = CharField(read_only=True, source='get_status_display')
risk_level = ReadOnlyField()
technical_details = JSONField(decoder=None, encoder=None, help_text='例如: {"os": "Ubuntu 22.04", "ip": "192.168.1.10", "cpu": "8 cores"}', label='技術細節', required=False, style={'base_template': 'textarea.html'})
acquisition_date = DateField(allow_null=True, label='取得日期', required=False)
created_at = DateTimeField(label='建立時間', read_only=True)
updated_at = DateTimeField(label='更新時間', read_only=True) |
/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py, line 253, in data
'You should either call `.is_valid()` first, '
'or access `.initial_data` instead.'
)
raise AssertionError(msg)
if not hasattr(self, '_data'):
if self.instance is not None and not getattr(self, '_errors', None):
self._data = self.to_representation(self.instance)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ …elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
self._data = self.to_representation(self.validated_data)
else:
self._data = self.get_initial()
return self._data
| Variable | Value |
|---|---|
| self | AssetSerializer(<Asset: DAT-SRC-001 - 原始程式碼倉庫>, context={'request': <rest_framework.request.Request: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'>, 'format': None, 'view': <assets.views.AssetViewSet object>}):
id = UUIDField(read_only=True)
asset_number = CharField(help_text='例如: AST-001', label='資產編號', max_length=50, validators=[<UniqueValidator(queryset=Asset.objects.all())>])
name = CharField(label='資產名稱', max_length=200)
description = CharField(allow_blank=True, label='描述', required=False, style={'base_template': 'textarea.html'})
asset_type = ChoiceField(choices=[('hardware', '硬體'), ('software', '軟體'), ('data', '資料'), ('people', '人員'), ('facility', '設施')], label='資產類型')
asset_type_display = CharField(read_only=True, source='get_asset_type_display')
asset_subtype = CharField(allow_blank=True, help_text='例如: 伺服器、工作站、資料庫等', label='資產子類型', max_length=50, required=False)
owner = PrimaryKeyRelatedField(allow_null=True, label='資產擁有者', queryset=User.objects.all(), required=False)
owner_detail = UserSimpleSerializer(read_only=True, source='owner')
custodian = PrimaryKeyRelatedField(allow_null=True, label='資產管理者', queryset=User.objects.all(), required=False)
custodian_detail = UserSimpleSerializer(read_only=True, source='custodian')
location = CharField(allow_blank=True, help_text='例如: 機房A-機櫃3', label='所在位置', max_length=200, required=False)
network_segment = CharField(allow_blank=True, label='網路區段', max_length=100, required=False)
confidentiality = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='機密性等級', required=False)
confidentiality_display = CharField(read_only=True, source='get_confidentiality_display')
integrity = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='完整性等級', required=False)
integrity_display = CharField(read_only=True, source='get_integrity_display')
availability = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='可用性等級', required=False)
availability_display = CharField(read_only=True, source='get_availability_display')
status = ChoiceField(choices=[('active', '使用中'), ('inactive', '閒置'), ('maintenance', '維護中'), ('decommissioned', '已報廢')], label='狀態', required=False)
status_display = CharField(read_only=True, source='get_status_display')
risk_level = ReadOnlyField()
technical_details = JSONField(decoder=None, encoder=None, help_text='例如: {"os": "Ubuntu 22.04", "ip": "192.168.1.10", "cpu": "8 cores"}', label='技術細節', required=False, style={'base_template': 'textarea.html'})
acquisition_date = DateField(allow_null=True, label='取得日期', required=False)
created_at = DateTimeField(label='建立時間', read_only=True)
updated_at = DateTimeField(label='更新時間', read_only=True) |
/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py, line 522, in to_representation
#
# For related fields with `use_pk_only_optimization` we need to
# resolve the pk value.
check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
if check_for_none is None:
ret[field.field_name] = None
else:
ret[field.field_name] = field.to_representation(attribute)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ …return ret
def validate(self, attrs):
return attrs
| Variable | Value |
|---|---|
| attribute | <User: auditor (稽核人員)> |
| check_for_none | <User: auditor (稽核人員)> |
| field | Error in formatting: AttributeError: 'str' object has no attribute '_meta' |
| fields | <generator object Serializer._readable_fields at 0x7fcc2d9e9630> |
| instance | <Asset: DAT-SRC-001 - 原始程式碼倉庫> |
| ret | OrderedDict([('id', '1d35714a-c0fe-4feb-b45e-1ab34c4b291d'),
('asset_number', 'DAT-SRC-001'),
('name', '原始程式碼倉庫'),
('description', 'Git 程式碼倉庫'),
('asset_type', 'data'),
('asset_type_display', '資料'),
('asset_subtype', 'source_code'),
('owner', UUID('a2ef09cd-2af3-403d-85ec-d3c01a3886d8'))]) |
| self | AssetSerializer(<Asset: DAT-SRC-001 - 原始程式碼倉庫>, context={'request': <rest_framework.request.Request: GET '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/'>, 'format': None, 'view': <assets.views.AssetViewSet object>}):
id = UUIDField(read_only=True)
asset_number = CharField(help_text='例如: AST-001', label='資產編號', max_length=50, validators=[<UniqueValidator(queryset=Asset.objects.all())>])
name = CharField(label='資產名稱', max_length=200)
description = CharField(allow_blank=True, label='描述', required=False, style={'base_template': 'textarea.html'})
asset_type = ChoiceField(choices=[('hardware', '硬體'), ('software', '軟體'), ('data', '資料'), ('people', '人員'), ('facility', '設施')], label='資產類型')
asset_type_display = CharField(read_only=True, source='get_asset_type_display')
asset_subtype = CharField(allow_blank=True, help_text='例如: 伺服器、工作站、資料庫等', label='資產子類型', max_length=50, required=False)
owner = PrimaryKeyRelatedField(allow_null=True, label='資產擁有者', queryset=User.objects.all(), required=False)
owner_detail = UserSimpleSerializer(read_only=True, source='owner')
custodian = PrimaryKeyRelatedField(allow_null=True, label='資產管理者', queryset=User.objects.all(), required=False)
custodian_detail = UserSimpleSerializer(read_only=True, source='custodian')
location = CharField(allow_blank=True, help_text='例如: 機房A-機櫃3', label='所在位置', max_length=200, required=False)
network_segment = CharField(allow_blank=True, label='網路區段', max_length=100, required=False)
confidentiality = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='機密性等級', required=False)
confidentiality_display = CharField(read_only=True, source='get_confidentiality_display')
integrity = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='完整性等級', required=False)
integrity_display = CharField(read_only=True, source='get_integrity_display')
availability = ChoiceField(choices=[('low', '低'), ('medium', '中'), ('high', '高')], label='可用性等級', required=False)
availability_display = CharField(read_only=True, source='get_availability_display')
status = ChoiceField(choices=[('active', '使用中'), ('inactive', '閒置'), ('maintenance', '維護中'), ('decommissioned', '已報廢')], label='狀態', required=False)
status_display = CharField(read_only=True, source='get_status_display')
risk_level = ReadOnlyField()
technical_details = JSONField(decoder=None, encoder=None, help_text='例如: {"os": "Ubuntu 22.04", "ip": "192.168.1.10", "cpu": "8 cores"}', label='技術細節', required=False, style={'base_template': 'textarea.html'})
acquisition_date = DateField(allow_null=True, label='取得日期', required=False)
created_at = DateTimeField(label='建立時間', read_only=True)
updated_at = DateTimeField(label='更新時間', read_only=True) |
/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py, line 507, in to_representation
def to_representation(self, instance):
"""
Object instance -> Dict of primitive datatypes.
"""
ret = OrderedDict()
fields = self._readable_fields
for field in fields:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ …try:
attribute = field.get_attribute(instance)
except SkipField:
continue
# We skip `to_representation` for `None` values so that fields do
| Variable | Value |
|---|---|
| fields | <generator object Serializer._readable_fields at 0x7fcc2d9e8e10> |
| instance | <User: auditor (稽核人員)> |
| ret | OrderedDict() |
| self | Error in formatting: AttributeError: 'str' object has no attribute '_meta' |
/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py, line 368, in _readable_fields
def _writable_fields(self):
for field in self.fields.values():
if not field.read_only:
yield field
@property
def _readable_fields(self):
for field in self.fields.values():
^^^^^^^^^^^ …if not field.write_only:
yield field
def get_fields(self):
"""
Returns a dictionary of {field_name: field_instance}.| Variable | Value |
|---|---|
| self | Error in formatting: AttributeError: 'str' object has no attribute '_meta' |
/usr/local/lib/python3.11/site-packages/django/utils/functional.py, line 57, in __get__
"""
Call the function and put the return value in instance.__dict__ so that
subsequent attribute access on the instance returns the cached value
instead of calling cached_property.__get__().
"""
if instance is None:
return self
res = instance.__dict__[self.name] = self.func(instance)
^^^^^^^^^^^^^^^^^^^ …return res
class classproperty:
"""
Decorator that converts a method with a single cls argument into a property
| Variable | Value |
|---|---|
| cls | <class 'assets.serializers.UserSimpleSerializer'> |
| instance | Error in formatting: AttributeError: 'str' object has no attribute '_meta' |
| self | <django.utils.functional.cached_property object at 0x7fcc2e5d0850> |
/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py, line 356, in fields
"""
A dictionary of {field_name: field_instance}."""
# `fields` is evaluated lazily. We do this to ensure that we don't
# have issues importing modules that use ModelSerializers as fields,
# even if Django's app-loading stage has not yet run.
fields = BindingDict(self)
for key, value in self.get_fields().items():
^^^^^^^^^^^^^^^^^ …fields[key] = value
return fields
@property
def _writable_fields(self):
for field in self.fields.values():
| Variable | Value |
|---|---|
| fields | {} |
| self | Error in formatting: AttributeError: 'str' object has no attribute '_meta' |
/usr/local/lib/python3.11/site-packages/rest_framework/serializers.py, line 1051, in get_fields
depth = getattr(self.Meta, 'depth', 0)
if depth is not None:
assert depth >= 0, "'depth' may not be negative."
assert depth <= 10, "'depth' may not be greater than 10."
# Retrieve metadata about fields & relationships on the model class.
info = model_meta.get_field_info(model)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ …field_names = self.get_field_names(declared_fields, info)
# Determine any extra field arguments and hidden fields that
# should be included
extra_kwargs = self.get_extra_kwargs()
extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs(
| Variable | Value |
|---|---|
| declared_fields | OrderedDict([('full_name', SerializerMethodField())]) |
| depth | 0 |
| model | 'accounts.User' |
| self | Error in formatting: AttributeError: 'str' object has no attribute '_meta' |
/usr/local/lib/python3.11/site-packages/rest_framework/utils/model_meta.py, line 35, in get_field_info
def get_field_info(model):
"""
Given a model class, returns a `FieldInfo` instance, which is a
`namedtuple`, containing metadata about the various field types on the model
including information about their relationships.
"""
opts = model._meta.concrete_model._meta
^^^^^^^^^^^ …pk = _get_pk(opts)
fields = _get_fields(opts)
forward_relations = _get_forward_relationships(opts)
reverse_relations = _get_reverse_relationships(opts)
fields_and_pk = _merge_fields_and_pk(pk, fields)
| Variable | Value |
|---|---|
| model | 'accounts.User' |
AnonymousUser
No GET data
No POST data
No FILES data
No cookie data
| Variable | Value |
|---|---|
| ALLOWED_HOSTS | 'localhost,127.0.0.1,backend' |
| CONTENT_LENGTH | '' |
| CONTENT_TYPE | 'text/plain' |
| CORS_ALLOWED_ORIGINS | 'http://localhost:3000' |
| DATABASE_URL | 'postgresql://iso27001_user:iso27001_pass@db:5432/iso27001_db' |
| DEBUG | 'True' |
| DJANGO_SETTINGS_MODULE | 'config.settings' |
| GATEWAY_INTERFACE | 'CGI/1.1' |
| GPG_KEY | '********************' |
| HOME | '/root' |
| HOSTNAME | 'b0b1813d0d3b' |
| HTTP_ACCEPT | '*/*' |
| HTTP_AUTHORIZATION | ('Bearer '
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzYxOTMwNzk2LCJpYXQiOjE3NjE5MjM1OTYsImp0aSI6ImFlNjIxNTk3MmMyZTQ4MzhhZjQ4N2Y5YmMzZWFiZWIwIiwidXNlcl9pZCI6ImJlMmFhYWUwLWIwYzQtNDQ1MC05YzhiLTQxYWRjZTUyNjQ2NyJ9.8uQvZuoU8nAcNap7ZwKX427DRgh7CTxcRAcmcJcTUj8') |
| HTTP_HOST | 'localhost:8000' |
| HTTP_USER_AGENT | 'curl/7.88.1' |
| LANG | 'C.UTF-8' |
| PATH | '/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' |
| PATH_INFO | '/api/assets/1d35714a-c0fe-4feb-b45e-1ab34c4b291d/' |
| PYTHON_SHA256 | '8fb5f9fbc7609fa822cb31549884575db7fd9657cbffb89510b5d7975963a83a' |
| PYTHON_VERSION | '3.11.13' |
| QUERY_STRING | '' |
| REDIS_URL | 'redis://redis:6379/0' |
| REMOTE_ADDR | '172.28.0.1' |
| REMOTE_HOST | '' |
| REQUEST_METHOD | 'GET' |
| RUN_MAIN | 'true' |
| SCRIPT_NAME | '' |
| SECRET_KEY | '********************' |
| SERVER_NAME | 'b0b1813d0d3b' |
| SERVER_PORT | '8000' |
| SERVER_PROTOCOL | 'HTTP/1.1' |
| SERVER_SOFTWARE | 'WSGIServer/0.2' |
| TZ | 'Asia/Taipei' |
| wsgi.errors | <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'> |
| wsgi.file_wrapper | <class 'wsgiref.util.FileWrapper'> |
| wsgi.input | <django.core.handlers.wsgi.LimitedStream object at 0x7fcc2d567b50> |
| wsgi.multiprocess | False |
| wsgi.multithread | True |
| wsgi.run_once | False |
| wsgi.url_scheme | 'http' |
| wsgi.version | (1, 0) |
config.settings| Setting | Value |
|---|---|
| ABSOLUTE_URL_OVERRIDES | {} |
| ADMINS | [] |
| ALLOWED_HOSTS | ['localhost', '127.0.0.1', 'backend'] |
| APPEND_SLASH | True |
| AUTHENTICATION_BACKENDS | ['django.contrib.auth.backends.ModelBackend'] |
| AUTH_PASSWORD_VALIDATORS | '********************' |
| AUTH_USER_MODEL | 'accounts.User' |
| BASE_DIR | PosixPath('/app') |
| CACHES | {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}} |
| CACHE_MIDDLEWARE_ALIAS | 'default' |
| CACHE_MIDDLEWARE_KEY_PREFIX | '********************' |
| CACHE_MIDDLEWARE_SECONDS | 600 |
| CELERY_ACCEPT_CONTENT | ['json'] |
| CELERY_BROKER_URL | 'redis://redis:6379/0' |
| CELERY_RESULT_BACKEND | 'redis://redis:6379/0' |
| CELERY_RESULT_SERIALIZER | 'json' |
| CELERY_TASK_SERIALIZER | 'json' |
| CELERY_TIMEZONE | 'Asia/Taipei' |
| CORS_ALLOWED_ORIGINS | ['http://localhost:3000', 'http://127.0.0.1:3000'] |
| CORS_ALLOW_CREDENTIALS | True |
| CSRF_COOKIE_AGE | 31449600 |
| CSRF_COOKIE_DOMAIN | None |
| CSRF_COOKIE_HTTPONLY | False |
| CSRF_COOKIE_MASKED | False |
| CSRF_COOKIE_NAME | 'csrftoken' |
| CSRF_COOKIE_PATH | '/' |
| CSRF_COOKIE_SAMESITE | 'Lax' |
| CSRF_COOKIE_SECURE | False |
| CSRF_FAILURE_VIEW | 'django.views.csrf.csrf_failure' |
| CSRF_HEADER_NAME | 'HTTP_X_CSRFTOKEN' |
| CSRF_TRUSTED_ORIGINS | [] |
| CSRF_USE_SESSIONS | False |
| DATABASES | {'default': {'ATOMIC_REQUESTS': False,
'AUTOCOMMIT': True,
'CONN_HEALTH_CHECKS': False,
'CONN_MAX_AGE': 600,
'ENGINE': 'django.db.backends.postgresql',
'HOST': 'db',
'NAME': 'iso27001_db',
'OPTIONS': {},
'PASSWORD': '********************',
'PORT': 5432,
'TEST': {'CHARSET': None,
'COLLATION': None,
'MIGRATE': True,
'MIRROR': None,
'NAME': None},
'TIME_ZONE': None,
'USER': 'iso27001_user'}} |
| DATABASE_ROUTERS | [] |
| DATA_UPLOAD_MAX_MEMORY_SIZE | 2621440 |
| DATA_UPLOAD_MAX_NUMBER_FIELDS | 1000 |
| DATA_UPLOAD_MAX_NUMBER_FILES | 100 |
| DATETIME_FORMAT | 'N j, Y, P' |
| DATETIME_INPUT_FORMATS | ['%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M:%S.%f', '%Y-%m-%d %H:%M', '%m/%d/%Y %H:%M:%S', '%m/%d/%Y %H:%M:%S.%f', '%m/%d/%Y %H:%M', '%m/%d/%y %H:%M:%S', '%m/%d/%y %H:%M:%S.%f', '%m/%d/%y %H:%M'] |
| DATE_FORMAT | 'N j, Y' |
| DATE_INPUT_FORMATS | ['%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', '%b %d %Y', '%b %d, %Y', '%d %b %Y', '%d %b, %Y', '%B %d %Y', '%B %d, %Y', '%d %B %Y', '%d %B, %Y'] |
| DEBUG | True |
| DEBUG_PROPAGATE_EXCEPTIONS | False |
| DECIMAL_SEPARATOR | '.' |
| DEFAULT_AUTO_FIELD | 'django.db.models.BigAutoField' |
| DEFAULT_CHARSET | 'utf-8' |
| DEFAULT_EXCEPTION_REPORTER | 'django.views.debug.ExceptionReporter' |
| DEFAULT_EXCEPTION_REPORTER_FILTER | 'django.views.debug.SafeExceptionReporterFilter' |
| DEFAULT_FILE_STORAGE | 'django.core.files.storage.FileSystemStorage' |
| DEFAULT_FROM_EMAIL | 'webmaster@localhost' |
| DEFAULT_INDEX_TABLESPACE | '' |
| DEFAULT_TABLESPACE | '' |
| DISALLOWED_USER_AGENTS | [] |
| EMAIL_BACKEND | 'django.core.mail.backends.smtp.EmailBackend' |
| EMAIL_HOST | 'localhost' |
| EMAIL_HOST_PASSWORD | '********************' |
| EMAIL_HOST_USER | '' |
| EMAIL_PORT | 25 |
| EMAIL_SSL_CERTFILE | None |
| EMAIL_SSL_KEYFILE | '********************' |
| EMAIL_SUBJECT_PREFIX | '[Django] ' |
| EMAIL_TIMEOUT | None |
| EMAIL_USE_LOCALTIME | False |
| EMAIL_USE_SSL | False |
| EMAIL_USE_TLS | False |
| FILE_UPLOAD_DIRECTORY_PERMISSIONS | None |
| FILE_UPLOAD_HANDLERS | ['django.core.files.uploadhandler.MemoryFileUploadHandler', 'django.core.files.uploadhandler.TemporaryFileUploadHandler'] |
| FILE_UPLOAD_MAX_MEMORY_SIZE | 2621440 |
| FILE_UPLOAD_PERMISSIONS | 420 |
| FILE_UPLOAD_TEMP_DIR | None |
| FIRST_DAY_OF_WEEK | 0 |
| FIXTURE_DIRS | [] |
| FORCE_SCRIPT_NAME | None |
| FORMAT_MODULE_PATH | None |
| FORM_RENDERER | 'django.forms.renderers.DjangoTemplates' |
| IGNORABLE_404_URLS | [] |
| INSTALLED_APPS | ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'rest_framework_simplejwt', 'corsheaders', 'django_filters', 'accounts', 'organizations', 'assets', 'documents', 'controls'] |
| INTERNAL_IPS | [] |
| LANGUAGES | [('af', 'Afrikaans'),
('ar', 'Arabic'),
('ar-dz', 'Algerian Arabic'),
('ast', 'Asturian'),
('az', 'Azerbaijani'),
('bg', 'Bulgarian'),
('be', 'Belarusian'),
('bn', 'Bengali'),
('br', 'Breton'),
('bs', 'Bosnian'),
('ca', 'Catalan'),
('ckb', 'Central Kurdish (Sorani)'),
('cs', 'Czech'),
('cy', 'Welsh'),
('da', 'Danish'),
('de', 'German'),
('dsb', 'Lower Sorbian'),
('el', 'Greek'),
('en', 'English'),
('en-au', 'Australian English'),
('en-gb', 'British English'),
('eo', 'Esperanto'),
('es', 'Spanish'),
('es-ar', 'Argentinian Spanish'),
('es-co', 'Colombian Spanish'),
('es-mx', 'Mexican Spanish'),
('es-ni', 'Nicaraguan Spanish'),
('es-ve', 'Venezuelan Spanish'),
('et', 'Estonian'),
('eu', 'Basque'),
('fa', 'Persian'),
('fi', 'Finnish'),
('fr', 'French'),
('fy', 'Frisian'),
('ga', 'Irish'),
('gd', 'Scottish Gaelic'),
('gl', 'Galician'),
('he', 'Hebrew'),
('hi', 'Hindi'),
('hr', 'Croatian'),
('hsb', 'Upper Sorbian'),
('hu', 'Hungarian'),
('hy', 'Armenian'),
('ia', 'Interlingua'),
('id', 'Indonesian'),
('ig', 'Igbo'),
('io', 'Ido'),
('is', 'Icelandic'),
('it', 'Italian'),
('ja', 'Japanese'),
('ka', 'Georgian'),
('kab', 'Kabyle'),
('kk', 'Kazakh'),
('km', 'Khmer'),
('kn', 'Kannada'),
('ko', 'Korean'),
('ky', 'Kyrgyz'),
('lb', 'Luxembourgish'),
('lt', 'Lithuanian'),
('lv', 'Latvian'),
('mk', 'Macedonian'),
('ml', 'Malayalam'),
('mn', 'Mongolian'),
('mr', 'Marathi'),
('ms', 'Malay'),
('my', 'Burmese'),
('nb', 'Norwegian Bokmål'),
('ne', 'Nepali'),
('nl', 'Dutch'),
('nn', 'Norwegian Nynorsk'),
('os', 'Ossetic'),
('pa', 'Punjabi'),
('pl', 'Polish'),
('pt', 'Portuguese'),
('pt-br', 'Brazilian Portuguese'),
('ro', 'Romanian'),
('ru', 'Russian'),
('sk', 'Slovak'),
('sl', 'Slovenian'),
('sq', 'Albanian'),
('sr', 'Serbian'),
('sr-latn', 'Serbian Latin'),
('sv', 'Swedish'),
('sw', 'Swahili'),
('ta', 'Tamil'),
('te', 'Telugu'),
('tg', 'Tajik'),
('th', 'Thai'),
('tk', 'Turkmen'),
('tr', 'Turkish'),
('tt', 'Tatar'),
('udm', 'Udmurt'),
('uk', 'Ukrainian'),
('ur', 'Urdu'),
('uz', 'Uzbek'),
('vi', 'Vietnamese'),
('zh-hans', 'Simplified Chinese'),
('zh-hant', 'Traditional Chinese')] |
| LANGUAGES_BIDI | ['he', 'ar', 'ar-dz', 'ckb', 'fa', 'ur'] |
| LANGUAGE_CODE | 'zh-hant' |
| LANGUAGE_COOKIE_AGE | None |
| LANGUAGE_COOKIE_DOMAIN | None |
| LANGUAGE_COOKIE_HTTPONLY | False |
| LANGUAGE_COOKIE_NAME | 'django_language' |
| LANGUAGE_COOKIE_PATH | '/' |
| LANGUAGE_COOKIE_SAMESITE | None |
| LANGUAGE_COOKIE_SECURE | False |
| LOCALE_PATHS | [] |
| LOGGING | {} |
| LOGGING_CONFIG | 'logging.config.dictConfig' |
| LOGIN_REDIRECT_URL | '/accounts/profile/' |
| LOGIN_URL | '/accounts/login/' |
| LOGOUT_REDIRECT_URL | None |
| MANAGERS | [] |
| MEDIA_ROOT | PosixPath('/app/media') |
| MEDIA_URL | '/media/' |
| MESSAGE_STORAGE | 'django.contrib.messages.storage.fallback.FallbackStorage' |
| MIDDLEWARE | ['django.middleware.security.SecurityMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware'] |
| MIGRATION_MODULES | {} |
| MONTH_DAY_FORMAT | 'F j' |
| NUMBER_GROUPING | 0 |
| PASSWORD_HASHERS | '********************' |
| PASSWORD_RESET_TIMEOUT | '********************' |
| PREPEND_WWW | False |
| REDIS_URL | 'redis://redis:6379/0' |
| REST_FRAMEWORK | {'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S',
'DATE_FORMAT': '%Y-%m-%d',
'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'],
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
'rest_framework.filters.OrderingFilter'],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated'],
'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer'],
'PAGE_SIZE': 25} |
| ROOT_URLCONF | 'config.urls' |
| SECRET_KEY | '********************' |
| SECRET_KEY_FALLBACKS | '********************' |
| SECURE_CONTENT_TYPE_NOSNIFF | True |
| SECURE_CROSS_ORIGIN_OPENER_POLICY | 'same-origin' |
| SECURE_HSTS_INCLUDE_SUBDOMAINS | False |
| SECURE_HSTS_PRELOAD | False |
| SECURE_HSTS_SECONDS | 0 |
| SECURE_PROXY_SSL_HEADER | None |
| SECURE_REDIRECT_EXEMPT | [] |
| SECURE_REFERRER_POLICY | 'same-origin' |
| SECURE_SSL_HOST | None |
| SECURE_SSL_REDIRECT | False |
| SERVER_EMAIL | 'root@localhost' |
| SESSION_CACHE_ALIAS | 'default' |
| SESSION_COOKIE_AGE | 1209600 |
| SESSION_COOKIE_DOMAIN | None |
| SESSION_COOKIE_HTTPONLY | True |
| SESSION_COOKIE_NAME | 'sessionid' |
| SESSION_COOKIE_PATH | '/' |
| SESSION_COOKIE_SAMESITE | 'Lax' |
| SESSION_COOKIE_SECURE | False |
| SESSION_ENGINE | 'django.contrib.sessions.backends.db' |
| SESSION_EXPIRE_AT_BROWSER_CLOSE | False |
| SESSION_FILE_PATH | None |
| SESSION_SAVE_EVERY_REQUEST | False |
| SESSION_SERIALIZER | 'django.contrib.sessions.serializers.JSONSerializer' |
| SETTINGS_MODULE | 'config.settings' |
| SHORT_DATETIME_FORMAT | 'm/d/Y P' |
| SHORT_DATE_FORMAT | 'm/d/Y' |
| SIGNING_BACKEND | 'django.core.signing.TimestampSigner' |
| SILENCED_SYSTEM_CHECKS | [] |
| SIMPLE_JWT | {'ACCESS_TOKEN_LIFETIME': '********************',
'ALGORITHM': 'HS256',
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_TOKEN_CLASSES': '********************',
'BLACKLIST_AFTER_ROTATION': True,
'REFRESH_TOKEN_LIFETIME': '********************',
'ROTATE_REFRESH_TOKENS': '********************',
'SIGNING_KEY': '********************',
'TOKEN_TYPE_CLAIM': '********************',
'UPDATE_LAST_LOGIN': True,
'USER_ID_CLAIM': 'user_id',
'USER_ID_FIELD': 'id'} |
| STATICFILES_DIRS | [] |
| STATICFILES_FINDERS | ['django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder'] |
| STATICFILES_STORAGE | 'django.contrib.staticfiles.storage.StaticFilesStorage' |
| STATIC_ROOT | PosixPath('/app/staticfiles') |
| STATIC_URL | '/static/' |
| STORAGES | {'default': {'BACKEND': 'django.core.files.storage.FileSystemStorage'},
'staticfiles': {'BACKEND': 'django.contrib.staticfiles.storage.StaticFilesStorage'}} |
| TEMPLATES | [{'APP_DIRS': True,
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'OPTIONS': {'context_processors': ['django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages']}}] |
| TEST_NON_SERIALIZED_APPS | [] |
| TEST_RUNNER | 'django.test.runner.DiscoverRunner' |
| THOUSAND_SEPARATOR | ',' |
| TIME_FORMAT | 'P' |
| TIME_INPUT_FORMATS | ['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] |
| TIME_ZONE | 'Asia/Taipei' |
| USE_DEPRECATED_PYTZ | False |
| USE_I18N | True |
| USE_L10N | True |
| USE_THOUSAND_SEPARATOR | False |
| USE_TZ | True |
| USE_X_FORWARDED_HOST | False |
| USE_X_FORWARDED_PORT | False |
| WSGI_APPLICATION | 'config.wsgi.application' |
| X_FRAME_OPTIONS | 'DENY' |
| YEAR_MONTH_FORMAT | 'F Y' |
You’re seeing this error because you have DEBUG = True in your
Django settings file. Change that to False, and Django will
display a standard page generated by the handler for this status code.