Admin Panel
Buraq ships with a built-in admin panel — no third-party dependencies required. It provides automatic CRUD pages for every registered model, with search, pagination, and dark-themed UI powered by Frutjam CSS.
Mount the admin in your URL config, like any other set of URLs:
from buraq.contrib import adminfrom buraq.urls import path
urlpatterns = [ path("/admin", admin.site.urls),]Log in with any account that has is_staff = True or is_superuser = True.
Create your first admin user from the command line:
buraq createsuperuserRegistering models
Section titled “Registering models”Create an admin.py inside your app. The admin imports one from every app in
INSTALLED_APPS when it is mounted — so a model appears only if its app is
listed there. An app with no admin.py is skipped; anything that fails inside
one is raised rather than swallowed.
from buraq.contrib import adminfrom posts.models import Category, Comment, Post
@admin.register(Post)class PostAdmin(admin.ModelAdmin): list_display = ["id", "title", "is_published", "created_at"] search_fields = ["title", "slug"] ordering = ["-created_at"] list_per_page = 25 readonly_fields = ["created_at"]
@admin.register(Comment)class CommentAdmin(admin.ModelAdmin): list_display = ["id", "author_name", "post_id", "created_at"] search_fields = ["author_name"]
admin.site.register(Category) # default ModelAdmin — shows all columnsThe decorator takes several models if one ModelAdmin suits them all
(@admin.register(Post, Draft)), and site.register(Model) on its own is the
way to register a model with the default admin, as Category does above.
Importing the module — from buraq.contrib import admin — keeps ModelAdmin,
register and site under one name. Importing them directly works the same
way:
from buraq.contrib.admin import ModelAdmin, site
class PostAdmin(ModelAdmin): ...
site.register(Post, PostAdmin)ModelAdmin options
Section titled “ModelAdmin options”| Option | Default | Description |
|---|---|---|
list_display |
all columns (up to 6) | Columns shown in the list view |
search_fields |
[] |
Fields searched via the search box (case-insensitive LIKE) |
list_filter |
[] |
Field names for sidebar filters (future) |
ordering |
["-id"] |
Default sort for list view |
list_per_page |
20 |
Rows per page |
fields |
all editable columns | Fields shown in add/change forms |
readonly_fields |
[] |
Fields displayed but not editable in forms |
can_create |
True |
Show the + Add button |
can_edit |
True |
Show the Edit button per row |
can_delete |
True |
Show the Delete button per row |
AdminSite
Section titled “AdminSite”site is the global AdminSite instance shared across your project.
You can also create isolated sites for multi-tenant setups:
from buraq.contrib.admin import AdminSite
private_site = AdminSite()private_site.site_header = "Staff Panel"private_site.register(Order, OrderAdmin)
urlpatterns = [ path("/staff", private_site.urls),]Two sites can be mounted at once, each at its own prefix, each with its own registry.
Authentication
Section titled “Authentication”The admin uses a separate signed session cookie (_buraq_admin).
Any user with is_staff=True or is_superuser=True can log in via /admin/login.
The cookie is signed with your project’s SECRET_KEY.
Production security
Section titled “Production security”- Set a strong, random
SECRET_KEY— the admin cookie is HMAC-signed with it. - Restrict
/adminto internal networks or a VPN using your reverse proxy; Buraq does not ship IP allowlisting for the admin panel. - The login endpoint enforces the global
RATE_LIMITsetting (default100/minuteper IP). Tighten this if you expose the admin publicly:
RATE_LIMIT = "10/minute"