Display Django admin changelists within changeform pages using Datasets. Learn how to show related data alongside model forms with list display, search, sorting, and pagination features.
Datasets allow you to embed Django admin changelists directly within changeform pages. This powerful feature enables you to display related data alongside a model’s edit form, providing a comprehensive view of associated records without leaving the page.
Define a ModelAdmin class with your desired changelist configuration.
admin.py
from unfold.admin import ModelAdminfrom .models import Orderclass OrderDatasetAdmin(ModelAdmin): search_fields = ["order_number", "customer__name"] list_display = ["order_number", "customer", "status", "total_amount", "created_at"] list_display_links = ["order_number"] list_per_page = 20 # Default: 10 def get_queryset(self, request): # Access the parent object from extra_context customer_id = self.extra_context.get("object") # Return no results on the create page if not customer_id: return super().get_queryset(request).none() # Filter orders by the current customer return super().get_queryset(request).filter( customer_id=customer_id ).select_related('customer')
2
Create the Dataset Class
Create a dataset class that inherits from BaseDataset and references your ModelAdmin.
admin.py
from unfold.datasets import BaseDatasetclass CustomerOrdersDataset(BaseDataset): model = Order model_admin = OrderDatasetAdmin tab = False # Set to True to display in a tab
3
Register the Dataset
Add the dataset to the parent model’s change_form_datasets.
from unfold.admin import ModelAdminclass OrderDatasetAdmin(ModelAdmin): list_display = ["order_number", "status", "total_amount"] def get_queryset(self, request): customer_id = self.extra_context.get("object") if not customer_id: return super().get_queryset(request).none() queryset = super().get_queryset(request).filter(customer_id=customer_id) # Restrict based on user permissions if not request.user.is_superuser: # Regular users only see their assigned orders if hasattr(request.user, 'sales_rep_profile'): queryset = queryset.filter( sales_rep=request.user.sales_rep_profile ) else: # Users without a sales rep profile see nothing queryset = queryset.none() return queryset def has_add_permission(self, request): # Only allow superusers to add orders from the dataset return request.user.is_superuser def has_delete_permission(self, request, obj=None): # Only allow order deletion for managers return request.user.groups.filter(name='Managers').exists()
Always handle the case when object is None in your get_queryset() method. This occurs when creating a new parent object. Return an empty queryset using .none() to prevent errors.