Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
85 views
in Technique[技术] by (71.8m points)

python - Django Select2MultipleWidget leads to form continuously trying to load

I'm trying to incorporate Select2 into my django form -- specifically ModelSelect2MultipleWidget -- so that the user can associate multiple event objects to another model (like CheckboxSelectMultiple). The associated models are:

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')

My forms.py file is:

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
            }

my view.py is:

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, })

lastly, my .html file is:

{% 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 %}

If I switch the pm_f4_events widget to a CheckboxSelectMultiple or a ModelSelect2Widget, the code works.

However, when I try to use a ModelSelect2MultipleWidget, the form continually tries to load but cannot and eventually just times out.

There are ~5000 items within the F4Events model, so that may have something to do with it. Any help to point me in the right direction would be greatly appreciated!

question from:https://stackoverflow.com/questions/65942769/django-select2multiplewidget-leads-to-form-continuously-trying-to-load

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can empty the pm_f4_events field's choices in the __init__ method:

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

Has been tested on my server, works well.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...