【Django】Admin内联显示去掉多余行

本文介绍如何在DjangoAdmin中优化内联显示,通过设置extra参数为0,解决显示多余的空白行问题,避免无效数据的保存。
Django Admin内联显示去掉多余行
  • Django Admin可以设置内联显示,让有外键依赖的Model再同一个页面显示。
# admin.py
# Case为Result的外键
# 相同于 一个Case下,有多个Result

class ResultInline(admin.TabularInline):
    model = Result

class CaseAdmin(admin.ModelAdmin):
    inlines = [ResultInline]

admin.site.register(Case, CaseAdmin)
  • 上面的代码,可以让Django Admin管理 Case时,可以显示隶属于该Case的Result。
  • 实际运行起来时,发现在Case管理页面,显示Result的部分,会多出几个空白行。而且,这几行没法删除,如果点击Save,会把这几个当成Result,保存进去。
  • 修改,将extra设置为0即可。
class ResultInline(admin.TabularInline):
    model = Result
    extra = 0   # 将额外的行设置为0,即可
  • 关于extra解释如下
  • https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.extra

InlineModelAdmin.extra
This controls the number of extra forms the formset will display in addition to the initial forms. See the formsets documentation for more information.
For users with JavaScript-enabled browsers, an “Add another” link is provided to enable any number of additional inlines to be added in addition to those provided as a result of the extra argument.
The dynamic link will not appear if the number of currently displayed forms exceeds max_num, or if the user does not have JavaScript enabled.

