Django外键只读

时间:2008-12-04 09:07:37

标签: django django-admin

我有两个模型,一个是Employee,另一个是Asset,Asset和Employee之间有多对一关系。并且Asset作为StackedInline字段添加到Employee Admin界面,无论如何,我可以在Employee Admin中将Asset作为只读字段。

我的目的是显示员工目前在管理员中持有的所有资产,这样他就不会意外删除。

5 个答案:

答案 0 :(得分:3)

编辑:实际上,我认为这不适用于内联模型..

Django将在Django 1.1中添加本地只读字段,该字段应该在3月中旬左右发布。

Read Only Admin Fieldshttp://www.djangosnippets.org/snippets/937/

此代码段允许您在管理员中将字段设置为只读。

答案 1 :(得分:2)

使用此代码 并在admin.py中将其作为ReadonlyAdmin导入。这是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 :(得分:0)

我认为django-admin中没有标志,请查看Django书的第18章以获取更多详细信息,您需要手动破解模板

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

答案 3 :(得分:0)

我想也许您可以将自定义窗口小部件添加到只是基本窗体的字段中,除非在所有元素上设置“禁用” - 我无法告诉您如何删除添加新记录的可能性。

答案 4 :(得分:0)

如果您只想显示员工的资产,可以更改默认的django admin change_form.html。 (您可能还想先禁用内联)

要覆盖默认管理模板,请将管理模板文件夹复制到本地django模板文件夹(settings.py中的$ {TEMPLATE_DIRS})

在change_form.html中,有这个块,

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

用于显示内联,以及您可以在此处执行的操作是,将一些额外信息(例如当前员工的资产列表)呈现给此模板,并将它们放在原始内联位置的上方。

现在问题是:如何将此额外信息呈现给此模板?这可以通过覆盖Employee管理模型中的change_view()函数来完成。

例如,在您的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)

现在回到管理员的change_form.html,使用模板标签显示EmployeeAdmin中的extra_context。

例如,

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

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

希望这会有所帮助,这与django 1.2.4

有关