Django foreign keys only

I have two models, one is Employee and the other is Asset, with a Many-to-One relationship between Asset and Employee. And the Asset is added as a StackedInline field to the Employee admin interface, I can still make the Asset as a read-only field in Employee Admin.

My intention was to show all the assets that the employee currently holds in Admin so that he doesn't accidentally delete it.

+1


source to share


5 answers


Edit: Actually, I don't think this will work for inline models.

Django will be adding its own read-only fields in Django 1.1, due out around mid-March.



read-only fields ( http://www.djangosnippets.org/snippets/937/ )

This snippet will allow you to set fields as read-only in admin.

+3


source


use this code and import it into admin.py as ReadonlyAdmin.This is a modified form of readonly admin.



from django import forms
from django.utils.safestring import mark_safe
from datetime import datetime

class ReadOnlyWidget(forms.Widget):
    def __init__(self, original_value, display_value):
        self.original_value = original_value
        self.display_value = display_value
        super(ReadOnlyWidget, self).__init__()

    def render(self, name, value, attrs=None):
        if self.display_value is not None:
            return unicode(self.display_value)
        return unicode(self.original_value)

    def value_from_datadict(self, data, files, name):
        return self.original_value

#to make fields  foreignkey readonly

class ReadOnlyAdminFields(object):
    def get_form(self, request, obj=None):
        form = super(ReadOnlyAdminFields, self).get_form(request, obj)
        if hasattr(self, 'readonly') and obj is not None:
            for field_name in self.readonly:
                if field_name in form.base_fields:
                    if hasattr(obj, 'get_%s_display' % field_name):
                        display_value = getattr(obj, 'get_%s_display' % field_name)()
                    else:
                        display_value = None
                    if getattr(obj, field_name).__class__ in [unicode , long, int, float, datetime, list]:
                        form.base_fields[field_name].widget = ReadOnlyWidget(getattr(obj, field_name), display_value)
                    else:
                        form.base_fields[field_name].widget = ReadOnlyWidget(getattr(obj, field_name).id, display_value)
            form.base_fields[field_name].required = False
        return form

      

+2


source


I don't think there is a flag in django-admin for this, check out chapter 18 of the Django book for more details, you need to hack the templates manually

http://www.djangobook.com/en/beta/chapter18/

0


source


I think that perhaps you can add a custom widget to fields that have only a basic form, other than being "disabled" for all elements. I cannot tell you how to remove the ability to add new entries.

0


source


If you only want to display employee assets, you can change the default django admin change_form.html. (and you can also disable inline first)

To override the default admin templates, copy the admin template folder to your local django templates folder ($ {TEMPLATE_DIRS} in your settings.py file)

And there is this block in the change_form.html file,

{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}

      

Used to display inline strings, and here you can do some additional information like a list of assets of the current employee and place them above where the inline strings originate from.

And now the question is, how do I provide this additional information to this template? This can be done by overriding the change_view () function in your Employee admin model.

For example in your admin.py

class EmployeeAdmin(admin.ModelAdmin):
    ...

    def change_view(self, request, object_id, extra_context=None):
        assets = Asset.objects.filter(employee=Employee.objects.get(id=object_id))
        context_data = {'inlines': assets, }
        return super(EmployeeAdmin, self).change_view(request, object_id, extra_context=context_data)

      

Now go back to your admin change_form.html, user template tags to display the extra_context from your EmployeeAdmin.

eg,

{% for inline in inlines %}
    {{ inline }}
{% endfor %}

{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}

      

Hope it helps and this is as of django 1.2.4

0


source







All Articles