将动态字段添加到django管理模型表单

时间:2022-09-12 08:52:26

I need to add the field with link to the model view on my site to the django admin view. When I add field name to the list_display and define method for rendering this url:

我需要将包含我网站上模型视图链接的字段添加到django管理视图中。当我向list_display添加字段名称并定义用于呈现此URL的方法时:

class SetAdmin(admin.ModelAdmin):
    list_display = ['many other fields', 'show_set_url']

    def show_set_url(self, obj):
            return '<a href="#">Set</a>' # render depends on other fields

It shows in Sets list in django admin, but not in model form. How can I fix this and add link to the Sets Form in django admin?

它显示在django admin中的Sets列表中,但不是以模型形式显示。如何修复此问题并在django admin中添加指向“设置表单”的链接?

I've tried also to create custom form for this model:

我也试过为这个模型创建自定义表单:

from core.models import Set
from django import forms

class SetAdminForm(forms.Form):
    class Meta:
        model = Set

    def __init__(self, *args, **kwargs):
        super(SetAdminForm, self).__init__(*args, **kwargs)
        self.fields['foo'] = forms.IntegerField(label=u"Link")

But there is now visible effect in form.

但现在形式上有明显的效果。

4 个解决方案

#1


5  

You can accomplish what you're trying by overriding ModelAdmin but you also need to override ModelAdmin.get_fieldsets. This answer might help you out. The OP in the link has a similar problem as well.

您可以通过重写ModelAdmin来完成您尝试的操作,但您还需要覆盖ModelAdmin.get_fieldsets。这个答案可能会帮到你。链接中的OP也存在类似的问题。

Edit: If you don't want an editable field you can try overriding ModelAdmin.get_readonly_fields. Also check here for more attributes to override.

编辑:如果您不想要可编辑字段,可以尝试重写ModelAdmin.get_readonly_fields。另请在此处查看要覆盖的更多属性。

#2


2  

You can create dynamic fields and fieldset using the form meta class. Sample code is given below. Add the loop logic as per you requirements.

您可以使用表单元类创建动态字段和字段集。示例代码如下。根据您的要求添加循环逻辑。

class CustomAdminFormMetaClass(ModelFormMetaclass):
    """
    Metaclass for custom admin form with dynamic field
    """
    def __new__(cls, name, bases, attrs):
        for field in myloop: #add logic to get the fields
            attrs[field] = forms.CharField(max_length=30) #add logic to the form field
        return super(CustomAdminFormMetaClass, cls).__new__(cls, name, bases, attrs)


class CustomAdminForm(six.with_metaclass(CustomAdminFormMetaClass, forms.ModelForm)):
    """
    Custom admin form
    """

    class Meta:
        model = ModelName
        fields = "__all__" 


class CustomAdmin(admin.ModelAdmin):
    """
    Custom admin 
    """

    fieldsets = None
    form = CustomAdminForm

    def get_fieldsets(self, request, obj=None):
        """
        Different fieldset for the admin form
        """
        self.fieldsets = self.dynamic_fieldset(). #add logic to add the dynamic fieldset with fields
        return super(CustomAdmin, self).get_fieldsets(request, obj)

    def dynamic_fieldset(self):
        """
        get the dynamic field sets
        """
        fieldsets = []
        for group in get_field_set_groups: #logic to get the field set group
            fields = []
            for field in get_group_fields: #logic to get the group fields
                fields.append(field)

            fieldset_values = {"fields": tuple(fields), "classes": ['collapse']}
            fieldsets.append((group, fieldset_values))

        fieldsets = tuple(fieldsets)

        return fieldsets

#3


1  

I had trouble with all of these answers in Django 1.9 for inline models.

我在Django 1.9中为内联模型解决了所有这些问题。

Here is a code snippet that accomplished dynamic fields for me. In this example, I'm assuming you already have a modal called ProductVariant which contains a foreign key relationship to a model called Product:

这是一个为我完成动态字段的代码片段。在这个例子中,我假设你已经有一个名为ProductVariant的模态,它包含一个名为Product的模型的外键关系:

class ProductVariantForm(forms.ModelForm):
  pass

class ProductVariantInline(admin.TabularInline):
  model = ProductVariant
  extra = 0

  def get_formset(self, request, obj=None, **kwargs):
    types = ( (0, 'Dogs'), (1, 'Cats'))
        #Break this line appart to add your own dict of form fields.
        #Also a handy not is you have an instance of the parent object in obj
    ProductVariantInline.form = type( 'ProductVariantFormAlt', (ProductVariantForm, ), { 'fancy_select': forms.ChoiceField(label="Animals",choices=types)})
    formset = super( ProductVariantInline, self).get_formset( request, obj, **kwargs)
    return formset

class ProductAdmin(admin.ModelAdmin):
  inlines = (ProductVariantInline, )

