Rekap Part 2: Menambahkan fungsionalitas admin dan form pada blog

Di tulisan rekap ini akan merangkum tulisan-tulisan sebelumnya:

  • Membuat superuser
  • Menampikan fitur-fitur blog di admin
  • Menyesuaikan tampilan
  • Membuat grup level user moderator dan creator
  • Manipulasi admin berdasarkan group user
  • Membuat custom field di form berdasarkan group user

Membuat Superuser

python manage.py createsuperuser

Lalu ikuti promp yang dimunculkan di terminal

Menampikan fitur-fitur blog di admin

Buka admin.py di folder blog, lalu tambahkan kode berikut

from django.contrib import admin

from blog.models import Category, Content, Tags

admin.site.register(Category)
admin.site.register(Tags)


@admin.register(Content)
class ContentAdmin(admin.ModelAdmin):
    pass

Perhatikan hanya content saja yang kita buat dengan class karena di content ini lah kita akan banyak bermain

Saya akan menggunakan aturan yang dibuat di tulisan sebelumnya termasuk forms.py

#forms.py
from django import forms

from blog.models import Content


class ContentForm(forms.ModelForm):
    OPTIONS = ((False, "Draft"), (True, "Publish"))
    publish = forms.ChoiceField(choices=OPTIONS)

    class Meta:
        model = Content
        exclude = ("slug",)

Dan di admin juga isinya mengikuti tulisan sebelumnya

@admin.register(Content)
class ContentAdmin(admin.ModelAdmin):
    form = ContentForm
    list_display = ["title", "slug", "category"]
    list_display_links = ["title"]
    search_fields = ["title"]
    list_filter = ["category"]
    list_per_page = 10
    readonly_fields = ["slug"]
    fieldsets = (
        ("Primary", {"fields": ("title",)}),
        ("Secondary", {"fields": ("category", "tags", "publish")}),
        (None, {"fields": ("body",)}),
    )

    def save_model(self, request, obj, form, change):
        if obj.id is None:
            title = obj.title
            obj.slug = title.lower().replace(" ", "-")
            obj.created_by = request.user
        super(ContentAdmin, self).save_model(request, obj, form, change)

Setelah superuser dibuat mari buat dua role “creator” dan “moderator”, hak aksesnya mirip dulu, untuk permission yang lain akan dibuat secara “custom” dengan cara mengubah beberapa method bawaan di admin.

Mari buat aturannya:

  1. Untuk group creator dia hanya bisa lihat postingan punya dia
  2. Untuk group moderator bisa semua lihat
  3. Untuk group moderator bisa akses category dan tags

Untuk mendaftarkan user bisa dengan menambahkan secara manual di menu users

setelah itu mari tambahkan dulu field untuk menampung info user di content

#tambahkan baris ini
from django.contrib.auth.models import User

class Content(models.Model):
    title = models.CharField(max_length=100)
    slug = models.CharField(max_length=200, null=True)
    category = models.ForeignKey(
        Category, related_name="content", on_delete=models.CASCADE
    )
    tags = models.ManyToManyField(Tags, related_name="content")
    body = models.TextField()
    publish = models.BooleanField(default=False)
    date_created = models.DateTimeField(auto_now_add=True)
    date_updated = models.DateTimeField(auto_now=True)
    #tambah yang baru ini
    created_by = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="content",
        null=True,
        blank=True,
    )

    def __str__(self):
        return self.title

Selanjutnya lakukan lagi makemigrations dan migrate

Setelah menambahkan kolom baru untuk menampung created by selanjutnya adalah bagaiaman django admin mengambil informasi user yang login, saya menggunakan contoh super user dulu (user id= 1 di dalam contoh ini)

Di bagian admin ada method save_model yang saat ini digunakan untuk mengisi nilai slug, untuk mengisi nilai user yang login kita bisa tambahkan di method ini, pertanyaanya bagaimana kita tahu user yang login? Jawabanya sederhana, objek user login terdapat di request, jadi method save_model kita ubah

def save_model(self, request, obj, form, change):
        if obj.id is None:
            title = obj.title
            obj.slug = title.lower().replace(" ", "-")
            #tambahkan ini
            obj.created_by = request.user
        super(ContentAdmin, self).save_model(request, obj, form, change)

Kalau kita membuat konten maka nanti user id akan otomatis terpasang

Membuat group dan user bisa lihat tulisannya di sini

Limitation by group

Sebelumnya saya sudah menyiapkan dummy data agar mempunyai banyak data

Saat login sebagai moderator dia melihat semua postingan, tapi ketika masuk sebagai creator dia hanya lihat punya dia sendiri

Jika untuk manipulasi proses simpan, untuk menampilkan bisa dengan method queryset

def get_queryset(self, request):
        qs = super().get_queryset(request)
        user = request.user
        if user.groups.filter(name="Creator").exists():
            return qs.filter(created_by=user)
        return qs

Kode di atas itu secara default akan menampilkan semuanya, tapi ketika user login terdaftar di group Creator maka hanya akan ditampilkan punya dia sendiri

Validation

Saya ingin yang punya akses ke field publish itu hanya moderator, sehingga content bisa dimoderasi dulu sebelum publish, tapi berhubung di permission hanya ada level form saja (change/edit) maka kita harus effort sedikit, caranya mirip dengan yang query set tapi sekarang diubah adlah fieldsetnya

def get_fieldsets(self, request, obj=None):
        fieldsets = super().get_fieldsets(request, obj)
        user = request.user
        if user.groups.filter(name="Creator").exists():
            fieldsets[1][1]["fields"] = ("category", "tags")
        else:
            fieldsets[1][1]["fields"] = ("category", "tags", "publish")
        return fieldsets

Oke selesai, sekarang sat “creator” dan “moderator” login masing-masing akan tampilan yang menyesuaikan.