Django Select2MultipleWidget 导致表单不断尝试加载

问题描述

我正在尝试将 Select2 合并到我的 django 表单中——特别是 ModelSelect2MultipleWidget——以便用户可以将多个事件对象关联到另一个模型(如 CheckBoxSelectMultiple)。相关模型为:

from django.contrib.auth import get_user_model
from django.db import models

class F4Events(models.Model):
    name = models.CharField(max_length=300)
    handling_type = models.ManyToManyField(WaferHandlingType)

    def __str__(self):
        return self.name

class ToolPm(models.Model):
    ceid = models.ForeignKey(CEID,on_delete=models.CASCADE)
    name = models.CharField(max_length=250)
    wafer_handling = models.BooleanField(default=True)
    wafer_based = models.BooleanField(default=False)
    frequency = models.FloatField(blank=True,null=True)
    handling_type = models.ManyToManyField(WaferHandlingType,blank=True)
    user_edited = models.BooleanField(default=False)
    pm_f4_events = models.ManyToManyField('F4Events',blank=True)

    def __str__(self):
        return str(self.name) if self.name else ''

    class Meta:
        ordering = ('ceid','name')

我的 forms.py 文件是:

from django import forms
from .models import Entity,ToolPm,CEID,PDL,F4Events,WaferHandlingType
from django_select2 import forms as s2forms

class F4EventWidget(s2forms.ModelSelect2MultipleWidget):
    search_fields = [
        'name__icontains',]

    attrs = {'data-placeholder': 'Please Choose F4 Events'}


class PMForm(forms.ModelForm):


    class Meta:
        model = ToolPm
        fields = ['wafer_handling','wafer_based','handling_type','pm_f4_events']
        widgets = {'handling_type': forms.CheckBoxSelectMultiple,'pm_f4_events': F4EventWidget
            }

我的 view.py 是:

from datetime import datetime,timedelta
from django.db.models import Sum
from django.http import JsonResponse,HttpResponseRedirect
from django.http.response import HttpResponse
from django.shortcuts import render,get_object_or_404,redirect
from django.views import View
from django.views.generic import ListView
from django_filters.views import FilterView
from pages.filter import CeidFilter,PmRundatefilter
from tools.forms import EntityForm,PMForm,CEIDForm,PDLAddForm
from tools.models import CEID,Entity,WaferHandlingType,PmRunDate
from django.urls import reverse

class UserCeidPMUpdate(View):
    template_name = 'tools/update_pm_attributes.html'

    def get(self,request,username,pk,pm_id):
        pm = ToolPm.objects.get(pk=pm_id)

        form = PMForm(request.GET or None,instance=pm)

        return render(request,self.template_name,{'form': form,'pm': pm,})

    def post(self,pm_id):
        pm = ToolPm.objects.get(pk=pm_id)
        pm.user_edited = True
        pm.save()

        form = PMForm(request.POST or None,instance=pm)

        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('pm_view',kwargs={'username': username,'pk': pm.ceid.id}))

        return render(request,})

最后,我的 .html 文件是:

{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="post">
    <p>Process: {{ pm.ceid.process }}</p>
    <p>CEID: {{ pm.ceid.ceid }}</p>
    <p>Name: {{ pm.name }}</p>
    <p>Frequency: {{ pm.frequency }}{% if pm.wafer_based %} wafers {% else %} days {% endif %}</p>
    <p>score: {{ pm.score }}</p>
    {% csrf_token %}
    {{ form }}

    <input type="submit" class="btn btn-success" value="Update PM"><a href="{% url 'pm_view' user.username pm.ceid.id %}"><button type="button" class="btn btn-primary">Go Back</button></a>
</form>

{% endblock content %}

如果我将 pm_f4_events 小部件切换为 CheckBoxSelectMultipleModelSelect2Widget代码将起作用。

但是,当我尝试使用 ModelSelect2MultipleWidget 时,表单会不断尝试加载但无法加载,最终只是超时。

F4Events 模型中有 ~5000 项,因此可能与此有关。任何为我指明正确方向的帮助将不胜感激!

解决方法

您可以在 pm_f4_events 方法中清空 __init__ 字段的选择

class PMForm(forms.ModelForm):
    class Meta:
        model = ToolPm
        fields = ['wafer_handling','wafer_based','handling_type','pm_f4_events']
        widgets = {
            'handling_type': forms.CheckboxSelectMultiple,'pm_f4_events': s2forms.ModelSelect2MultipleWidget(
                model=F4Events,search_fields=["name__icontains",],attrs = {'data-placeholder': 'Please Choose F4 Events'}
            )
         }


    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        choices_F4Events = []
        pm_f4_events_field = self.fields["pm_f4_events"]
        # selected values
        selected_F4Events = self.data.getlist("pm_f4_events") or self.initial.get("pm_f4_events")
        if selected_F4Events:
            # check of selected values not object
            if not isinstance(selected_F4Events[0],F4Events):
                selected_F4Events = pm_f4_events_field.queryset.filter(pk__in=selected_F4Events)
            choices_F4Events = [(item.pk,item.name) for item in selected_F4Events]
        # assign selected values or empty list
        pm_f4_events_field.choices = choices_F4Events

已在我的服务器上测试过,运行良好。