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

Django Select2MultipleWidget leads to form continuously trying to load

我正在尝试将 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, F4Events, ToolPm, 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, request, username, pk, 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, self.template_name, {'form': form, 'pm': pm, })

最后,我的 .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项,所以这可能与它有关。如果能帮我指明正确的方向,我们将不胜感激!

您可以在__init__方法中清空pm_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': 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

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