在ModelForm表单字段定义中访问Django模型实例

时间:2011-03-25 16:41:38

标签: django django-forms olwidget

在我的某个管理表单中,我覆盖了一个模型表单字段(location),以便使用不同的地图特定表单字段(olwidget)。此MapField应包含一个图层(InfoLayerField),该图层显示所有其他模型实例,但此时正在编辑的实例。现在,它显示所有模型实例(参见MyModel.objects.all()),这意味着,如果编辑模型,当前位置将显示两次。

为了实现这一点,我必须从InfoLayerField中使用的QuerySet(类似MyModel.objects.exclude(pk=self.instance.pk))中排除当前编辑的模型实例。但由于表单字段被定义为静态变量,我无法访问self.instance

有没有办法实现这个目标?

# models.py
class MyModel(models.Model):
    name = models.CharField(max_length=200)
    location = models.PointField(blank=True, null=True)


# admin.py
from olwidget.fields import MapField, EditableLayerField, InfoLayerField
from olwidget.utils import get_ewkt

class MyModelAdminForm(forms.ModelForm):
    class Meta:
        model = MyModel

    location = MapField([
        EditableLayerField({
            'geometry': 'point',
            'name': 'location',
        }),
        InfoLayerField(
            [(get_ewkt(m.location), m.name) for m in MyModel.objects.all() if m.location ], {
                'geometry': 'point',
                'name': 'other locations',
                'cluster': True,
                'cluster_display': 'list',
            }
        )
    ])

class MyModelOlwidgetAdmin(admin.ModelAdmin, GeoModelAdmin):
    form = MyModelAdminForm

...

感谢任何提示。

1 个答案:

答案 0 :(得分:4)

我认为您只需要覆盖表单上的__init__

class MyModelAdminForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self,*args,**kwargs):
        super(MyModelAdminForm, self).__init__(*args,**kwargs)
        qs = MyModel.objects.exclude(pk = self.instance.pk) #grab instance.pk here
        self.fields['location'] = MapField([
            EditableLayerField({
                'geometry': 'point',
                'name': 'location',
            }),
            InfoLayerField(
                [(get_ewkt(m.location), m.name) for m in qs if m.location ], {
                    'geometry': 'point',
                    'name': 'other locations',
                    'cluster': True,
                    'cluster_display': 'list',
                }
            )
        ])