My specific use case is ProductVariant has a many to many relationship that should only have limited selections based on business logic grouping of the entries. Thus my need for custom dynamic fields in the inline.

我的具体用例是ProductVariant具有多对多关系,只能根据条目的业务逻辑分组进行有限的选择。因此我需要内联中的自定义动态字段。

#4


0  

You have to add it to the readonly_fields list.

您必须将其添加到readonly_fields列表中。

class SetAdmin(admin.ModelAdmin):
    list_display = ['many other fields', 'show_set_url']
    readonly_fields = ['show_set_url']

    def show_set_url(self, obj):
            return '<a href="#">Set</a>' # render depends on other fields

Relevant documentation.

#1


5  

You can accomplish what you're trying by overriding ModelAdmin but you also need to override ModelAdmin.get_fieldsets. This answer might help you out. The OP in the link has a similar problem as well.

您可以通过重写ModelAdmin来完成您尝试的操作,但您还需要覆盖ModelAdmin.get_fieldsets。这个答案可能会帮到你。链接中的OP也存在类似的问题。

Edit: If you don't want an editable field you can try overriding ModelAdmin.get_readonly_fields. Also check here for more attributes to override.

编辑:如果您不想要可编辑字段,可以尝试重写ModelAdmin.get_readonly_fields。另请在此处查看要覆盖的更多属性。

#2


2  

You can create dynamic fields and fieldset using the form meta class. Sample code is given below. Add the loop logic as per you requirements.

您可以使用表单元类创建动态字段和字段集。示例代码如下。根据您的要求添加循环逻辑。

class CustomAdminFormMetaClass(ModelFormMetaclass):
    """
    Metaclass for custom admin form with dynamic field
    """
    def __new__(cls, name, bases, attrs):
        for field in myloop: #add logic to get the fields
            attrs[field] = forms.CharField(max_length=30) #add logic to the form field
        return super(CustomAdminFormMetaClass, cls).__new__(cls, name, bases, attrs)


class CustomAdminForm(six.with_metaclass(CustomAdminFormMetaClass, forms.ModelForm)):
    """
    Custom admin form
    """

    class Meta:
        model = ModelName
        fields = "__all__" 


class CustomAdmin(admin.ModelAdmin):
    """
    Custom admin 
    """

    fieldsets = None
    form = CustomAdminForm

    def get_fieldsets(self, request, obj=None):
        """
        Different fieldset for the admin form
        """
        self.fieldsets = self.dynamic_fieldset(). #add logic to add the dynamic fieldset with fields
        return super(CustomAdmin, self).get_fieldsets(request, obj)

    def dynamic_fieldset(self):
        """
        get the dynamic field sets
        """
        fieldsets = []
        for group in get_field_set_groups: #logic to get the field set group
            fields = []
            for field in get_group_fields: #logic to get the group fields
                fields.append(field)

            fieldset_values = {"fields": tuple(fields), "classes": ['collapse']}
            fieldsets.append((group, fieldset_values))

        fieldsets = tuple(fieldsets)

        return fieldsets

#3


1  

I had trouble with all of these answers in Django 1.9 for inline models.

我在Django 1.9中为内联模型解决了所有这些问题。

Here is a code snippet that accomplished dynamic fields for me. In this example, I'm assuming you already have a modal called ProductVariant which contains a foreign key relationship to a model called Product:

这是一个为我完成动态字段的代码片段。在这个例子中,我假设你已经有一个名为ProductVariant的模态,它包含一个名为Product的模型的外键关系:

class ProductVariantForm(forms.ModelForm):
  pass

class ProductVariantInline(admin.TabularInline):
  model = ProductVariant
  extra = 0

  def get_formset(self, request, obj=None, **kwargs):
    types = ( (0, 'Dogs'), (1, 'Cats'))
        #Break this line appart to add your own dict of form fields.
        #Also a handy not is you have an instance of the parent object in obj
    ProductVariantInline.form = type( 'ProductVariantFormAlt', (ProductVariantForm, ), { 'fancy_select': forms.ChoiceField(label="Animals",choices=types)})
    formset = super( ProductVariantInline, self).get_formset( request, obj, **kwargs)
    return formset

class ProductAdmin(admin.ModelAdmin):
  inlines = (ProductVariantInline, )

My specific use case is ProductVariant has a many to many relationship that should only have limited selections based on business logic grouping of the entries. Thus my need for custom dynamic fields in the inline.

我的具体用例是ProductVariant具有多对多关系,只能根据条目的业务逻辑分组进行有限的选择。因此我需要内联中的自定义动态字段。

#4


0  

You have to add it to the readonly_fields list.

您必须将其添加到readonly_fields列表中。

class SetAdmin(admin.ModelAdmin):
    list_display = ['many other fields', 'show_set_url']
    readonly_fields = ['show_set_url']

    def show_set_url(self, obj):
            return '<a href="#">Set</a>' # render depends on other fields

Relevant documentation.