django模型表单,显示外键文本(在模型中不使用__str__)

时间:2018-07-31 15:26:28

标签: django django-forms

我有一个映射表,我将其作为另一个表的外键引用,即

映射表:

class DeviceCircuitSubnets(models.Model):
    device = models.ForeignKey(Device, on_delete=models.CASCADE)
    circuit = models.ForeignKey(Circuit, on_delete=models.CASCADE, blank=True, null=True)

然后在我的界面表中:

class InterfaceData(models.Model):
    device_circuit = models.ForeignKey(DeviceCircuit, verbose_name="Device", on_delete=models.CASCADE)
    interface_name = models.CharField(max_length=100, verbose_name='Interface name')
    dashboard = models.BooleanField(default=False, verbose_name="Display on monitoring dashboard?")
    wallboard = models.BooleanField(default=False, verbose_name="Display on wallboards?")

我正在Forms.py中为接口数据构建表单,但是下拉菜单的显示文本只是DeviceCircuit对象。我知道这是因为我没有设置def str (自我),但是据我了解,如果这样做,我将对其他模型进行不必要的调用(即str会引用设备。主机名和circuit.circuit_type.circuit_type等等,我不需要。

我只想在需要时更改下拉菜单的显示。

到目前为止,我已经过滤并重命名了该字段,但似乎无法设置显示,可以使用模型表单吗?

class InterfaceDataForm(forms.ModelForm):
    class Meta:
        model = InterfaceData
        fields = ['device_circuit','interface_name','dashboard','wallboard']

    def __init__(self, *args, **kwargs):
        self.is_add = kwargs.pop("is_add", False)
        device_id = kwargs.pop("device_id")
        super(InterfaceDataForm, self).__init__(*args, **kwargs)
        self.fields['device_circuit'].queryset = DeviceCircuit.objects.filter(device_id=device_id) \
                                                                                        .select_related('device') \
                                                                                        .select_related('circuit') \
                                                                                        .select_related('circuit__circuit_type') \
                                                                                        .select_related('circuit__service_contact') \
                                                                                        .select_related('circuit__service_contact__provider') 
        self.fields['device_circuit'].label = 'Device / Circuit'

1 个答案:

答案 0 :(得分:0)

如果您希望下拉文本为'{} - {} {}'.format(device.hostname,circuit.circuit_type, circuit.provider),那么您是正确的,这将调用其他模型。但这真的有问题吗?如果要显示该信息,则必须在某个时候进行。假设每次为DeviceCircuit调用 str 时都使用select / prefetch_related,那么它应该是有效的。无论如何,“ DeviceCircuit对象”何时才有用。

如果您仍然不想覆盖 str ,则可以按照docs中概述的ModelChoiceField子类:

class DeviceCircuitField(forms.ModelChoiceField):

    def label_from_instance(self, device_circuit):
        circuit = device_circuit.circuit
        device = device_circuit.device
        return '{} - {} {}'.format(
            device.hostname, circuit.circuit_type, circuit.service_contact.provider
        )


class InterfaceDataForm(forms.ModelForm):

    class Meta:
        model = InterfaceData
        fields = ['device_circuit','interface_name','dashboard','wallboard']

    def __init__(self, *args, **kwargs):
        self.is_add = kwargs.pop("is_add", False)
        device_id = kwargs.pop("device_id")
        super(InterfaceDataForm, self).__init__(*args, **kwargs)
        self.fields['device_circuit'] = DeviceCircuitField(
            queryset=DeviceCircuit.objects.filter(device_id=device_id).select_related(
                'device', 'circuit', 'circuit__circuit_type', 'circuit__service_contact__provider'
            ),
            label='Device / Circuit'
        )