<think>我们讨论Django Admin中的内联(Inline)个性化用法。内联允许在父模型的编辑页面编辑关联的子模型数据。 常用的内联有TabularInline(表格形式)和StackedInline(堆叠形式)。个性化通常涉及自定义内联显示、表单、为等。 以下是一些常见的个性化用法: 1. 自定义显示的字段 2. 添加自定义的表单验证或逻辑 3. 重写内联表单集以增加自定义方法 4. 根据条件动态设置只读字段或排除字段 5. 自定义表单的布局和样式 假设有两个模型:Author(作者)和Book(书籍),Book通过外键关联到Author。 首先定义模型(models.py): ```python from django.db import models class Author(models.Model): name = models.CharField(max_length=100) email = models.EmailField() def __str__(self): return self.name class Book(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCADE) title = models.CharField(max_length=200) publication_date = models.DateField() is_published = models.BooleanField(default=False) def __str__(self): return self.title ``` 接下来,我们创建一个内联,并对其进个性化定制。 在admin.py中: ```python from django.contrib import admin from .models import Author, Book # 自定义内联表单集,可以添加额外的验证或保存逻辑 from django.forms.models import BaseInlineFormSet class CustomBookFormSet(BaseInlineFormSet): def clean(self): super().clean() # 自定义验证逻辑,例如:检查是否有重复的书名 titles = [] for form in self.forms: if not form.is_valid(): return if form.cleaned_data and not form.cleaned_data.get('DELETE', False): title = form.cleaned_data.get('title') if title in titles: form.add_error('title', 'This book title is duplicated in this set.') titles.append(title) # 自定义内联 class BookInline(admin.TabularInline): # 或者使用StackedInline model = Book extra = 1 # 控制额外显示的空表单数量 # 自定义显示的字段 fields = ('title', 'publication_date', 'is_published', 'custom_field') # 注意:如果模型中没有'custom_field',我们需要使用只读字段或者自定义方法来显示 # 只读字段 readonly_fields = ('custom_field',) # 定义自定义字段(模型中存在,需要自定义方法) def custom_field(self, instance): # 这里可以返回一些自定义的HTML或字符串 if instance.pk: return f"Custom: {instance.title.upper()}" return "New book" custom_field.short_description = 'Custom Info' # 使用自定义的表单集 formset = CustomBookFormSet # 根据条件动态设置只读字段 def get_readonly_fields(self, request, obj=None): # 如果对象已经存在(即编辑现有作者),则让publication_date只读 if obj: # obj是父模型实例,这里指Author return self.readonly_fields + ('publication_date',) return self.readonly_fields # 还可以通过重写表单来定制字段的widget等 # 定义内联自己的表单类 from django import forms class BookForm(forms.ModelForm): class Meta: model = Book fields = '__all__' # 可以在这里自定义字段的widget publication_date = forms.DateField(widget=forms.TextInput(attrs={'type': 'date'})) form = BookForm @admin.register(Author) class AuthorAdmin(admin.ModelAdmin): inlines = [BookInline] ``` 上述代码中,我们实现了: 1. 自定义内联表单集(CustomBookFormSet),用于添加自定义的验证逻辑(这里检查重复书名)。 2. 在内联中定义了一个只读的自定义字段(custom_field),显示为大写的书名。 3. 根据父模型实例是否存在(即新建还是编辑)动态设置只读字段(编辑时publication_date变为只读)。 4. 使用自定义的表单(BookForm)来改变publication_date字段的widget,使其使用日期选择器。 注意:自定义字段(custom_field)在模型中没有定义,因此需要在模型中添加一个方法,或者内联中定义。这里我们在内联中定义了一个方法custom_field。 但是,如果需要在列表显示显示计算字段,也可以在模型中使用@property,并在内联的readonly_fields中添加属性名。 另外,内联还支持其他个性化,比如: - 控制内联显示数量(使用min_num, max_num) - 通过重写get_queryset方法来控制内联显示的对象 - 添加额外的上下文数据等 示例:重写get_queryset方法来过滤内联显示的书(只显示已出版的): ```python class BookInline(admin.TabularInline): model = Book def get_queryset(self, request): qs = super().get_queryset(request) return qs.filter(is_published=True) ``` 以上是Django Admin内联个性化的一些常见用法。 注意:在实际使用中,请根据需求选择合适的方式。 现在,我来提出相关问题: </think>### Django Admin 内联个性化用法详解 在 Django Admin 中使用内联(如 `TabularInline` 或 `StackedInline`)时,可通过以下方式实现个性化定制: #### 基础示例 假设有 `Author`(作者)和 `Book`(书籍)两个模型,`Book` 通过外键关联 `Author`: ```python # models.py from django.db import models class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCADE) title = models.CharField(max_length=200) publish_date = models.DateField() is_published = models.BooleanField(default=False) ``` --- ### 个性化定制方案 #### 1. 自定义字段显示 ```python # admin.py from django.contrib import admin class BookInline(admin.TabularInline): # 或 StackedInline model = Book extra = 1 # 空表单数量 # 指定显示字段(排除外键) fields = ('title', 'publish_date', 'is_published', 'status') readonly_fields = ('status',) # 只读字段 # 计算字段(需在模型中定义或此处自定义) def status(self, instance): return "已发布" if instance.is_published else "未发布" status.short_description = '状态' ``` #### 2. 动态表单字段 ```python class BookInline(admin.TabularInline): model = Book def get_formset(self, request, obj=None, **kwargs): formset = super().get_formset(request, obj, **kwargs) # 根据作者名称动态修改字段必填性 if obj and obj.name == "特殊作者": formset.form.base_fields["title"].required = False return formset ``` #### 3. 条件过滤内联数据 ```python class BookInline(admin.TabularInline): model = Book def get_queryset(self, request): qs = super().get_queryset(request) # 只显示已出版的书籍 return qs.filter(is_published=True) ``` #### 4. 自定义表单验证 ```python from django.forms.models import BaseInlineFormSet class CustomFormSet(BaseInlineFormSet): def clean(self): super().clean() for form in self.forms: if form.cleaned_data.get('is_published') and not form.cleaned_data.get('title'): form.add_error('title', '已出版书籍必须有标题') class BookInline(admin.TabularInline): model = Book formset = CustomFormSet # 使用自定义表单集 ``` #### 5. 完整集成示例 ```python # admin.py @admin.register(Author) class AuthorAdmin(admin.ModelAdmin): inlines = [BookInline] list_display = ('name',) # 动态控制内联显示(例如仅对管理员显示) def get_inline_instances(self, request, obj=None): if request.user.is_superuser: return [BookInline(self.model, self.admin_site)] return [] ``` --- ### 关键特性说明 1. **字段控制** `fields`/`exclude` 控制显示字段,`readonly_fields` 设置只读字段 2. **动态为** 通过重写 `get_formset` 或 `get_queryset` 实现条件逻辑 3. **验证扩展** 自定义 `BaseInlineFormSet` 添加复杂验证规则 4. **权限控制** 在 `get_inline_instances` 中基于请求对象或父对象控制内联显示 5. **UI优化** `verbose_name` 修改标签文本,`classes` 添加CSS类控制折叠样式 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值