Fakultas Ilmu Komputer UI
Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
PMPL
Class Project
DIGIPUS
Commits
a3d532b6
Commit
a3d532b6
authored
Nov 11, 2020
by
Mutia Rahmatun Husna
Browse files
[REFACTOR] edit navbar code
parents
764cffe7
bdacd895
Pipeline
#60478
passed with stages
in 21 minutes and 40 seconds
Changes
47
Pipelines
1
Show whitespace changes
Inline
Side-by-side
administration/templates/edit_kontributor.html
deleted
100644 → 0
View file @
764cffe7
{% extends 'administration/base_administrasi.html' %}
{% load static %}
{% block content %}
<div
class=
"card shadow mb-4"
>
<div
class=
"card-header py-3"
>
<h6
class=
"m-0 font-weight-bold text-primary"
>
Edit {{ page_title }}
</h6>
</div>
<div
class=
"card-body"
>
<form
method=
"POST"
>
{% csrf_token %}
{{ item.name }}
<div
class=
"status d-flex align-items-baseline"
>
{{ form.is_active }}
<br>
Active
</div>
<div
class=
""
>
<button
class=
"btn-sm btn-primary rounded p-12"
type=
"submit"
>
<i
class=
"far fa-save"
aria-hidden=
"true"
></i>
Simpan
</button>
</div>
</form>
</div>
</div>
{% endblock %}
\ No newline at end of file
administration/templates/kelola_admin.html
View file @
a3d532b6
{% extends 'administration/base_administrasi2.html' %}
{% load static %}
{% block title %}
<title>
Kelola Admin | Digipus
</title>
...
...
administration/templates/registrasi_admin.html
View file @
a3d532b6
{%
load static
%}
{%
extends 'administration/base_administrasi2.html'
%}
<!DOCTYPE html>
<html
lang=
"en"
>
{% block title %}
<title>
Dasbor - Kelola Admin
</title>
{% endblock %}
<head>
<meta
charset=
"utf-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1, shrink-to-fit=no"
>
<meta
name=
"description"
content=
""
>
<meta
name=
"author"
content=
""
>
<title>
Dasbor - Kelola Admin
</title>
<!-- Custom fonts for this template -->
<link
href=
"https://fonts.googleapis.com/css2?family=Poppins&display=swap"
rel=
"stylesheet"
>
<!-- Custom styles for this template -->
<link
rel=
"icon"
type=
"image/png"
href=
"{% static 'images/icons/logo.ico' %}"
/>
<link
href=
"{% static 'css/sb-admin-2.min.css' %}"
rel=
"stylesheet"
>
<link
rel=
"stylesheet"
href=
"{% static 'css/button.css' %}"
>
<!-- Custom styles for this page -->
<link
href=
"{% static 'vendor/datatables/dataTables.bootstrap4.min.css' %}"
rel=
"stylesheet"
>
</head>
<body
id=
"page-top"
style=
"font-family: 'Poppins', sans-serif;"
>
<!-- Page Wrapper -->
<div
id=
"wrapper"
>
<!-- Sidebar -->
<ul
class=
"navbar-nav bg-gradient-primary sidebar sidebar-dark accordion"
id=
"accordionSidebar"
>
<!-- Sidebar - Brand -->
<a
class=
"sidebar-brand d-flex align-items-center justify-content-center"
href=
"{% url 'daftar_katalog' %}"
>
<div
class=
"sidebar-brand-icon rotate-n-15"
>
</div>
<div
class=
"sidebar-brand-text mx-3"
>
Digipus
</div>
</a>
<!-- Divider -->
<hr
class=
"sidebar-divider my-0"
>
<!-- Nav Item - Dashboard -->
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"/administration/"
>
<span>
Verifikasi Materi
</span></a>
</li>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"#"
>
<span>
Statistik Materi
</span></a>
</li>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"/administration/laporan-materi/"
>
<span>
Laporan Materi
</span></a>
</li>
<!-- Divider -->
<hr
class=
"sidebar-divider my-0"
>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"/administration/setting/verification/"
>
<span>
Pengaturan Verifikasi
</span></a>
</li>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"/administration/setting/category/"
>
<span>
Pengaturan Kategori
</span></a>
</li>
<!-- Divider -->
<hr
class=
"sidebar-divider my-0"
>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"/administration/kelola-kontributor/"
>
<span>
Kelola Kontributor
</span></a>
</li>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"/administration/kelola-admin/"
>
<span>
Kelola Admin
</span></a>
</li>
<!-- Divider -->
<hr
class=
"sidebar-divider my-0"
>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div
id=
"content-wrapper"
class=
"d-flex flex-column"
>
<!-- Main Content -->
<div
id=
"content"
>
<!-- Topbar -->
<nav
class=
"navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow"
>
<!-- Sidebar Toggle (Topbar) -->
<button
id=
"sidebarToggleTop"
class=
"btn btn-link d-md-none rounded-circle mr-3"
>
<em
class=
"fa fa-bars"
></em>
</button>
<div
class=
"sidebar-brand-text mx-3"
>
Diskominfo Kota Depok
</div>
<!-- Topbar Navbar -->
<ul
class=
"navbar-nav ml-auto"
>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"/dashboard/"
>
<span
class=
"mr-2 d-none d-lg-inline text-gray-600 small"
>
Administrasi
</span>
</a>
</li>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"/profil/"
>
<span
class=
"mr-2 d-none d-lg-inline text-gray-600 small"
>
Profil
</span>
</a>
</li>
<li
class=
"nav-item"
>
<a
class=
"nav-link"
href=
"/logout/"
>
<span
class=
"mr-2 d-none d-lg-inline text-gray-600 small"
>
Logout
</span>
</a>
</li>
<div
class=
"topbar-divider d-none d-sm-block"
></div>
<!-- Nav Item - User Information -->
<li
class=
"nav-item dropdown no-arrow"
>
<a
class=
"nav-link dropdown-toggle"
href=
"#"
id=
"userDropdown"
role=
"button"
data-toggle=
"dropdown"
aria-haspopup=
"true"
aria-expanded=
"false"
>
<span
class=
"mr-2 d-none d-lg-inline text-gray-600 small"
>
{{ user.name }}
</span>
{% if not user.default_profile_picture %}
<img
class=
"img-profile rounded-circle"
src=
"https://i.ibb.co/9wgPzyZ/default-image.png"
alt=
"User profile picture"
>
{% else %}
<img
class=
"img-profile rounded-circle"
src=
"{{ user.profile_picture.url }}"
alt=
"User profile picture"
>
{% endif %}
</a>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div
class=
"container-fluid"
>
<!-- Page Heading -->
{% block content %}
<h1
class=
"h3 mb-2 text-gray-800"
>
Registrasi Admin
</h1>
<div
class=
"form-margin"
></div>
<div
class=
"container admin-page"
>
...
...
@@ -220,10 +72,11 @@
<div
class=
"col-md-6 admin-page"
>
<div
class=
"d-flex flex-row"
>
<div
class=
"p-2"
>
<button
type=
"submit"
class=
"btn btn-success btn-edit"
style=
"background-color: #615CFD; border-color: #615CFD;"
>
Simpan
</button>
<button
type=
"submit"
class=
"btn btn-success btn-edit"
style=
"background-color: #615CFD; border-color: #615CFD;"
>
Simpan
</button>
</div>
<div
class=
"p-2"
>
<a
href=
"/administra
si
/kelola-admin"
class=
"btn btn-secondary"
>
Kembali Ke Kelola Admin
</a>
<a
href=
"/administra
tion
/kelola-admin"
class=
"btn btn-secondary"
>
Kembali Ke Kelola Admin
</a>
</div>
</div>
<div
class=
"fieldWrapper"
>
...
...
@@ -233,58 +86,4 @@
</form>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer
class=
"sticky-footer bg-white"
>
<div
class=
"container my-auto"
>
<div
class=
"copyright text-center my-auto"
>
<span>
Copyright
©
Diskominfo Kota Depok 2020
</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a
class=
"scroll-to-top rounded"
href=
"#page-top"
>
<em
class=
"fas fa-angle-up"
></em>
</a>
<!-- Bootstrap core JavaScript-->
<script
src=
"https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity=
"sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin=
"anonymous"
></script>
<script
src=
"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity=
"sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin=
"anonymous"
></script>
<script
src=
"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity=
"sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin=
"anonymous"
></script>
<!-- Core plugin JavaScript-->
<script
src=
"https://code.jquery.com/jquery-3.5.0.min.js"
integrity=
"sha256-xNzN2a4ltkB44Mc/Jz3pT4iU1cmeR0FkXs4pru/JxaQ="
crossorigin=
"anonymous"
></script>
<!-- Custom scripts for all pages-->
<script
src=
"{% static 'js/sb-admin-2.min.js' %}"
></script>
<!-- Page level plugins -->
<script
src=
"{% static 'vendor/datatables/jquery.dataTables.min.js' %}"
></script>
<script
src=
"{% static 'vendor/datatables/dataTables.bootstrap4.min.js' %}"
></script>
<!-- Page level custom scripts -->
<script
src=
"{% static 'js/demo/datatables-demo.js' %}"
></script>
</body>
</html>
\ No newline at end of file
{% endblock %}
\ No newline at end of file
administration/views.py
View file @
a3d532b6
...
...
@@ -9,9 +9,10 @@ from django.utils import timezone
from
administration.models
import
VerificationReport
,
VerificationSetting
,
DeletionHistory
from
administration.forms
import
CategoryForm
,
VerificationSettingForm
,
RegistrasiAdminForm
,
PeriodForm
,
EditAdminStatusForm
,
EditKontributorStatusForm
from
administration.services
import
StatisticService
,
DetailVerificationService
,
LaporanMateriService
from
app.models
import
Category
,
Materi
,
ViewStatistics
,
DownloadStatistics
,
Comment
,
Like
,
LaporanMateri
from
app.models
import
Category
,
Materi
,
ViewStatistics
,
DownloadStatistics
,
Comment
,
Like
,
LaporanMateri
,
AdminNotification
from
authentication.models
import
User
from
datetime
import
datetime
from
app.models
import
NotifikasiKontributor
from
administration.utils
import
generate_time_step
...
...
@@ -82,11 +83,17 @@ class DetailVerificationView(TemplateView):
verif_report
=
VerificationReport
(
report
=
report
,
materi
=
materi
,
user
=
self
.
request
.
user
,
status
=
materi
.
get_status_display
())
verif_report
.
save
()
new_kontributor_notif
=
NotifikasiKontributor
(
materi
=
materi
,
user
=
materi
.
uploader
,
feedback
=
materi
.
get_status_display
())
new_kontributor_notif
.
save
()
return
HttpResponseRedirect
(
"/administration/"
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
context
=
self
.
get_context_data
(
**
kwargs
)
if
(
request
.
user
.
is_admin
):
AdminNotification
.
objects
.
filter
(
materi
=
context
[
"materi_data"
]).
delete
()
return
self
.
render_to_response
(
context
=
context
)
...
...
@@ -421,7 +428,7 @@ class EditAdminStatusView(TemplateView):
class
EditKontributorStatusView
(
TemplateView
):
template_name
=
"edit_
kontributor
.html"
template_name
=
"edit_
admin
.html"
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
if
not
request
.
user
.
is_authenticated
or
not
request
.
user
.
is_admin
:
...
...
@@ -583,6 +590,8 @@ def blok_materi(request, *args, **kwargs):
if
materi
.
status
==
"APPROVE"
and
LaporanMateri
.
objects
.
filter
(
is_rejected
=
False
,
materi_id
=
materi
.
id
):
materi
.
status
=
"BLOCKED"
materi
.
save
()
new_kontributor_notif
=
NotifikasiKontributor
(
materi
=
materi
,
user
=
materi
.
uploader
,
feedback
=
materi
.
get_status_display
())
new_kontributor_notif
.
save
()
return
HttpResponseRedirect
(
ADMINISTRATION_REPORT
)
...
...
app/admin.py
View file @
a3d532b6
from
django.contrib
import
admin
from
.models
import
AdminNotification
# Register your models here.
admin
.
site
.
register
(
AdminNotification
)
\ No newline at end of file
app/forms.py
View file @
a3d532b6
from
django
import
forms
from
app.models
import
Materi
,
Category
,
RatingContributor
from
app.models
import
Materi
,
Category
,
RatingContributor
,
GuestBook
from
authentication.models
import
User
import
datetime
def
year_choices
():
return
[(
r
,
r
)
for
r
in
range
(
2000
,
datetime
.
date
.
today
().
year
+
1
)]
return
[(
r
,
r
)
for
r
in
range
(
2000
,
datetime
.
date
.
today
().
year
+
1
)]
class
UploadMateriForm
(
forms
.
ModelForm
):
categories
=
forms
.
ModelMultipleChoiceField
(
queryset
=
Category
.
objects
.
all
(),
widget
=
forms
.
CheckboxSelectMultiple
(
attrs
=
{
'style'
:
'column-count:2'
}),
required
=
True
)
release_year
=
forms
.
TypedChoiceField
(
coerce
=
int
,
choices
=
year_choices
,
initial
=
datetime
.
date
.
today
().
year
)
yt_video_id
=
forms
.
CharField
(
label
=
"Youtube Video Id"
,
\
categories
=
forms
.
ModelMultipleChoiceField
(
queryset
=
Category
.
objects
.
all
(
),
widget
=
forms
.
CheckboxSelectMultiple
(
attrs
=
{
'style'
:
'column-count:2'
}),
required
=
True
)
release_year
=
forms
.
TypedChoiceField
(
coerce
=
int
,
choices
=
year_choices
,
initial
=
datetime
.
date
.
today
().
year
)
yt_video_id
=
forms
.
CharField
(
label
=
"Youtube Video Id"
,
help_text
=
"This is not required.<br>
\
Please insert only Youtube link videos! Take a note for the video id!<br>
\
Example : https://www.youtube.com/watch?v=DkJ-50GLi2I <br> has video id DkJ-50GLi2I"
,
required
=
False
)
...
...
@@ -29,14 +33,13 @@ class UploadMateriForm(forms.ModelForm):
field
.
widget
.
attrs
[
"class"
]
=
"form-control"
field
.
widget
.
attrs
[
"placeholder"
]
=
field
.
initial
field
.
initial
=
""
self
.
fields
[
'categories'
].
widget
.
attrs
.
update
({
'class'
:
"native"
})
self
.
fields
[
'categories'
].
widget
.
attrs
.
update
({
'class'
:
"native"
})
class
SuntingProfilForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
User
fields
=
[
"email"
,
"name"
,
"instansi"
,
"nik"
,
"alamat"
,
"nomor_telpon"
,
fields
=
[
"email"
,
"name"
,
"instansi"
,
"nik"
,
"alamat"
,
"nomor_telpon"
,
"profile_picture"
,
"linkedin"
,
"facebook"
,
"twitter"
,
"instagram"
,
"biography"
,
"is_subscribing_to_material_comments"
]
...
...
@@ -51,7 +54,6 @@ class SuntingProfilForm(forms.ModelForm):
key
=
list
(
self
.
errors
)[
0
]
self
.
fields
[
key
].
widget
.
attrs
[
"autofocus"
]
=
""
self
.
fields
[
"email"
].
widget
.
attrs
[
"readonly"
]
=
True
...
...
@@ -61,14 +63,43 @@ class RatingContributorForm(forms.ModelForm):
fields
=
[
'score'
,
'user'
,
'contributor'
]
SCORE_CHOICE
=
(
(
''
,
'Select score'
),
(
'1'
,
'1'
),
# First one is the value of select option and second is the displayed value in option
# First one is the value of select option and second is the displayed value in option
(
'1'
,
'1'
),
(
'2'
,
'2'
),
(
'3'
,
'3'
),
(
'4'
,
'4'
),
(
'5'
,
'5'
),
)
widgets
=
{
'score'
:
forms
.
Select
(
choices
=
SCORE_CHOICE
,
attrs
=
{
'class'
:
'form-control'
,
'id'
:
'form-rating'
},),
'score'
:
forms
.
Select
(
choices
=
SCORE_CHOICE
,
attrs
=
{
'class'
:
'form-control'
,
'id'
:
'form-rating'
},),
'user'
:
forms
.
HiddenInput
(),
'contributor'
:
forms
.
HiddenInput
()
}
class
GuestBookForm
(
forms
.
models
.
ModelForm
):
class
Meta
:
model
=
GuestBook
fields
=
[
'name'
,
'job'
,
'gender'
]
gender_choices
=
(
(
'Male'
,
'Male'
),
(
'Female'
,
'Female'
)
)
widgets
=
{
'name'
:
forms
.
fields
.
TextInput
(
attrs
=
{
'placeholder'
:
'Input your name'
,
'class'
:
'form-control input-lg'
}),
'job'
:
forms
.
fields
.
TextInput
(
attrs
=
{
'placeholder'
:
'Input your job'
,
'class'
:
'form-control input-lg'
}),
'gender'
:
forms
.
fields
.
Select
(
choices
=
gender_choices
,
attrs
=
{
'class'
:
'form-control input-lg'
})
}
error_messages
=
{
'name'
:
{
'required'
:
'Name is required'
},
'job'
:
{
'required'
:
'Job is required'
},
'gender'
:
{
'required'
:
'Gender is required'
}
}
app/migrations/0028_adminnotification.py
0 → 100644
View file @
a3d532b6
# Generated by Django 3.1 on 2020-10-31 14:46
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'app'
,
'0027_readlater'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'AdminNotification'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'materi'
,
models
.
ForeignKey
(
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
to
=
'app.materi'
)),
],
),
]
app/migrations/0028_notifikasikontributor.py
0 → 100644
View file @
a3d532b6
# Generated by Django 3.1 on 2020-10-31 16:29
from
django.conf
import
settings
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
migrations
.
swappable_dependency
(
settings
.
AUTH_USER_MODEL
),
(
'app'
,
'0027_readlater'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'NotifikasiKontributor'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'feedback'
,
models
.
CharField
(
default
=
''
,
max_length
=
20
)),
(
'materi'
,
models
.
ForeignKey
(
max_length
=
120
,
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
to
=
'app.materi'
)),
(
'user'
,
models
.
ForeignKey
(
on_delete
=
django
.
db
.
models
.
deletion
.
CASCADE
,
to
=
settings
.
AUTH_USER_MODEL
)),
],
),
]
app/migrations/0029_guestbook.py
0 → 100644
View file @
a3d532b6
# Generated by Django 3.1 on 2020-10-31 18:19
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'app'
,
'0028_adminnotification'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'GuestBook'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'name'
,
models
.
TextField
(
default
=
''
)),
(
'job'
,
models
.
TextField
(
default
=
''
)),
(
'gender'
,
models
.
CharField
(
default
=
'Male'
,
max_length
=
6
)),
],
),
]
app/migrations/0029_merge_20201101_0217.py
0 → 100644
View file @
a3d532b6
# Generated by Django 3.1 on 2020-10-31 19:17
from
django.db
import
migrations
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'app'
,
'0028_notifikasikontributor'
),
(
'app'
,
'0028_adminnotification'
),
]
operations
=
[
]
app/migrations/0030_merge_20201101_0621.py
0 → 100644
View file @
a3d532b6
# Generated by Django 3.1 on 2020-10-31 23:21
from
django.db
import
migrations
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'app'
,
'0029_guestbook'
),
(
'app'
,
'0028_notifikasikontributor'
),
]
operations
=
[
]
app/migrations/0031_merge_20201101_1729.py
0 → 100644
View file @
a3d532b6
# Generated by Django 3.1 on 2020-11-01 10:29
from
django.db
import
migrations
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'app'
,
'0030_merge_20201101_0621'
),
(
'app'
,
'0029_merge_20201101_0217'
),
]
operations
=
[
]
app/models.py
View file @
a3d532b6
import
random
import
datetime
import
math
from
django.contrib.postgres
import
search
from
django.core.exceptions
import
ValidationError
...
...
@@ -25,9 +26,11 @@ def get_random_color():
color
=
"%06x"
%
random
.
randint
(
0
,
0xFFFFFF
)
return
color
def
current_year
():
return
datetime
.
date
.
today
().
year
class
Category
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
20
)
description
=
models
.
TextField
(
blank
=
False
,
default
=
""
)
...
...
@@ -49,21 +52,32 @@ class MateriManager(models.Manager):
return
SoftDeletionQuerySet
(
self
.
model
)
def
search
(
self
,
search_text
):
search_vector
=
search
.
SearchVector
(
"title"
,
weight
=
"A"
)
search_vector
=
None
for
field
,
weight
in
Materi
.
SEARCH_INDEX
:
if
search_vector
is
None
:
search_vector
=
search
.
SearchVector
(
field
,
weight
=
weight
)
else
:
search_vector
+=
search
.
SearchVector
(
field
,
weight
=
weight
)
search_query
=
search
.
SearchQuery
(
search_text
)
search_rank
=
search
.
SearchRank
(
search_vector
,
search_query
)
search_result
=
(
self
.
get_queryset
().
filter
(
_search_vector
=
search_query
).
annotate
(
rank
=
search_rank
).
order_by
(
"-rank"
)
self
.
get_queryset
()
.
filter
(
_search_vector
=
search_query
)
.
annotate
(
rank
=
search_rank
)
.
order_by
(
"-rank"
)
)
return
search_result
class
SoftDeletionQuerySet
(
models
.
query
.
QuerySet
):
def
delete
(
self
):
return
super
(
SoftDeletionQuerySet
,
self
).
update
(
deleted_at
=
timezone
.
now
())
class
SoftDeleteModel
(
models
.
Model
):
deleted_at
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
)
...
...
@@ -76,6 +90,7 @@ class SoftDeleteModel(models.Model):
self
.
deleted_at
=
timezone
.
now
()
self
.
save
()
class
Materi
(
SoftDeleteModel
):
cover
=
models
.
ImageField
()
content
=
models
.
FileField
()
...
...
@@ -86,7 +101,8 @@ class Materi(SoftDeleteModel):
release_year
=
models
.
IntegerField
(
default
=
current_year
)
pages
=
models
.
IntegerField
(
default
=
0
)