Opened 15 years ago
Closed 15 years ago
#14095 closed (invalid)
Objects not saved when readonly_fields is set for inline admin
| Reported by: | Owned by: | nobody | |
|---|---|---|---|
| Component: | contrib.admin | Version: | 1.2 |
| Severity: | Keywords: | TabularInline, inline, readonly_fields, sprintdec2010 | |
| Cc: | simon@… | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Code
models.py:
class BalanceCode(models.Model):
created_at = models.DateField(auto_now_add=True)
code = models.CharField(max_length=BALANCE_CODE_LENGTH, unique=True,
default=generate_balance_code, help_text=code_help)
value = models.PositiveIntegerField(default=BALANCE_CODE_DEFAULT_VALUE)
refill_series = models.ForeignKey(RefillSeries)
used_by = models.ForeignKey(Student, null=True, blank=True)
used_at = models.DateField(blank=True, null=True)
class RefillSeries(models.Model):
issued = models.DateField(default=default_issued)
least_valid_until = models.DateField(default=default_least_valid_until)
admin.py:
class BalanceCodeInline(admin.TabularInline):
readonly_fields = ('code', )
model = BalanceCode
extra = SERIES_CODE_COUNT
max_num = SERIES_CODE_COUNT
class BalanceCodeAdmin(admin.ModelAdmin):
readonly_fields = ('code', )
class RefillSeriesAdmin(admin.ModelAdmin):
inlines = (BalanceCodeInline,)
Problem Description
Expected
When a new RefillSeries is created, SERIES_CODE_COUNT BalanceCodes should
be created as well.
Actual
No BalanceCodes are created. When readonly_fields is unset,
SERIES_CODE_COUNT objects are created, as expected.
Creating new BalanceCodes directly (not inlined in the RefillSeries admin
interface) works as expected when readonly_fields is set.
Change History (2)
comment:1 by , 15 years ago
comment:2 by , 15 years ago
| Keywords: | sprintdec2010 added |
|---|---|
| Resolution: | → invalid |
| Status: | new → closed |
Thank you for the report, Simon. It is true that Django is behaving oddly here. However, this is caused by the way inlines are currently designed to work. If you make the code field readonly, then there will not be any input added to the form for it, which means that Django has no way of detecting that anything has changed in the form, and therefore cannot know that an object should be created.
I've discussed this at length with russelm and DrMeers (both core committers), and the answer is that this cannot be fixed. To achieve what you want you'd probably have to not make the code field readonly, and then use a bit of javascript to prevent the user from modifying it.
For that reason I'm closing this ticket as invalid. I also invite you to look into ticket #14832, which has in fact emerged after looking at this one and which discusses a related issue.
Finally, for the record, here's the code I've used to study this issue (some elements like generate_balance_code or SERIES_CODE_COUNT were missing in your description):
Models:
import datetime, hashlib from django.db import models from django.contrib.auth.models import User def generate_balance_code(): return hashlib.md5(str(datetime.datetime.now())).hexdigest() class RefillSeries(models.Model): issued = models.DateField(default=datetime.datetime.today) least_valid_until = models.DateField(default=datetime.datetime.today() + datetime.timedelta(days=10000)) class BalanceCode(models.Model): created_at = models.DateField(auto_now_add=True) code = models.CharField(max_length=100, unique=True, default=generate_balance_code,) value = models.PositiveIntegerField(default=10) refill_series = models.ForeignKey(RefillSeries) used_by = models.ForeignKey(User, null=True, blank=True) used_at = models.DateField(blank=True, null=True)
Admin:
from django.contrib import admin from .models import BalanceCode, RefillSeries class BalanceCodeAdmin(admin.ModelAdmin): readonly_fields = ('code', ) class BalanceCodeInline(admin.TabularInline): readonly_fields = ('code', ) model = BalanceCode extra = 2 max_num = 5 class RefillSeriesAdmin(admin.ModelAdmin): inlines = [BalanceCodeInline] admin.site.register(BalanceCode, BalanceCodeAdmin) admin.site.register(RefillSeries, RefillSeriesAdmin)
Addendum: The inlined
BalanceCodes show up in the admin interface, but they are not saved to database.