Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
aa.gusti
/
opensipkd-base
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Settings
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit 712624f7
authored
Jul 11, 2026
by
aa.gustiana@gmail.com
Browse Files
Options
Browse Files
Tag
Download
Plain Diff
Enhance logging and template definitions for improved error handling and response clarity
2 parents
36e817a9
b417aa72
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
53 additions
and
36 deletions
opensipkd/base/views/api_base.py
opensipkd/base/views/base_views.py
opensipkd/base/views/templates/404.pt
opensipkd/base/views/templates/500.pt
opensipkd/base/views/templates/base3.1.pt
opensipkd/base/views/templates/base5.pt
opensipkd/base/views/templates/login.pt
opensipkd/base/views/templates/logout.pt
opensipkd/base/widgets/templates/file_upload.pt
opensipkd/base/widgets/widget_os.py
opensipkd/detable/detable.py
opensipkd/detable/widget.py
opensipkd/base/views/api_base.py
View file @
712624f
...
@@ -223,6 +223,7 @@ class ApiViews(APIView):
...
@@ -223,6 +223,7 @@ class ApiViews(APIView):
"""
"""
Mengubah data menjadi list dan convert objek menjadi string
Mengubah data menjadi list dan convert objek menjadi string
"""
"""
_log
.
debug
(
"Response to Client:
%
s"
,
data
)
if
not
isinstance
(
data
,
list
):
if
not
isinstance
(
data
,
list
):
data
=
[
data
]
data
=
[
data
]
for
i
,
item
in
enumerate
(
data
):
for
i
,
item
in
enumerate
(
data
):
...
...
opensipkd/base/views/base_views.py
View file @
712624f
...
@@ -57,9 +57,11 @@ log = logging.getLogger(__name__)
...
@@ -57,9 +57,11 @@ log = logging.getLogger(__name__)
# }
# }
class
AddSchema
(
colander
.
Schema
):
class
AddSchema
(
colander
.
Schema
):
kode
=
colander
.
SchemaNode
(
colander
.
String
(),
title
=
"Kode"
,
validator
=
colander
.
Length
(
max
=
50
),
kode
=
colander
.
SchemaNode
(
colander
.
String
(),
title
=
"Kode"
,
validator
=
colander
.
Length
(
max
=
50
),
search_method
=
"string_contains"
,
search_method
=
"string_contains"
,
searchable
=
True
,
searchable
=
True
,
aligned
=
"text-left"
)
)
class
UploadSchema
(
colander
.
Schema
):
class
UploadSchema
(
colander
.
Schema
):
upload
=
colander
.
SchemaNode
(
upload
=
colander
.
SchemaNode
(
...
@@ -143,7 +145,7 @@ class BaseView(object):
...
@@ -143,7 +145,7 @@ class BaseView(object):
self
.
list_form
=
None
# List dam Form
self
.
list_form
=
None
# List dam Form
self
.
form_list
=
None
# Form kemudian detail list
self
.
form_list
=
None
# Form kemudian detail list
self
.
global_search
=
False
self
.
form_scripts
=
"""
self
.
form_scripts
=
"""
$('#parent_nm').bind('typeahead:selected', function(obj, datum) {
$('#parent_nm').bind('typeahead:selected', function(obj, datum) {
$('#parent_id').val(datum.id);
$('#parent_id').val(datum.id);
...
@@ -590,9 +592,10 @@ class BaseView(object):
...
@@ -590,9 +592,10 @@ class BaseView(object):
if
not
self
.
columns
:
if
not
self
.
columns
:
columns
=
[]
columns
=
[]
for
d
in
list_schema
():
for
d
in
list_schema
():
global_search
=
getattr
(
d
,
"global_search"
,
False
)
global_search
=
hasattr
(
d
,
"global_search"
)
\
and
getattr
(
d
,
"global_search"
,
self
.
global_search
)
or
self
.
global_search
search_method
=
hasattr
(
d
,
"search_method"
)
\
search_method
=
hasattr
(
d
,
"search_method"
)
\
and
getattr
(
d
,
"search_method"
)
or
"string_contains"
and
getattr
(
d
,
"search_method"
,
"string_contains"
)
or
"string_contains"
if
hasattr
(
d
,
"field"
):
if
hasattr
(
d
,
"field"
):
if
isinstance
(
d
.
field
,
str
):
if
isinstance
(
d
.
field
,
str
):
columns
.
append
(
columns
.
append
(
...
@@ -825,8 +828,10 @@ class BaseView(object):
...
@@ -825,8 +828,10 @@ class BaseView(object):
def
view_view
(
self
,
**
kwargs
):
def
view_view
(
self
,
**
kwargs
):
request
=
self
.
req
request
=
self
.
req
row
=
self
.
query_id
()
.
first
()
qry
=
self
.
query_id
()
row
=
qry
.
first
()
if
not
row
:
if
not
row
:
log
.
debug
(
str
(
qry
.
statement
.
compile
(
compile_kwargs
=
{
'literal_binds'
:
True
})))
return
self
.
id_not_found
()
return
self
.
id_not_found
()
self
.
ses
[
"readonly"
]
=
True
self
.
ses
[
"readonly"
]
=
True
...
@@ -1196,6 +1201,7 @@ class BaseView(object):
...
@@ -1196,6 +1201,7 @@ class BaseView(object):
msg
=
f
"Data yang dicari Tidak Ditemukan ID:"
\
msg
=
f
"Data yang dicari Tidak Ditemukan ID:"
\
f
" {self.req.matchdict['id']}."
f
" {self.req.matchdict['id']}."
self
.
req
.
session
.
flash
(
msg
,
'error'
)
self
.
req
.
session
.
flash
(
msg
,
'error'
)
log
.
error
(
msg
)
return
self
.
route_list
(
**
kwargs
)
return
self
.
route_list
(
**
kwargs
)
def
get_values
(
self
,
row
,
istime
=
False
,
null
=
False
):
def
get_values
(
self
,
row
,
istime
=
False
,
null
=
False
):
...
@@ -1250,6 +1256,8 @@ class BaseView(object):
...
@@ -1250,6 +1256,8 @@ class BaseView(object):
is_object
=
kwargs
.
get
(
"is_object"
,
self
.
is_object
)
is_object
=
kwargs
.
get
(
"is_object"
,
self
.
is_object
)
kwargs
[
"is_object"
]
=
is_object
kwargs
[
"is_object"
]
=
is_object
if
not
row
:
if
not
row
:
log
.
debug
(
self
.
query_id
()
.
statement
.
compile
(
compile_kwargs
=
{
'literal_binds'
:
True
}))
return
self
.
id_not_found
(
**
kwargs
)
return
self
.
id_not_found
(
**
kwargs
)
if
self
.
edit_restrict
(
row
):
if
self
.
edit_restrict
(
row
):
...
@@ -1350,6 +1358,9 @@ class BaseView(object):
...
@@ -1350,6 +1358,9 @@ class BaseView(object):
is_object
=
kwargs
.
get
(
"is_object"
,
self
.
is_object
)
is_object
=
kwargs
.
get
(
"is_object"
,
self
.
is_object
)
kwargs
[
"is_object"
]
=
is_object
kwargs
[
"is_object"
]
=
is_object
if
not
row
:
if
not
row
:
log
.
debug
(
str
(
q
.
statement
.
compile
(
compile_kwargs
=
{
'literal_binds'
:
True
})))
return
self
.
id_not_found
()
return
self
.
id_not_found
()
if
not
self
.
bindings
:
if
not
self
.
bindings
:
self
.
bindings
=
self
.
get_bindings
(
row
)
self
.
bindings
=
self
.
get_bindings
(
row
)
...
...
opensipkd/base/views/templates/404.pt
View file @
712624f
<html
tal:define=
"home
''
;"
>
<html
tal:define=
"home
request.home.strip('/')
;"
>
<body>
<body>
<div
class=
"well"
>
<div
class=
"well"
>
<h2>
${request.app_name}
</h2>
<h2>
${request.app_name}
</h2>
...
...
opensipkd/base/views/templates/500.pt
View file @
712624f
<html>
<html
tal:define=
"home request.home.strip('/');"
>
<body>
<body>
<div
class=
"well"
>
<div
class=
"well"
>
...
...
opensipkd/base/views/templates/base3.1.pt
View file @
712624f
<!DOCTYPE html>
<!DOCTYPE html>
<html
lang=
"en-us"
tal:define=
"
<html
lang=
"en-us"
tal:define=
"
home request.home;
home request.home
.strip('/')
;
user_path ['user', 'user-add', 'user-edit', 'user-view', 'user-delete'];
user_path ['user', 'user-add', 'user-edit', 'user-view', 'user-delete'];
user_area_path ['user-area', 'user-area-add', 'user-area-edit', 'user-area-view', 'user-area-delete'];
user_area_path ['user-area', 'user-area-add', 'user-area-edit', 'user-area-view', 'user-area-delete'];
user_dep_path ['user-departemen', 'user-departemen-add', 'user-departemen-edit', 'user-departemen-view', 'user-departemen-delete'];
user_dep_path ['user-departemen', 'user-departemen-add', 'user-departemen-edit', 'user-departemen-view', 'user-departemen-delete'];
...
...
opensipkd/base/views/templates/base5.pt
View file @
712624f
...
@@ -5,13 +5,9 @@
...
@@ -5,13 +5,9 @@
css css|[];
css css|[];
js js|[];
js js|[];
"
>
"
>
<head>
<head>
<!--<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">-->
<!--<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">-->
<title>
${request.app_name} | ${request.company}
</title>
<title>
${request.app_name} | ${request.company}
</title>
<meta
name=
"description"
content=
""
>
<meta
name=
"description"
content=
""
>
<meta
name=
"author"
content=
""
>
<meta
name=
"author"
content=
""
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
>
...
@@ -207,8 +203,6 @@
...
@@ -207,8 +203,6 @@
</span>
</span>
</aside>
</aside>
<!-- END NAVIGATION -->
<!-- END NAVIGATION -->
<!-- JS -->
<!-- JS -->
<script
src=
"${home}/static/v3/js/jquery-2.1.1.min.js"
></script>
<script
src=
"${home}/static/v3/js/jquery-2.1.1.min.js"
></script>
<script>
<script>
...
...
opensipkd/base/views/templates/login.pt
View file @
712624f
<!DOCTYPE html>
<!DOCTYPE html>
<html
lang=
"en"
tal:define=
"home request.home;"
>
<html
lang=
"en"
tal:define=
"home request.home
.strip('/')
;"
>
<head>
<head>
<meta
charset=
"utf-8"
>
<meta
charset=
"utf-8"
>
...
...
opensipkd/base/views/templates/logout.pt
View file @
712624f
<!DOCTYPE html>
<!DOCTYPE html>
<html
lang=
"en"
tal:define=
"home request.home;"
>
<html
lang=
"en"
tal:define=
"home request.home
.strip('/')
;"
>
<head>
<head>
<meta
charset=
"utf-8"
>
<meta
charset=
"utf-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
>
...
...
opensipkd/base/widgets/templates/file_upload.pt
View file @
712624f
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
css_class css_class|field.widget.css_class;
css_class css_class|field.widget.css_class;
style style|field.widget.style;
style style|field.widget.style;
preview_url cstruct.get('preview_url')|'';
preview_url cstruct.get('preview_url')|'';
ext str(cstruct.get('filename').split('.')[-1:][0]).lower()|
[]
;
ext str(cstruct.get('filename').split('.')[-1:][0]).lower()|
''
;
fname str(cstruct.get('filename'))|'';
fname str(cstruct.get('filename'))|'';
delete cstruct.get('delete')|'';
delete cstruct.get('delete')|'';
maxsize field.widget.size|5242880;
maxsize field.widget.size|5242880;
...
@@ -10,8 +10,12 @@
...
@@ -10,8 +10,12 @@
video ['avi', 'mov', 'mp4']
video ['avi', 'mov', 'mp4']
">
">
${field.start_mapping()}
${field.start_mapping()}
<div class="thumbnail" tal:condition="not ext or ext ==''">
<img id="preview-${oid}" alt="" src="${preview_url}" style="${style}"
onload="window.URL.revokeObjectURL(this.src);"></img>
</div>
<div class="thumbnail" tal:condition="ext in img or ext in video or ext=='pdf'">
<div class="thumbnail" tal:condition="ext in img or ext in video or ext=='pdf'">
<img tal:condition="ext in img" id="preview-${oid}" alt="" src="${preview_url}" style="${style}"
<img tal:condition="ext in img
or ext
" id="preview-${oid}" alt="" src="${preview_url}" style="${style}"
onload="window.URL.revokeObjectURL(this.src);"></img>
onload="window.URL.revokeObjectURL(this.src);"></img>
<video tal:condition="ext in video" style="${style}" controls src="${preview_url}" type="video/${ext}"
<video tal:condition="ext in video" style="${style}" controls src="${preview_url}" type="video/${ext}"
id="preview-${oid}">
id="preview-${oid}">
...
...
opensipkd/base/widgets/widget_os.py
View file @
712624f
from
pyramid.csrf
import
new_csrf_token
,
get_csrf_token
from
iso8601.iso8601
import
ISO8601_REGEX
# from deform.widget import str
import
json
import
json
import
logging
import
logging
from
pyramid.csrf
import
new_csrf_token
,
get_csrf_token
from
pyramid.csrf
import
new_csrf_token
,
get_csrf_token
from
iso8601.iso8601
import
ISO8601_REGEX
from
iso8601.iso8601
import
ISO8601_REGEX
from
colander
import
SchemaNode
,
null
,
Mapping
,
Invalid
# , str
ing_types
from
colander
import
SchemaNode
,
null
,
Mapping
,
Invalid
# , str
# from colander import compat # tidak ada di colander 2.0
# from colander import compat # tidak ada di colander 2.0
from
deform
import
widget
from
deform
import
widget
# from deform.compat import sequence_types, text_type, text_
# from deform.compat import sequence_types, text_type, text_
...
@@ -16,7 +19,7 @@ from deform.widget import (
...
@@ -16,7 +19,7 @@ from deform.widget import (
from
opensipkd.tools.captcha
import
img_captcha
from
opensipkd.tools.captcha
import
img_captcha
_logging
=
logging
.
getLogger
(
__name__
)
_logging
=
logging
.
getLogger
(
__name__
)
sequence_types
=
(
list
,
range
,
tuple
)
class
DokumenWidget
(
Widget
):
class
DokumenWidget
(
Widget
):
template
=
"opensipkd.base:/widgets/templates/dokumen.pt"
template
=
"opensipkd.base:/widgets/templates/dokumen.pt"
readonly_template
=
"opensipkd.base:/widgets/templates/readonly/dokumen.pt"
readonly_template
=
"opensipkd.base:/widgets/templates/readonly/dokumen.pt"
...
@@ -257,12 +260,12 @@ class AutocompleteMsInputWidget(AutocompleteInputWidget):
...
@@ -257,12 +260,12 @@ class AutocompleteMsInputWidget(AutocompleteInputWidget):
readonly
=
kw
.
get
(
"readonly"
,
self
.
readonly
)
readonly
=
kw
.
get
(
"readonly"
,
self
.
readonly
)
options
=
{}
options
=
{}
if
isinstance
(
self
.
values
,
str
):
#string_types
if
isinstance
(
self
.
values
,
str
):
options
[
"remote"
]
=
"
%
s?term=
%%
QUERY"
%
self
.
values
options
[
"remote"
]
=
"
%
s?term=
%%
QUERY"
%
self
.
values
else
:
else
:
# vals = []
# vals = []
# for v in self.values:
# for v in self.values:
# if not isinstance(v, str):
#string_types
# if not isinstance(v, str):
# vals.append(v[1])
# vals.append(v[1])
# if not vals:
# if not vals:
# vals = self.values
# vals = self.values
...
@@ -285,7 +288,7 @@ class AutocompleteMsInputWidget(AutocompleteInputWidget):
...
@@ -285,7 +288,7 @@ class AutocompleteMsInputWidget(AutocompleteInputWidget):
try
:
try
:
validated
=
self
.
_pstruct_schema
.
deserialize
(
pstruct
)
validated
=
self
.
_pstruct_schema
.
deserialize
(
pstruct
)
except
Invalid
as
exc
:
except
Invalid
as
exc
:
raise
Invalid
(
field
.
schema
,
text_
(
"Invalid pstruct:
%
s"
%
exc
)
)
raise
Invalid
(
field
.
schema
,
"Invalid pstruct:
%
s"
%
exc
)
auto_id
=
validated
[
"auto_id"
]
auto_id
=
validated
[
"auto_id"
]
auto_value
=
validated
[
"auto_value"
]
auto_value
=
validated
[
"auto_value"
]
...
@@ -394,7 +397,7 @@ class CaptchaWidget(Widget):
...
@@ -394,7 +397,7 @@ class CaptchaWidget(Widget):
def
deserialize
(
self
,
field
,
pstruct
):
def
deserialize
(
self
,
field
,
pstruct
):
if
pstruct
is
null
:
if
pstruct
is
null
:
return
null
return
null
elif
not
isinstance
(
pstruct
,
str
):
#string_types
elif
not
isinstance
(
pstruct
,
str
):
raise
Invalid
(
field
.
schema
,
"Pstruct is not a string"
)
raise
Invalid
(
field
.
schema
,
"Pstruct is not a string"
)
if
self
.
strip
:
if
self
.
strip
:
pstruct
=
pstruct
.
strip
()
pstruct
=
pstruct
.
strip
()
...
@@ -460,7 +463,7 @@ class ImageWidget(Widget):
...
@@ -460,7 +463,7 @@ class ImageWidget(Widget):
def
deserialize
(
self
,
field
,
pstruct
):
def
deserialize
(
self
,
field
,
pstruct
):
if
pstruct
is
null
:
if
pstruct
is
null
:
return
null
return
null
elif
not
isinstance
(
pstruct
,
str
):
# string_types
elif
not
isinstance
(
pstruct
,
str
):
raise
Invalid
(
field
.
schema
,
"Pstruct is not a string"
)
raise
Invalid
(
field
.
schema
,
"Pstruct is not a string"
)
if
self
.
strip
:
if
self
.
strip
:
pstruct
=
pstruct
.
strip
()
pstruct
=
pstruct
.
strip
()
...
@@ -540,7 +543,7 @@ class MapWidget(Widget):
...
@@ -540,7 +543,7 @@ class MapWidget(Widget):
def
deserialize
(
self
,
field
,
pstruct
):
def
deserialize
(
self
,
field
,
pstruct
):
if
pstruct
is
null
:
if
pstruct
is
null
:
return
null
return
null
elif
not
isinstance
(
pstruct
,
str
):
#string_types
elif
not
isinstance
(
pstruct
,
str
):
raise
Invalid
(
field
.
schema
,
"Pstruct is not a string"
)
raise
Invalid
(
field
.
schema
,
"Pstruct is not a string"
)
if
self
.
strip
:
if
self
.
strip
:
pstruct
=
pstruct
.
strip
()
pstruct
=
pstruct
.
strip
()
...
@@ -622,7 +625,7 @@ class MapWidget(Widget):
...
@@ -622,7 +625,7 @@ class MapWidget(Widget):
# def deserialize(self, field, pstruct):
# def deserialize(self, field, pstruct):
# if pstruct is null:
# if pstruct is null:
# return null
# return null
# elif not isinstance(pstruct, str):
#string_types
# elif not isinstance(pstruct, str):
# raise Invalid(field.schema, "Pstruct is not a string")
# raise Invalid(field.schema, "Pstruct is not a string")
# if self.strip:
# if self.strip:
# pstruct = pstruct.strip()
# pstruct = pstruct.strip()
...
@@ -834,7 +837,7 @@ class TextInputWidget(widget.TextInputWidget):
...
@@ -834,7 +837,7 @@ class TextInputWidget(widget.TextInputWidget):
def
__init__
(
self
,
**
kw
):
def
__init__
(
self
,
**
kw
):
super
(
TextInputWidget
,
self
)
.
__init__
(
**
kw
)
super
(
TextInputWidget
,
self
)
.
__init__
(
**
kw
)
# if isinstance(self.button, compat.str
ing_types
):
# if isinstance(self.button, compat.str):
if
self
.
button
:
if
self
.
button
:
if
isinstance
(
self
.
button
,
str
):
if
isinstance
(
self
.
button
,
str
):
self
.
button
=
Button
(
self
.
button
,
type
=
"button"
)
self
.
button
=
Button
(
self
.
button
,
type
=
"button"
)
...
@@ -893,10 +896,10 @@ class FilterWidget(Widget):
...
@@ -893,10 +896,10 @@ class FilterWidget(Widget):
"""
"""
if
self
.
multiple
:
if
self
.
multiple
:
if
value
in
map
(
text_type
,
cstruct
):
if
value
in
map
(
str
,
cstruct
):
# text_type
return
"selected"
return
"selected"
else
:
else
:
if
value
==
text_type
(
cstruct
):
if
value
==
str
(
cstruct
):
#text_type
return
"selected"
return
"selected"
return
None
return
None
...
@@ -973,7 +976,7 @@ class FilterWidget(Widget):
...
@@ -973,7 +976,7 @@ class FilterWidget(Widget):
# readonly = kw.get("readonly", self.readonly)
# readonly = kw.get("readonly", self.readonly)
#
#
# options = {}
# options = {}
# if isinstance(self.values, str
ing_types
):
# if isinstance(self.values, str):
# options["remote"] = "%s?term=%%QUERY" % self.values
# options["remote"] = "%s?term=%%QUERY" % self.values
# else:
# else:
# options["local"] = self.values
# options["local"] = self.values
...
@@ -1003,7 +1006,7 @@ class CSRFWidget(widget.HiddenWidget):
...
@@ -1003,7 +1006,7 @@ class CSRFWidget(widget.HiddenWidget):
cstruct
=
get_csrf_token
(
request
)
cstruct
=
get_csrf_token
(
request
)
if
pstruct
is
null
:
if
pstruct
is
null
:
return
null
return
null
elif
not
isinstance
(
pstruct
,
str
):
#string_types
elif
not
isinstance
(
pstruct
,
str
):
raise
Invalid
(
field
.
schema
,
"Pstruct is not a string"
)
raise
Invalid
(
field
.
schema
,
"Pstruct is not a string"
)
if
not
pstruct
:
if
not
pstruct
:
return
null
return
null
...
...
opensipkd/detable/detable.py
View file @
712624f
...
@@ -6,13 +6,17 @@ import re
...
@@ -6,13 +6,17 @@ import re
import
colander
import
colander
# import deform
# import deform
# from deform import compat, widget as deform_widget, field
from
deform
import
widget
as
deform_widget
,
field
# compat,
from
deform
import
field
,
widget
as
deform_widget
from
.
import
widget
from
.
import
widget
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
sequence_types
=
(
list
,
tuple
,
range
,
)
class
DeTable
(
field
.
Field
):
class
DeTable
(
field
.
Field
):
"""
"""
Field representing an entire form.
Field representing an entire form.
...
...
opensipkd/detable/widget.py
View file @
712624f
...
@@ -19,7 +19,7 @@ from deform.widget import MappingWidget
...
@@ -19,7 +19,7 @@ from deform.widget import MappingWidget
# from deform.compat import text_
# from deform.compat import text_
from
.i18n
import
_
from
.i18n
import
_
# _BLANK = text_("")
_BLANK
=
""
class
TableWidget
(
MappingWidget
):
class
TableWidget
(
MappingWidget
):
...
...
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment