Автоматическое резервное копирование последней записи в поле в админке django
У меня есть модель, которая служит базой данных цен для детали:
class Part(models.Model):
name = models.CharField("name", max_length=128)
class Price(models.Model):
value = models.DecimalField(max_digits=10, decimal_places=2)
part = models.ForeignKey(Part, on_delete=models.CASCADE)
is_active = models.BooleanField(default=True)
В админке я хочу иметь поле, в котором можно изменить цену, но также и список, в котором видны старые цены. Я вроде бы решил эту проблему с помощью встроенных методов Django, но это кажется довольно сложным для такого простого запроса:
class FakePlainTextWidget(forms.Widget):
"""
this widget masks an input field for prices so they are only being listed and not really editable or look that way
"""
def __init__(self, attrs=None):
super().__init__(attrs)
def render(self, name, value, attrs, renderer=None):
s = f"""border: none; background-color: transparent; pointer-events: none; -webkit-appearance: none; -moz-appearance: textfield;"""
return format_html(f"""<input type="number" name="{attrs["id"][3:]}" value="{value}" id="{attrs["id"]}" style="{s}"> €""")
class PriceInlineForm(forms.ModelForm):
class Meta:
model = Price
fields = "__all__"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and not self.instance.is_active:
# make fields read-only if price is_active=False
for field in self.fields:
self.fields[field].widget = FakePlainTextWidget()
def save(self, commit=False):
instance = super().save(commit=False)
instance.is_active = False
instance.save(update_fields=["is_active"])
Price.objects.create(value=self.cleaned_data["value"], part=instance.part)
return instance
class PriceInline(admin.TabularInline):
model = Price
can_delete = False
exclude = ["is_active",]
extra = 0 # No extra empty forms
min_num = 1 # Ensure at least one form is displayed
max_num = 1 # Ensure only one form can be added
form = PriceInlineForm
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.order_by("-id") # so active input is first
@admin.register(Part)
class PartAdmin(admin.ModelAdmin):
inlines = [PriceInline]
Мне кажется, что должен быть гораздо более простой способ добиться того же самого?