复杂的" limit_choices_to" Django中的函数

时间:2016-05-18 13:51:47

标签: django django-models django-admin

我有两个型号的Django数据库:DeviceModel和Device。让我们说,例如,DeviceModel对象是" LCD面板"和设备对象是" LCD面板№547"。所以这两个表有ManyToOne关系。

class DeviceModel(models.Model):
    name = models.CharField(max_length=255)

class Device(models.Model):
    device_model = models.ForeignKey(DeviceModel)
    serial_number = models.CharField(max_length=255)

现在我需要在DeviceModel对象之间添加一些关系。例如" LCD Panel"可以在"平板电脑"对象或在" Monitor"宾语。另一个对象可以是个体,因此它不与其他对象链接。

我决定用ManyToMany关系来做这件事,反对使用JSON或类似的序列化(顺便说一句,哪种方法在什么情况下更好?)。

我填写了设备模型之间的所有关系,并知道我需要在Device表中添加功能关系。

为此,我添加了#34; master_dev"外键字段指向' self'。它完全按照我的需要工作,但我想在django管理面板中限制输出。它应该只显示通过device_links连接的设备。目前的代码:

class DeviceModel(models.Model):
    name = models.CharField(max_length=255)
    device_links = models.ManyToManyField('self')

class Device(models.Model):
    device_model = models.ForeignKey(DeviceModel)
    serial_number = models.CharField(max_length=255)
    master_dev = models.ForeignKey('self', blank=True, null=True)

那么,如何限制管理面板中master_dev字段的输出? 有一个功能" limit_choices_to"但我无法让它工作......

2 个答案:

答案 0 :(得分:1)

form.py中的

def master_dev_chioses():
    chioses = DeviceModel.objects.filter(do your connection filter here - so not all Devicemodels comes to choicefield)


class DeviceForm(forms.ModelForm):
    class Meta:
        model = Device

    def __init__(self, *args, **kwargs):
        super(Device, self).__init__(*args, **kwargs)

        self.fields['master_dev'].choices = master_dev_chioses()

答案 1 :(得分:0)

虽然没有直接回答我关于" limit_choices_to"的问题。功能,我发布了实现所需输出的解决方案:

from django import forms
from django.contrib import admin
from .models import DeviceModel, Device

class DeviceForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(DeviceForm, self).__init__(*args, **kwargs)
        try:
            linked_device_models = self.instance.device_model.device_links.all()
            linked_devices = Device.objects.filter(device_model__in=linked_device_models)

            required_ids = set(linked_devices.values_list("id", flat=True))

            self.fields['master_dev'].queryset = Device.objects.filter(id__in=required_ids).order_by("device_model__name", "serial_number")         
        except:
            # can't restrict masters output if we don't know device yet
            # admin should edit master_dev field only after creation

            self.fields['master_dev'].queryset = Device.objects.none()


    class Meta:
        model = Device
        fields = ["device_model", "serial_number", "master_dev"]


class DeviceAdmin(admin.ModelAdmin):
    form = DeviceForm

    list_display = ('id', 'device_model', 'serial_number')
    list_display_links = ('id', 'device_model')
    search_fields = ('device_model__name', 'serial_number')
    list_per_page = 50
    list_filter = ('device_model',)