我无法从 django ModelForm 访问反向 ManyToMany 字段

问题描述

我有两个实体,它们之间存在多对多关系。 ProcessModel 具有 RouteModel 的 ManyToManyField 并创建了反向关系“流程”。我已经定义了两个 ModelForms,但我无法从路由表单访问反向多对多关系“进程”。包含路线表单的视图不显示流程字段。如何显示反向 ManyToMany 字段并使用表单保存信息。 这是我的代码

class ProcessModel(models.Model):

    name = models.CharField(verbose_name="nombre",max_length=50,blank=False,null=False)
    code = models.CharField(verbose_name="Código",blank=True,null=True,unique=True)    
    routes = models.ManyToManyField("RouteModel",verbose_name="lista de rutas",related_name="processes",blank=True)

class RouteModel(models.Model):
    
    name = models.CharField(verbose_name="Nombre",null=False)

    route_type_id = models.ForeignKey("RouteTypeModel",verbose_name="Tipo",on_delete=models.SET_NULL,related_name="routes")

    start_date = models.DateField(verbose_name="Fecha inicio")
    end_date = models.DateField(verbose_name="Fecha inicio")


from django_select2.forms import ModelSelect2Widget,ModelSelect2MultipleWidget
class ProcessForm(forms.ModelForm):
    class Meta:
        model = ProcessModel
        exclude = ('id',)

        widgets = {
            'name':forms.TextInput(attrs={'class': 'form-control'}),'code':forms.TextInput(attrs={'class': 'form-control'}),'routes': ModelSelect2MultipleWidget(model=RouteModel,queryset=RouteModel.objects.filter(),search_fields=['name__icontains'],attrs={'style': 'width: 100%;'}),} 


class RouteForm(forms.ModelForm):
    
    class Meta:
        model = RouteModel
        exclude = ("id",)
        widgets = {
            'name':forms.TextInput(attrs={'class': 'form-control'}),'route_type_id': forms.Select(attrs={'class': 'form-control'}),'start_date' :forms.DateInput(attrs={'class': 'form-control datepicker','autocomplete': 'off'}),'end_date' :forms.DateInput(attrs={'class': 'form-control datepicker','processes': ModelSelect2MultipleWidget(model=ProcessModel,queryset=ProcessModel.objects.filter(),}

解决方法

我刚刚找到了解决方案,我不得不添加进程字段并覆盖“init”和“save”函数。这里是RouteForm的定义

class RouteForm(forms.ModelForm):
    
    processes = forms.ModelMultipleChoiceField(
            queryset=ProcessModel.objects.all(),widget=ModelSelect2MultipleWidget(model=ProcessModel,queryset=ProcessModel.objects.filter(),search_fields=['name__icontains'],attrs={'style': 'width: 100%;'}),)
    class Meta:
        model = RouteModel
        exclude = ("id",)
        widgets = {
            'name':forms.TextInput(attrs={'class': 'form-control'}),'route_geom': LeafletWidget(),'route_type_id': forms.Select(attrs={'class': 'form-control'}),'start_date' :forms.DateInput(attrs={'class': 'form-control datepicker','autocomplete': 'off'}),'end_date' :forms.DateInput(attrs={'class': 'form-control datepicker',}

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

        # Here we fetch the currently related projects into the field,# so that they will display in the form.
        if self.instance.id:
            self.fields['processes'].initial = self.instance.processes.all(
            ).values_list('id',flat=True)

    def save(self,**kwargs):
        instance = super(RouteForm,self).save(*args,**kwargs)

        # Here we save the modified project selection back into the database
        instance.processes.set(self.cleaned_data['processes'])

        return instance