【问题标题】:I cannot access reverse ManyToMany field from django ModelForm我无法从 django ModelForm 访问反向多对多字段
【发布时间】:2021-08-13 08:34:59
【问题描述】:

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

class ProcessModel(models.Model):

    name = models.CharField(verbose_name="nombre", max_length=50, blank=False, null=False)
    code = models.CharField(verbose_name="Código", max_length=50, 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", max_length=50, blank=False, null=False)

    route_type_id = models.ForeignKey("RouteTypeModel", verbose_name="Tipo",
                                                 blank=True, null=True, 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', 'autocomplete': 'off'}),
            'processes': ModelSelect2MultipleWidget(model=ProcessModel, queryset=ProcessModel.objects.filter(),
                                            search_fields=['name__icontains'],
                                           attrs={'style': 'width: 100%;'}), 
            }

【问题讨论】:

  • 以上链接解释了 django 中的反向关系
  • 问题是我想让反向多对多“进程”字段在 RouteForm 中可用
  • 您在 Route 模型中没有 processes 字段,是吗?我认为在您的情况下是必需的
  • Processes 在 routes 模型中的 routes 属性的相关名称中。这应该会创建自动推动的流程

标签: python django django-forms django-orm django-select2


【解决方案1】:

我刚刚找到了解决方案,我必须添加进程字段并覆盖“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', 'autocomplete': 'off'}), }

    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, *args, **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

【讨论】:

    猜你喜欢
    • 2011-10-24
    • 2011-01-14
    • 1970-01-01
    • 2023-03-31
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2021-01-06
    相关资源
    最近更新 更多