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
PMPL
Class Project
DIGIPUS
Commits
a3591023
Commit
a3591023
authored
Oct 23, 2020
by
Rizkhi PH
🤔
Browse files
[
#35
] Material: Delete Material (Soft Delete/Recycle Bin)
parent
d5c0345b
Changes
7
Hide whitespace changes
Inline
Side-by-side
administration/templates/kelola_materi.html
View file @
a3591023
...
...
@@ -30,6 +30,7 @@
<th
scope=
"col"
>
Kontributor
</th>
<th
scope=
"col"
>
Status
</th>
<th
scope=
"col"
>
Jumlah Like
</th>
<th
scope=
"col"
>
Pilihan
</th>
</tr>
</thead>
<tfoot>
...
...
@@ -40,6 +41,7 @@
<th
scope=
"col"
>
Kontributor
</th>
<th
scope=
"col"
>
Status
</th>
<th
scope=
"col"
>
Jumlah Like
</th>
<th
scope=
"col"
>
Pilihan
</th>
</tr>
</tr>
</tfoot>
...
...
@@ -57,6 +59,11 @@
<td>
{{ materi.uploader }}
</td>
<td>
{{ materi.status }}
</td>
<td>
{{ materi.like_count }}
</td>
<td>
{% if not materi.deleted_at %}
<a
type=
"button"
href=
"/materi/{{materi.id}}/delete"
class=
"reject-button button-decoration"
style=
"background-color:red"
>
Hapus
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
...
...
administration/views.py
View file @
a3591023
...
...
@@ -505,7 +505,7 @@ class KelolaMateriView(TemplateView):
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
(
KelolaMateriView
,
self
).
get_context_data
(
**
kwargs
)
context
[
'materi_list'
]
=
Materi
.
objects
.
all
()
context
[
'materi_list'
]
=
Materi
.
all_
objects
.
all
()
return
context
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
app/migrations/0023_materi_deleted_at.py
0 → 100644
View file @
a3591023
# Generated by Django 3.1 on 2020-10-23 03:23
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'app'
,
'0022_merge_20201011_1122'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'materi'
,
name
=
'deleted_at'
,
field
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
),
),
]
app/models.py
View file @
a3591023
...
...
@@ -39,6 +39,15 @@ class Category(models.Model):
class
MateriManager
(
models
.
Manager
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
alive_only
=
kwargs
.
pop
(
'alive_only'
,
True
)
super
(
MateriManager
,
self
).
__init__
(
*
args
,
**
kwargs
)
def
get_queryset
(
self
):
if
self
.
alive_only
:
return
SoftDeletionQuerySet
(
self
.
model
).
filter
(
deleted_at
=
None
)
return
SoftDeletionQuerySet
(
self
.
model
)
def
search
(
self
,
search_text
):
search_vector
=
search
.
SearchVector
(
"title"
,
weight
=
"A"
)
search_query
=
search
.
SearchQuery
(
search_text
)
...
...
@@ -51,8 +60,23 @@ class MateriManager(models.Manager):
return
search_result
class
SoftDeletionQuerySet
(
models
.
query
.
QuerySet
):
def
delete
(
self
):
return
super
(
SoftDeletionQuerySet
,
self
).
update
(
deleted_at
=
timezone
.
now
())
class
Materi
(
models
.
Model
):
class
SoftDeleteModel
(
models
.
Model
):
deleted_at
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
)
all_objects
=
MateriManager
(
alive_only
=
False
)
class
Meta
:
abstract
=
True
def
soft_delete
(
self
):
self
.
deleted_at
=
timezone
.
now
()
self
.
save
()
class
Materi
(
SoftDeleteModel
):
cover
=
models
.
ImageField
()
content
=
models
.
FileField
()
title
=
models
.
CharField
(
max_length
=
50
,
default
=
"Judul"
)
...
...
@@ -61,7 +85,7 @@ class Materi(models.Model):
publisher
=
models
.
CharField
(
max_length
=
30
,
default
=
"Penerbit"
)
release_year
=
models
.
IntegerField
(
default
=
current_year
)
pages
=
models
.
IntegerField
(
default
=
0
)
descriptions
=
models
.
TextField
(
default
=
"Deskripsi"
)
descriptions
=
models
.
TextField
(
default
=
"Deskripsi"
)
status
=
models
.
CharField
(
max_length
=
30
,
choices
=
VERIFICATION_STATUS
,
default
=
VERIFICATION_STATUS
[
0
][
0
])
categories
=
models
.
ManyToManyField
(
Category
)
date_created
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
...
...
app/tests.py
View file @
a3591023
...
...
@@ -1071,26 +1071,57 @@ class DashboardKontributorViewTest(TestCase):
html
=
response
.
content
.
decode
(
"utf-8"
)
self
.
assertIn
(
ERROR_403_MESSAGE
,
html
)
class
DeleteMateriTest
(
TestCase
):
def
setUp
(
self
):
self
.
client
=
Client
()
self
.
admin_credential
=
{
"email"
:
"admin@gov.id"
,
"password"
:
id_generator
()
}
self
.
superuser_credential
=
{
"email"
:
"superuser@gov.id"
,
"password"
:
id_generator
()
}
self
.
contributor_credential
=
{
"email"
:
"contributor@gov.id"
,
"password"
:
id_generator
()
}
self
.
admin
=
get_user_model
().
objects
.
create_user
(
**
self
.
admin_credential
,
name
=
"Admin"
,
is_admin
=
True
)
self
.
superuser
=
get_user_model
().
objects
.
create_user
(
**
self
.
superuser_credential
,
name
=
"Superuser"
,
is_admin
=
True
,
is_superuser
=
True
)
self
.
content
=
SimpleUploadedFile
(
"content.txt"
,
b
"Test"
)
self
.
cover
=
SimpleUploadedFile
(
"flower.jpg"
,
b
"Test file"
)
self
.
contributor
=
User
.
objects
.
create_contributor
(
email
=
"kontributor@gov.id"
,
password
=
"kontributor"
)
self
.
contributor
=
User
.
objects
.
create_contributor
(
**
self
.
contributor_credential
)
Materi
(
title
=
"Materi 1"
,
author
=
"Agas"
,
uploader
=
self
.
contributor
,
publisher
=
"Kelas SC"
,
descriptions
=
"Deskripsi Materi 1"
,
status
=
"APPROVE"
,
cover
=
self
.
cover
,
content
=
self
.
content
).
save
()
self
.
materi1
=
Materi
.
objects
.
first
()
self
.
url
=
"/materi/"
+
str
(
self
.
materi1
.
id
)
+
"/delete"
def
test_url_delete_materi_is_success
(
self
):
def
test_url_delete_materi_is_success_as_contributor
(
self
):
self
.
client
.
login
(
**
self
.
contributor_credential
)
response
=
self
.
client
.
get
(
self
.
url
)
self
.
assertEqual
(
response
.
status_code
,
302
)
def
test_url_soft_delete_materi_is_success_as_admin
(
self
):
self
.
client
.
login
(
**
self
.
admin_credential
)
response
=
self
.
client
.
get
(
self
.
url
)
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
materi1
.
refresh_from_db
()
self
.
assertNotEqual
(
self
.
materi1
.
deleted_at
,
None
)
def
test_url_soft_delete_materi_is_success_as_superuser
(
self
):
self
.
client
.
login
(
**
self
.
superuser_credential
)
response
=
self
.
client
.
get
(
self
.
url
)
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
materi1
.
refresh_from_db
()
self
.
assertNotEqual
(
self
.
materi1
.
deleted_at
,
None
)
class
ProfilViewTest
(
TestCase
):
@
classmethod
def
setUpTestData
(
cls
):
...
...
app/views.py
View file @
a3591023
...
...
@@ -259,6 +259,9 @@ def view_materi(request, pk):
def
delete_materi
(
request
,
pk
):
materi
=
get_object_or_404
(
Materi
,
pk
=
pk
)
if
request
.
user
.
is_superuser
or
request
.
user
.
is_admin
:
materi
.
soft_delete
()
return
HttpResponseRedirect
(
"/administration/"
)
materi
.
delete
()
return
HttpResponseRedirect
(
"/dashboard/"
)
...
...
digipus/__pycache__/settings.cpython-36.pyc
View file @
a3591023
No preview for this file type
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
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 comment