简体   繁体   中英

Django admin read only fields with list_display and list_editable

I'm trying to make only blank fields editable with list_display and list_editable options, I guess there are no way to do it from the "box"... but there must be methods like get_list_editable_field or way to create it and override builtin... does anyone know a way to do it? 在此处输入图像描述

Now I have just standard options, so I want only 'energy_quantity' be editable when is blank/None

class UserDataPeriodicAdmin(admin.ModelAdmin):
list_display = (
    'prim_address',
    'sec_address',
    'energy_quantity',
    'heat_power',
    'time_date',
    'apartment',
)
list_editable = ('energy_quantity',)
readonly_fields = (
    'prim_address',
    'sec_address',
    'energy_quantity',
    'heat_power',
    'flow_rate',
    'flow_t',
    'return_t',
    'time_date',
    'ver',
    'status_code',
    'apartment',
    'weather',
)
list_display_links = None
list_filter = (
    ('time_date', DateRangeFilter),
)

I returned to this question... figured out that there are some options to do this... to change visual style and other... To prevent changing data it is bad idea to use

form.fields['energy_quantity'].disabled = True

because there will be mess with forms in request. So You can copy whole

def changelist_view(self, request, extra_context=None)

to admin.Model and slightly correct if statement where it's saving data to db

if request.method == 'POST' and cl.list_editable and '_save' in request.POST

class MyAdminFormSet(BaseModelFormSet):
    def _construct_form(self, i, **kwargs):
        if self.get_queryset()[i].field_editable:
            form = super()._construct_form(i, **kwargs)
            form.fields['energy_quantity'].widget.attrs['style'] = "color: #79aec8; border: 2px solid #79aec8"
            return form
        else:
            form = super()._construct_form(i, **kwargs)
            form.fields['energy_quantity'].widget.attrs['style'] = "color:  #b7b7b7 ; border: 1px solid #b7b7b7 "
            return form


    class UserDataPeriodicAdmin(admin.ModelAdmin):
        list_display = (
            'prim_address',
            'sec_address',
            'energy_quantity',
            'heat_power',
            'time_date',
            'apartment',
        )
        list_editable = ('energy_quantity',)
        readonly_fields = (
            'prim_address',
            'sec_address',
            'energy_quantity',
            'heat_power',
            'flow_rate',
            'flow_t',
            'return_t',
            'time_date',
            'ver',
            'status_code',
            'apartment',
            'weather',
        )
        list_display_links = None
        list_filter = (
            ('time_date', DateRangeFilter),
        )

        def get_changelist_formset(self, request, **kwargs):
        kwargs['formset'] = MyAdminFormSet
        return super().get_changelist_formset(request, **kwargs)

    def changelist_view(self, request, extra_context=None):
   ...
        if request.method == 'POST' and cl.list_editable and '_save' in request.POST:
            if not self.has_change_permission(request):
                raise PermissionDenied
            FormSet = self.get_changelist_formset(request)
            modified_objects = self._get_list_editable_queryset(request, FormSet.get_default_prefix())
            formset = cl.formset = FormSet(request.POST, request.FILES, queryset=modified_objects)
            if formset.is_valid():
                changecount = 0
                for form in formset.forms:
                    if form.has_changed():
                        obj = self.save_form(request, form, change=True)
                        if obj.field_editable:
                            self.save_model(request, obj, form, change=True)
                            self.save_related(request, form, formsets=[], change=True)
                            change_msg = self.construct_change_message(request, form, None)
                            self.log_change(request, obj, change_msg)
                            changecount += 1
    ...
        return TemplateResponse(request, self.change_list_template or [
            'admin/%s/%s/change_list.html' % (app_label, opts.model_name),
            'admin/%s/change_list.html' % app_label,
            'admin/change_list.html'
        ], context)

Additionally there are other salvations, for example to check saving data in model.Model

class UserDataPeriodic(models.Model):
energy_quantity = models.IntegerField(null=True, blank=True, verbose_name='Спожито тепла, кВт*год')
field_editable = models.BooleanField(default=True)

__original_energy_quantity = None

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.__original_energy_quantity = self.energy_quantity

def save(self, force_insert=False, force_update=False, using=None,
         update_fields=None, *args, **kwargs):
    if self.energy_quantity != self.__original_energy_quantity and not self.field_editable:
        return
    else:
        return super().save(force_insert, force_update, *args, **kwargs)

I guess there are other options to play with rendered data in

def changelist_view

图片

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM