Задать вопрос

Тел: +7 965 3737 888

683

Просмотров

11

Ответов

Readonly admin fields

<p>Put this code and import it where you define your ModelAdmin-classes.
</p>
# typical admin.py file:
from django.contrib import admin
from foo.bar import ReadOnlyAdminFields

class MyModelAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
    readonly = ('field1', 'field2',)

Вопрос полезен? Да0/Нет0
file_4136.py(1.2Кб)
None

Ответы (11):

Ответfarmking:18.03.2013
Ответ полезен? Да0/Нет0

This appears to now be built in to django.contrib.admin as readonly_fields and works with StackedInline and TabularInline in addition to ModelAdmin.

https://github.com/django/django/blob/master/django/contrib/admin/options.py

Ответseddonym:18.01.2010
Ответ полезен? Да0/Нет0

I couldn't get this to work - I get the following error:

'NoneType' object is not callable

Traceback: File "/usr/local/lib/python2.6/dist-packages/django/core/handlers/base.py" in get_response 99. response = callback(request, callback_args, callback_kwargs) File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/options.py" in wrapper 237. return self.admin_site.admin_view(view)(*args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in call 36. return self.decorator(self.func)(args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in _wrapped_view 86. response = view_func(request, *args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in call 36. return self.decorator(self.func)(args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func 70. response = view_func(request, *args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/sites.py" in inner 187. return view(request, args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in _wrapped_view 86. response = view_func(request, *args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/db/transaction.py" in _commit_on_success 295. res = func(args, *kw) File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/options.py" in change_view 894. form = ModelForm(instance=obj)

Exception Type: TypeError at /admin/snippets/snippet/1/ Exception Value: 'NoneType' object is not callable

Ответniran:20.12.2009
Ответ полезен? Да0/Нет0

get_form() should accept arbitrary kwargs as well to match the signature of the function being overridden.

Ответinvitro:11.10.2009
Ответ полезен? Да0/Нет0

EDIT: I forgot to tell this, change the code after those line and this is complete code of "ReadOnlyAdminFields"

class ReadOnlyAdminFields( object ):
    def get_form( self, request, obj = None ):
        form = super( ReadOnlyAdminFields, self ).get_form( request, obj )

        if hasattr( self, 'readonly' ):
            for field_name in self.readonly:
                if field_name in form.base_fields:

                    # field with 'choices' attribute
                    if hasattr( obj, 'get_%s_display' % field_name ):
                        original_value  = getattr( obj, field_name, '' )
                        display_value   = getattr( obj, 'get_%s_display' % field_name )()
                    # ForeignKey or ManyToManyField
                    elif hasattr( obj, '%s_id' % field_name ):
                        original_value  = getattr( obj, "%s_id" % field_name, '' )
                        display_value   = getattr( obj, field_name, '' )
                    # other field type
                    else:
                        original_value  = getattr( obj, field_name, '' )
                        display_value   = getattr( obj, field_name, '' )

                    form.base_fields[field_name].widget     = ReadOnlyWidget( original_value, display_value )
                    form.base_fields[field_name].required   = False

Ответinvitro:11.10.2009
Ответ полезен? Да0/Нет0

To make it work with ForeignKey or ManyToManyField, I changed line 27-31:

# field with 'choices' attribute
if hasattr( obj, 'get_%s_display' % field_name ):
    original_value  = getattr( obj, field_name, '' )
    display_value   = getattr( obj, 'get_%s_display' % field_name )()
# ForeignKey or ManyToManyField
elif hasattr( obj, '%s_id' % field_name ):
    original_value  = getattr( obj, "%s_id" % field_name, '' )
    display_value   = getattr( obj, field_name, '' )
# other field type
else:
    original_value  = getattr( obj, field_name, '' )
    display_value   = getattr( obj, field_name, '' )

I hope it helps

Ответline:23.07.2009
Ответ полезен? Да0/Нет0

If you want activate this feature only for a specific user group, put this code and import it where you define your ModelAdmin-classes.

# typical admin.py file:
from django.contrib import admin
from foo.bar import ReadOnlyAdminFields

class MyModelAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        if request.user.is_authenticated():
            ReadOnlyAdminFields.readonly = ('',)
            for group in request.user.groups.all():
                if str(group) == 'LimitedGroup':
                    ReadOnlyAdminFields.readonly = ('field1', 'field2',)
        return super(SetAdmin, self).get_form(request, obj, **kwargs)

Limitation: the name of the group (LimitedGroup) is hard coded here, which is not recommended. But it still provides some hints on how to do it. Man can imagine a simple model class to add/configure those limited groups.

If you have some better code feel free to share! ;)

Ответrickvanderzwet:30.11.2008
Ответ полезен? Да0/Нет0

Will there be some way to also enable this very useful fields in InlineForms as well? As snippet below, does not seems to fix it.

# typical admin.py file:
from django.contrib import admin
from foo.bar import ReadOnlyAdminFields

class MyModelInline(ReadOnlyAdminFields, admin.TabularInline):
    readonly = ('fieldFoo', 'fieldBar',)

class MyModelAdmin(ReadOnlyAdminFields,admin.ModelAdmin):
    readonly = ('field1', 'field2',)
    inlines = (MyModelInline, )

Ответekellner:28.08.2008
Ответ полезен? Да0/Нет0

I see, it doesn't use a hidden field because it intercepts the value_from_datadict call to the widget. Unfortunately, when the field owning the widget expects a form value isn't the same as the object property value -- as is the case for widgets that post more than 1 value, or foreign key values where the field expects an id -- the widget doesn't provide the value in the right format for the field.

Ответekellner:28.08.2008
Ответ полезен? Да0/Нет0

I think this needs to output a hidden input field on render, or else the form that this belongs to will not validate. I think just by inheriting from widget.HiddenInput and calling super on render, it should (basically) work.

Ответdjbe:27.08.2008
Ответ полезен? Да0/Нет0

It works - but when I try to update existing data via admin interface, I get blocked and receive the errormessage:

"Enter a list of values."

This happens on a DateTime field. I have not tried others so far.

Ответmredar:26.08.2008
Ответ полезен? Да0/Нет0

This worked great. Should be part of the main Django branch IMHO, seems to be a bit of functionality that is needed quite often!