Fakultas Ilmu Komputer UI
Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ppl-fasilkom-ui
2020
PPL-C
PPTI-Mobile Apps Monitoring Wabah Tuberkolosis
Neza-Backend
Commits
9a170c4e
Commit
9a170c4e
authored
Apr 19, 2020
by
Jonathan Christopher Jakub
Browse files
Merge branch 'rework-model-revisions' into 'staging'
Implement rework on model revisions See merge request
!35
parents
20842e86
c10e67ad
Pipeline
#41513
passed with stages
in 20 minutes and 29 seconds
Changes
39
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
apps/accounts/filters.py
View file @
9a170c4e
from
django_filters
import
FilterSet
,
CharFilter
ACCOUNT_FILTERSET_FIELDS
=
(
"name"
,
"email"
,
"phone_number"
,
"area"
,
"is_admin"
,
"is_verified"
,
"is_active"
,
)
from
apps.accounts.models
import
Account
ACCOUNT_SEARCH_FIELDS
=
(
"name"
,
"email"
,
"phone_number"
,
"area"
,
"is_admin"
,
"is_verified"
,
"is_active"
,
)
class
AccountFilter
(
FilterSet
):
username
=
CharFilter
(
field_name
=
"user__username"
)
class
Meta
:
model
=
Account
fields
=
[
"username"
,
"name"
,
"email"
,
"phone_number"
,
"area"
,
"is_admin"
,
"is_verified"
,
]
ACCOUNT_ORDERING_FIELDS
=
(
"name"
,
"email"
,
"phone_number"
,
"area"
,
"is_admin"
,
"is_verified"
,
"is_active"
,
"created_at"
,
)
apps/accounts/migrations/0002_auto_20200419_0156.py
0 → 100644
View file @
9a170c4e
# Generated by Django 3.0.1 on 2020-04-18 18:56
from
django.db
import
migrations
,
models
import
uuid
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
"accounts"
,
"0001_initial"
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
"AccountHistory"
,
fields
=
[
(
"revision_id"
,
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
editable
=
False
,
primary_key
=
True
,
serialize
=
False
,
),
),
(
"object_id"
,
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
editable
=
False
)),
(
"action_type"
,
models
.
CharField
(
choices
=
[
(
"Create"
,
"Create"
),
(
"Edit"
,
"Edit"
),
(
"Delete"
,
"Delete"
),
],
max_length
=
64
,
),
),
(
"recorded_at"
,
models
.
DateTimeField
(
auto_now_add
=
True
)),
(
"user_id"
,
models
.
IntegerField
()),
(
"name"
,
models
.
CharField
(
max_length
=
128
)),
(
"email"
,
models
.
EmailField
(
max_length
=
128
)),
(
"phone_number"
,
models
.
CharField
(
max_length
=
64
)),
(
"area"
,
models
.
CharField
(
max_length
=
128
)),
(
"is_admin"
,
models
.
BooleanField
(
default
=
False
)),
(
"is_verified"
,
models
.
BooleanField
(
default
=
False
)),
(
"is_active"
,
models
.
BooleanField
(
default
=
False
)),
],
options
=
{
"verbose_name_plural"
:
"account histories"
,
"db_table"
:
"account_history"
,
"ordering"
:
[
"-recorded_at"
],
},
),
migrations
.
AlterModelOptions
(
name
=
"account"
,
options
=
{
"ordering"
:
[
"-created_at"
],
"verbose_name_plural"
:
"accounts"
},
),
migrations
.
AddField
(
model_name
=
"account"
,
name
=
"deleted_at"
,
field
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
),
),
]
apps/accounts/migrations/0003_accounthistory_author.py
0 → 100644
View file @
9a170c4e
# Generated by Django 3.0.1 on 2020-04-19 11:26
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
"accounts"
,
"0002_auto_20200419_0156"
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
"accounthistory"
,
name
=
"author"
,
field
=
models
.
UUIDField
(
null
=
True
),
),
]
apps/accounts/migrations/0004_account_author.py
0 → 100644
View file @
9a170c4e
# Generated by Django 3.0.1 on 2020-04-19 11:29
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
"accounts"
,
"0003_accounthistory_author"
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
"account"
,
name
=
"author"
,
field
=
models
.
ForeignKey
(
blank
=
True
,
null
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
DO_NOTHING
,
related_name
=
"account"
,
to
=
"accounts.Account"
,
),
),
]
apps/accounts/models.py
View file @
9a170c4e
...
...
@@ -2,10 +2,12 @@ import uuid
from
django.contrib.auth.models
import
User
from
django.db
import
models
from
apps.commons.managers
import
SoftDeleteManager
from
apps.commons.models
import
HistoryEnabledModel
,
HistoryModel
class
Account
(
models
.
Model
):
id
=
models
.
UUIDField
(
primary_key
=
True
,
default
=
uuid
.
uuid4
,
editable
=
False
)
user
=
models
.
OneToOneField
(
User
,
on_delete
=
models
.
CASCADE
)
class
AccountHistory
(
HistoryModel
):
user
_id
=
models
.
IntegerField
(
null
=
False
)
name
=
models
.
CharField
(
max_length
=
128
)
email
=
models
.
EmailField
(
max_length
=
128
)
phone_number
=
models
.
CharField
(
max_length
=
64
)
...
...
@@ -13,15 +15,46 @@ class Account(models.Model):
is_admin
=
models
.
BooleanField
(
default
=
False
)
is_verified
=
models
.
BooleanField
(
default
=
False
)
is_active
=
models
.
BooleanField
(
default
=
False
)
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
)
author
=
models
.
UUIDField
(
null
=
True
)
objects
=
models
.
Manager
()
class
Meta
:
db_table
=
"account_history"
verbose_name_plural
=
"account histories"
ordering
=
[
"-recorded_at"
]
def
__str__
(
self
):
return
f
"[History] Rev.
{
self
.
revision_id
}
-
{
self
.
name
}
"
class
Account
(
HistoryEnabledModel
):
user
=
models
.
OneToOneField
(
User
,
on_delete
=
models
.
CASCADE
)
name
=
models
.
CharField
(
max_length
=
128
)
email
=
models
.
EmailField
(
max_length
=
128
)
phone_number
=
models
.
CharField
(
max_length
=
64
)
area
=
models
.
CharField
(
max_length
=
128
)
is_admin
=
models
.
BooleanField
(
default
=
False
)
is_verified
=
models
.
BooleanField
(
default
=
False
)
is_active
=
models
.
BooleanField
(
default
=
False
)
author
=
models
.
ForeignKey
(
"self"
,
blank
=
True
,
null
=
True
,
on_delete
=
models
.
DO_NOTHING
,
related_name
=
"account"
,
)
history_class
=
AccountHistory
relation_fields
=
[
"user"
]
objects
=
SoftDeleteManager
()
class
Meta
:
db_table
=
"account"
verbose_name_plural
=
"accounts"
ordering
=
[
"-created_at"
]
def
__str__
(
self
):
if
self
.
is_admin
:
return
f
"[Admin]
{
self
.
user
.
username
}
"
return
f
"[Officer]
{
self
.
user
.
username
}
"
account_role
=
"[Admin]"
if
self
.
is_admin
else
"[Officer]"
return
f
"
{
account_role
}
{
self
.
user
.
username
}
"
apps/accounts/serializers.py
View file @
9a170c4e
...
...
@@ -5,7 +5,7 @@ from apps.accounts.models import Account
class
AccountSerializer
(
serializers
.
ModelSerializer
):
username
=
serializers
.
CharField
(
source
=
"user.username"
,
re
quired
=
Fals
e
)
username
=
serializers
.
CharField
(
source
=
"user.username"
,
re
ad_only
=
Tru
e
)
class
Meta
:
model
=
Account
...
...
@@ -26,6 +26,10 @@ class AccountSerializer(serializers.ModelSerializer):
"username"
,
]
def
save
(
self
):
account
=
self
.
context
.
get
(
'request'
).
user
.
account
super
(
AccountSerializer
,
self
).
save
(
author
=
account
)
class
AccountRegisterSerializer
(
serializers
.
ModelSerializer
):
username
=
serializers
.
CharField
(
max_length
=
128
)
...
...
@@ -47,3 +51,7 @@ class AccountRegisterSerializer(serializers.ModelSerializer):
def
validate_password
(
self
,
value
):
password_validation
.
validate_password
(
value
)
return
value
def
to_representation
(
self
,
instance
):
serializer
=
AccountSerializer
(
instance
)
return
serializer
.
data
apps/accounts/tests/test_units/test_accounts.py
View file @
9a170c4e
...
...
@@ -6,7 +6,7 @@ from rest_framework.authtoken.models import Token
from
rest_framework.test
import
APITestCase
,
APIClient
from
apps.accounts.tests.factories.accounts
import
AccountFactory
,
UserFactory
from
apps.accounts.models
import
Account
from
apps.accounts.models
import
Account
,
AccountHistory
from
apps.constants
import
(
HEADER_PREFIX
,
ACTIVITY_TYPE_CREATE
,
...
...
@@ -17,20 +17,21 @@ from apps.constants import (
class
AccountViewTest
(
APITestCase
):
@
classmethod
def
setUpTestData
(
self
):
self
.
BASE_URL
=
"/accounts/"
self
.
PROFILE_URL
=
self
.
BASE_URL
+
"me/"
def
setUpTestData
(
cls
):
cls
.
BASE_URL
=
"/accounts/"
cls
.
PROFILE_URL
=
cls
.
BASE_URL
+
"me/"
cls
.
LOGS_URL
=
"/logs/"
self
.
user_1
=
UserFactory
(
username
=
"user_1"
,
password
=
"justpass"
)
self
.
user_2
=
UserFactory
(
username
=
"user_2"
,
password
=
"justpass"
)
self
.
admin
=
AccountFactory
(
admin
=
True
,
user
=
self
.
user_1
)
self
.
officer
=
AccountFactory
(
admin
=
False
,
user
=
self
.
user_2
)
self
.
accounts
=
[
self
.
admin
,
self
.
officer
]
cls
.
user_1
=
UserFactory
(
username
=
"user_1"
,
password
=
"justpass"
)
cls
.
user_2
=
UserFactory
(
username
=
"user_2"
,
password
=
"justpass"
)
cls
.
admin
=
AccountFactory
(
admin
=
True
,
user
=
cls
.
user_1
)
cls
.
officer
=
AccountFactory
(
admin
=
False
,
user
=
cls
.
user_2
)
cls
.
accounts
=
[
cls
.
admin
,
cls
.
officer
]
self
.
token_1
,
_
=
Token
.
objects
.
get_or_create
(
user
=
self
.
user_1
)
self
.
token_2
,
_
=
Token
.
objects
.
get_or_create
(
user
=
self
.
user_2
)
cls
.
token_1
,
_
=
Token
.
objects
.
get_or_create
(
user
=
cls
.
user_1
)
cls
.
token_2
,
_
=
Token
.
objects
.
get_or_create
(
user
=
cls
.
user_2
)
self
.
faker
=
Faker
()
cls
.
faker
=
Faker
()
def
setUp
(
self
):
self
.
client
=
APIClient
(
HTTP_AUTHORIZATION
=
HEADER_PREFIX
+
self
.
token_1
.
key
)
...
...
@@ -42,6 +43,12 @@ class AccountViewTest(APITestCase):
officer_str
=
f
"[Officer]
{
self
.
officer
.
user
.
username
}
"
self
.
assertEqual
(
officer_str
,
str
(
self
.
officer
))
def
test_history_string_representation
(
self
):
history
=
AccountHistory
.
objects
.
all
().
first
()
history_str
=
f
"[History] Rev.
{
history
.
revision_id
}
-
{
history
.
name
}
"
self
.
assertEqual
(
history_str
,
str
(
history
))
def
test_list_all_accounts_success
(
self
):
url
=
self
.
BASE_URL
...
...
@@ -51,33 +58,6 @@ class AccountViewTest(APITestCase):
self
.
assertIn
(
'"user_1"'
,
response_string
)
self
.
assertIn
(
'"user_2"'
,
response_string
)
def
test_list_all_accounts_paginate_failed
(
self
):
url
=
self
.
BASE_URL
+
"?page=100"
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_404_NOT_FOUND
)
response_string
=
response
.
rendered_content
.
decode
(
"utf-8"
)
self
.
assertIn
(
'"detail":"Invalid page."'
,
response_string
)
def
test_list_all_accounts_filter_success
(
self
):
url
=
self
.
BASE_URL
+
"?username="
+
self
.
user_1
.
username
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
response_string
=
response
.
rendered_content
.
decode
(
"utf-8"
)
self
.
assertIn
(
'"count":1'
,
response_string
)
def
test_list_all_accounts_filter_failed
(
self
):
url
=
self
.
BASE_URL
+
"?username=1234567890"
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_200_OK
)
response_string
=
response
.
rendered_content
.
decode
(
"utf-8"
)
self
.
assertIn
(
'"count":0'
,
response_string
)
def
test_retrieve_account_success
(
self
):
url
=
self
.
BASE_URL
+
str
(
self
.
officer
.
id
)
+
"/"
response
=
self
.
client
.
get
(
url
)
...
...
@@ -142,32 +122,14 @@ class AccountViewTest(APITestCase):
# Have account creation log for the new officer
new_officer_id
=
Account
.
objects
.
filter
(
email
=
_account_id
)[
0
].
id
response
=
self
.
client
.
get
(
"/logs/"
)
response
=
self
.
client
.
get
(
self
.
LOGS_URL
)
response_string
=
response
.
rendered_content
.
decode
(
"utf-8"
)
self
.
assertIn
(
'"object_id":"{
}"'
.
format
(
new_officer_id
)
,
response_string
)
self
.
assertIn
(
f
'"object_id":"
{
new_officer_id
}
"'
,
response_string
)
self
.
assertIn
(
'"action_type":"{
}"'
.
format
(
ACTIVITY_TYPE_CREATE
)
,
response_string
f
'"action_type":"
{
ACTIVITY_TYPE_CREATE
}
"'
,
response_string
)
def
test_username_lowercased
(
self
):
url
=
self
.
BASE_URL
data
=
{
"name"
:
self
.
faker
.
name
(),
"username"
:
"aBcDeFgH"
,
"password"
:
"justpass"
,
"email"
:
self
.
faker
.
email
(),
"phone_number"
:
self
.
faker
.
phone_number
(),
"area"
:
self
.
faker
.
city
(),
"is_admin"
:
False
,
}
self
.
client
.
post
(
path
=
url
,
data
=
data
,
format
=
"json"
,
)
self
.
assertTrue
(
Account
.
objects
.
filter
(
user__username
=
"abcdefgh"
).
exists
())
def
test_create_new_account_fails_with_poor_password
(
self
):
url
=
self
.
BASE_URL
_account_id
=
self
.
faker
.
email
()
...
...
@@ -210,11 +172,11 @@ class AccountViewTest(APITestCase):
)
# Have account update log
response
=
self
.
client
.
get
(
"/logs/"
)
response
=
self
.
client
.
get
(
self
.
LOGS_URL
)
response_string
=
response
.
rendered_content
.
decode
(
"utf-8"
)
self
.
assertIn
(
'"object_id":"{
}"'
.
format
(
self
.
officer
.
id
)
,
response_string
)
self
.
assertIn
(
'"action_type":"{
}"'
.
format
(
ACTIVITY_TYPE_EDIT
)
,
response_string
)
self
.
assertIn
(
f
'"object_id":"
{
self
.
officer
.
id
}
"'
,
response_string
)
self
.
assertIn
(
f
'"action_type":"
{
ACTIVITY_TYPE_EDIT
}
"'
,
response_string
)
def
test_edit_account_fail_without_complete_fields
(
self
):
url
=
self
.
BASE_URL
+
str
(
self
.
officer
.
id
)
+
"/"
...
...
@@ -231,19 +193,32 @@ class AccountViewTest(APITestCase):
def
test_delete_success
(
self
):
url
=
self
.
BASE_URL
+
str
(
self
.
officer
.
id
)
+
"/"
account_prev_count
=
Account
.
objects
.
all
().
count
()
account_history_prev_count
=
AccountHistory
.
objects
.
all
().
count
()
account_deleted_prev_count
=
Account
.
objects
.
deleted
().
count
()
response
=
self
.
client
.
delete
(
url
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_20
0_OK
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_20
4_NO_CONTENT
)
# Have account deletion log
response
=
self
.
client
.
get
(
"/logs/"
)
response
=
self
.
client
.
get
(
self
.
LOGS_URL
)
response_string
=
response
.
rendered_content
.
decode
(
"utf-8"
)
self
.
assertIn
(
'"object_id":"{
}"'
.
format
(
self
.
officer
.
id
)
,
response_string
)
self
.
assertIn
(
f
'"object_id":"
{
self
.
officer
.
id
}
"'
,
response_string
)
self
.
assertIn
(
'"action_type":"{
}"'
.
format
(
ACTIVITY_TYPE_DELETE
)
,
response_string
f
'"action_type":"
{
ACTIVITY_TYPE_DELETE
}
"'
,
response_string
)
account_current_count
=
Account
.
objects
.
all
().
count
()
account_history_current_count
=
AccountHistory
.
objects
.
all
().
count
()
account_deleted_current_count
=
Account
.
objects
.
deleted
().
count
()
self
.
assertEqual
(
account_current_count
,
account_prev_count
-
1
)
self
.
assertEqual
(
account_history_current_count
,
account_history_prev_count
+
1
)
self
.
assertEqual
(
account_deleted_current_count
,
account_deleted_prev_count
+
1
)
def
test_retrieve_current_profile_success
(
self
):
url
=
self
.
PROFILE_URL
...
...
apps/accounts/views.py
View file @
9a170c4e
...
...
@@ -3,17 +3,22 @@ from django.shortcuts import get_object_or_404
from
django_filters.rest_framework
import
DjangoFilterBackend
from
rest_framework
import
status
,
viewsets
from
rest_framework.decorators
import
action
from
rest_framework.filters
import
SearchFilter
,
OrderingFilter
from
rest_framework.pagination
import
PageNumberPagination
from
rest_framework.response
import
Response
from
apps.accounts.filters
import
AccountFilter
from
apps.accounts.filters
import
(
ACCOUNT_FILTERSET_FIELDS
,
ACCOUNT_ORDERING_FIELDS
,
ACCOUNT_SEARCH_FIELDS
,
)
from
apps.accounts.models
import
Account
from
apps.accounts.serializers
import
(
AccountSerializer
,
AccountRegisterSerializer
,
)
from
apps.commons.permissions
import
(
Is
SelfOrAdministrator
,
Is
Authenticated
,
CreateOnly
,
)
from
apps.constants
import
(
...
...
@@ -22,85 +27,39 @@ from apps.constants import (
ACTIVITY_TYPE_EDIT
,
ACTIVITY_TYPE_DELETE
,
)
from
apps.logs.models
import
Log
class
AccountViewSet
(
viewsets
.
ViewSet
):
queryset
=
Account
.
objects
.
all
().
select_related
(
"user"
).
order_by
(
"-created_at"
)
filter_backends
=
(
DjangoFilterBackend
,)
permission_classes
=
[
IsSelfOrAdministrator
|
CreateOnly
,
]
def
list
(
self
,
request
):
paginator
=
PageNumberPagination
()
filtered_set
=
AccountFilter
(
request
.
GET
,
queryset
=
self
.
queryset
).
qs
context
=
paginator
.
paginate_queryset
(
filtered_set
,
request
)
serializer
=
AccountSerializer
(
context
,
many
=
True
)
return
paginator
.
get_paginated_response
(
serializer
.
data
)
def
retrieve
(
self
,
request
,
pk
=
None
):
instance
=
get_object_or_404
(
self
.
queryset
,
pk
=
pk
)
self
.
check_object_permissions
(
request
,
instance
)
serializer
=
AccountSerializer
(
instance
)
return
Response
(
serializer
.
data
,
status
=
status
.
HTTP_200_OK
)
def
create
(
self
,
request
):
serializer
=
AccountRegisterSerializer
(
data
=
request
.
data
)
serializer
.
is_valid
(
raise_exception
=
True
)
class
AccountViewSet
(
viewsets
.
ModelViewSet
):
serializer_class
=
AccountSerializer
queryset
=
Account
.
objects
.
all
()
filter_backends
=
(
DjangoFilterBackend
,
SearchFilter
,
OrderingFilter
)
filterset_fields
=
ACCOUNT_FILTERSET_FIELDS
permission_classes
=
(
IsAuthenticated
|
CreateOnly
,
)
pagination_class
=
PageNumberPagination
search_fields
=
ACCOUNT_SEARCH_FIELDS
ordering_fields
=
ACCOUNT_ORDERING_FIELDS
def
get_queryset
(
self
):
user
=
self
.
request
.
user
account
=
Account
.
objects
.
filter
(
user
=
user
)
if
account
.
first
().
is_admin
:
return
Account
.
objects
.
all
()
return
account
def
get_serializer_class
(
self
):
if
self
.
action
in
[
'create'
]:
return
AccountRegisterSerializer
return
AccountSerializer
def
perform_create
(
self
,
serializer
):
username
=
serializer
.
validated_data
.
pop
(
"username"
).
lower
()
password
=
serializer
.
validated_data
.
pop
(
"password"
)
user
=
User
.
objects
.
create_user
(
username
=
username
,
password
=
password
)
account
=
Account
.
objects
.
create
(
user
=
user
,
**
serializer
.
validated_data
)
# Add account creation log
Log
.
objects
.
create
(
model_name
=
MODEL_NAME_ACCOUNT
,
object_id
=
account
.
id
,
action_type
=
ACTIVITY_TYPE_CREATE
,
author
=
account
,
)
Account
.
objects
.
create
(
user
=
user
,
**
serializer
.
validated_data
)
return
Response
(
AccountSerializer
(
account
).
data
,
status
=
status
.
HTTP_201_CREATED
,
)
def
update
(
self
,
request
,
pk
=
None
):
instance
=
get_object_or_404
(
self
.
queryset
,
pk
=
pk
)
self
.
check_object_permissions
(
request
,
instance
)
serializer
=
AccountSerializer
(
instance
,
data
=
request
.
data
)
serializer
.
is_valid
(
raise_exception
=
True
)
serializer
.
save
()
# Add account update log
Log
.
objects
.
create
(
model_name
=
MODEL_NAME_ACCOUNT
,
object_id
=
pk
,
action_type
=
ACTIVITY_TYPE_EDIT
,
author
=
request
.
user
.
account
,
)
return
Response
(
serializer
.
data
,
status
=
status
.
HTTP_200_OK
)
def
destroy
(
self
,
request
,
pk
=
None
):
instance
=
get_object_or_404
(
self
.
queryset
,
pk
=
pk
)
self
.
check_object_permissions
(
request
,
instance
)
instance
.
delete
()
# Add account deletion log
Log
.
objects
.
create
(
model_name
=
MODEL_NAME_ACCOUNT
,
object_id
=
pk
,
action_type
=
ACTIVITY_TYPE_DELETE
,
author
=
request
.
user
.
account
,
)
serializer
=
AccountSerializer
(
instance
=
instance
)
return
Response
(
serializer
.
data
,
status
=
status
.
HTTP_200_OK
)
def
perform_destroy
(
self
,
instance
):
instance
.
delete
(
author
=
self
.
request
.
user
.
account
)
@
action
(
detail
=
False
,
methods
=
[
"get"
],
url_path
=
"me"
)
def
profile
(
self
,
request
):
...
...
apps/cases/filters.py
View file @
9a170c4e
from
django_filters
import
FilterSet
from
apps.cases.models
import
(
CaseSubject
,
InvestigationCase
,
MonitoringCase
,
)
class
CaseSubjectFilter
(
FilterSet
):
class
Meta
:
model
=
CaseSubject
fields
=
[
"age"
,
"is_male"
,
"address"
,
"district"
,