Select2 with Django 不接受选择

Select2 with Django not accepting selections

几天来我一直在研究这个问题,我只是被难住了。尝试在不使用 django-select2 应用程序的情况下集成 Select2.js。 我的模型:

from django.contrib.auth import get_user_model
from django.db import models
import datetime as dt
from WHST.settings import PROCESS_LEVELS
class CEID(models.Model):
process = models.CharField(max_length=4,
                           choices=PROCESS_LEVELS)
ceid = models.CharField(max_length=6)
representative = models.ManyToManyField(get_user_model(), blank=True)
functional_area = models.CharField(max_length=200)
score = models.IntegerField(null=True, blank=True)
ceid_is_production = models.BooleanField(default=True)
ceid_is_front_end = models.BooleanField(default=True)
ceid_is_hidden = models.BooleanField(default=False)
ceid_pdl = models.ManyToManyField('PDL', blank=True)
user_edited = models.BooleanField(default=False)

def __str__(self):
    return str(self.process) + ' ' + str(self.ceid) if self.ceid else ''

def __unicode__(self):
    return str(self.process) + ' ' + str(self.ceid) if self.ceid else ''

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

def calculate_ceid_score(self):
    entities = Entity.objects.filter(
        ceid__id=self.id).filter(production=True)
    score = 0

    for entity in entities:
        score += entity.score if entity.score else 0
    self.score = score / len(entities) if len(entities) > 0 else 0
    self.save()
    return

我的看法:

from datetime import datetime, timedelta
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.db.models import Sum, Q
from django.http import JsonResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django.views import View
from django.views.generic import ListView, TemplateView, FormView, UpdateView
from django_filters.views import FilterView
from django.contrib.auth import get_user_model
from dal import autocomplete

from pages.filter import CeidFilter, PmRunInformationFilter, HomePageFilter
from pages.forms import PDLAddForm, PagesAdminSetCeidUserAssociationForm, AreaAutofillSearchForm
from tools.models import CEID, Entity, WaferHandlingType, PmRunInformation, ToolPm
class PagesAdminSetCeidUserAssociation(LoginRequiredMixin, View, UserPassesTestMixin):
template_name = 'pages/pages_admin_set_ceid_user_association.html'
login_url = '/login/'

def test_func(self):
    return self.request.user.is_superuser

def get(self, request):

    form = PagesAdminSetCeidUserAssociationForm()

    if request.is_ajax():
        if request.GET.get('dat_type') == 'representatives':

            representatives = get_user_model().objects.filter(
                username__icontains=request.GET.get('term')
            )

            representative_response_content = list(
                representatives.values())

            return JsonResponse(representative_response_content, safe=False)
        elif request.GET.get('dat_type') == 'ceids':

            ceids = CEID.objects.filter(
                ceid__icontains=request.GET.get('term')
            )

            ceid_response_content = list(ceids.values())

            return JsonResponse(ceid_response_content, safe=False)


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

def post(self, request):

    form = PagesAdminSetCeidUserAssociationForm(request.POST or None)

    if form.is_valid():
        print(form)
        pass
        # form.save()
        return HttpResponseRedirect(reverse('pages_home_page'))
    return render(request, self.template_name, {'form': form})

我的表格:

from django import forms
from tools.models import PDL, CEID
from django.contrib.auth import get_user_model
from django.conf import settings
class PagesAdminSetCeidUserAssociationForm(forms.ModelForm):

representative = forms.MultipleChoiceField(label='WHST Representative')
ceid = forms.MultipleChoiceField(label='CEID')

class Meta:
    model = CEID
    fields = ['representative', 'ceid']

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

        # self.fields['representative'].queryset = get_user_model().objects.none()
        # self.fields['ceid'].queryset = CEID.objects.none()
        for field in self.fields:
            self.fields[field].widget.attrs = {'class': 'form-control'}

        if 'ceid' in self.data:
            ceid = self.data.get('ceid')
            self.fields['ceid'].queryset = CEID.objects.filter(ceid__in=ceid).order_by()
        if 'representative' in self.data:
            rep = self.data.get('representative')
            self.fields['representative'].queryset = get_user_model().objects.filter(username__in=rep)

最后,我的模板:

{% extends 'base.html' %} {% load crispy_forms_tags %} 
{% block title %}User CEID Association{% endblock %}
{% block content %}

<form novalidate method="post" action="{% url 'pages_admin_set_ceid_user_association' %}" >
  {% csrf_token %} {{ form|crispy }}
  <input type="submit" class="btn btn-success" value="Update" /><a
    href="{% url 'pages_home_page' %}"
    ><button type="button" class="btn btn-primary">Go Back</button></a
  >
</form>

<script>
    $('#id_representative').select2({
        ajax: {
            url: '{% url 'pages_admin_set_ceid_user_association' %}',
            dataType: 'json',
            data: function(params) {
                return {
                    q: params.term,
                    term: params.term,
                    _type: params._type,
                    dat_type: 'representatives'
                }
            },
            processResults: function(data) {
                return {
                    results: $.map(data, function(item) {
                        return {id: item.id, text: item.username + ' (' + item.first_name + ' ' + item.last_name + ')'};
                    })
                };
            }
        },
        minimumInputLength: 3
    });

    $('#id_ceid').select2({
        ajax: {
            url: '{% url 'pages_admin_set_ceid_user_association' %}',
            dataType: 'json',
            data: function(params) {
                return {
                    q: params.term,
                    term: params.term,
                    _type: params._type,
                    dat_type: 'ceids'
                }
            },
            processResults: function(data) {
                return {
                    results: $.map(data, function(item) {
                        console.log(item)
                        return {id: item.id, text: item.process + ' ' + item.ceid};
                    })
                };
            }
        },
        minimumInputLength: 3
    });
    
</script>

{% endblock content %}

当我尝试提交时,出现以下错误:

枚举是:

PROCESS_LEVELS = [('1270', '1270'), ('1272', '1272'), ('1274', '1274'), ('1222', '1222')]

我已经尝试为 forms.MultipleChoiceField 设置选项,但这并没有解决问题。我试过将字段切换为 CharField 和 ChoiceField,但这也没有解决问题。我也尝试过在表单中​​删除和添加 novalidate,但这没有任何作用。任何帮助将不胜感激!

找到解决问题的方法: 在我的表单中,我创建了一个自定义多项选择字段:

class CustomMultipleChoiceField(forms.MultipleChoiceField):
"""This field is a MultipleChoiceField designed to override the validation method of a default MultipleChoiceField

"""

def validate(self, value):
    return value

这绕过了常规的表单验证程序。然后我将该自定义字段设置为我表单中的字段,并将其从 ModelForm 转换为常规表单:

class PagesAdminSetCeidUserAssociationForm(forms.Form):

representative = CustomMultipleChoiceField(label='WHST Representative')
ceid = CustomMultipleChoiceField(label='CEID')

class Meta:
    model = CEID
    fields = ['representative', 'ceid']

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

        # self.fields['representative'].queryset = get_user_model().objects.none()
        # self.fields['ceid'].queryset = CEID.objects.none()
        for field in self.fields:
            self.fields[field].widget.attrs = {'class': 'form-control'}

        if 'ceid' in self.data:
            ceid = self.data.get('ceid')
            self.fields['ceid'].queryset = CEID.objects.filter(
                ceid__in=ceid).order_by()
        if 'representative' in self.data:
            rep = self.data.get('representative')
            self.fields['representative'].queryset = get_user_model(
            ).objects.filter(username__in=rep)

之后,编写我的 post 请求以按每个输入的 ID 进行过滤是一件简单的事情:

class PagesAdminSetCeidUserAssociation(LoginRequiredMixin, View, UserPassesTestMixin):
template_name = 'pages/pages_admin_set_ceid_user_association.html'
login_url = '/login/'

def test_func(self):
    return self.request.user.is_superuser

def get(self, request):

    form = PagesAdminSetCeidUserAssociationForm()

    if request.is_ajax():
        if request.GET.get('dat_type') == 'representatives':

            representatives = get_user_model().objects.filter(
                username__icontains=request.GET.get('term')
            )

            representative_response_content = list(
                representatives.values())

            return JsonResponse(representative_response_content, safe=False)
        elif request.GET.get('dat_type') == 'ceids':

            ceids = CEID.objects.filter(
                ceid__icontains=request.GET.get('term')
            )

            ceid_response_content = list(ceids.values())

            return JsonResponse(ceid_response_content, safe=False)

        elif request.GET.get('dat_type') == 'user-ceid-association-container':
            
            representative = get_user_model().objects.get(id=request.GET.get('term[]'))
            ceids = list(CEID.objects.filter(representative=representative))
            print(ceids)

            ceid_name_list = []

            for ceid in ceids:
                ceid_name_list.append(ceid.__str__())

            print(ceid_name_list)
            response = {
                'representative': representative.username + ' ( ' + representative.first_name + ' ' + representative.last_name + ' )',
                'ceids': ceid_name_list,
            }
            return JsonResponse(response, safe=False)



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

def post(self, request):

    form = PagesAdminSetCeidUserAssociationForm(request.POST or None)
    

    if form.is_valid():
        
        for ceid in CEID.objects.filter(id__in=form.cleaned_data['ceid']):
            ceid.representative.set(get_user_model().objects.filter(id__in=form.cleaned_data['representative']))


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

还有我的 html 代码:

{% extends 'base.html' %} {% load crispy_forms_tags %} {% block title %}User
CEID Association{% endblock %} {% block content %}

<h3>Please note, submitting associate will reset assignment of CEIDs</h3>
<form method="post" action="{% url 'pages_admin_set_ceid_user_association' %}">
  {% csrf_token %} {{ form|crispy }}
  <input type="submit" class="btn btn-success" value="Update" /><a
    href="{% url 'pages_home_page' %}"
    ><button type="button" class="btn btn-primary">Go Back</button></a
  >
</form>
<div
  id="user-ceid-association-container"
  class="container"
  style="display: none"
>
  <div class="card mb-4 shadow-sm">
    <div class="card-body">
      <h6 class="card-text" id="User"></h6>
      <ul class="card-text" id="ceids"></ul>
    </div>
  </div>
</div>

<script>
  $('#id_representative').select2({
      ajax: {
          url: '{% url 'pages_admin_set_ceid_user_association' %}',
          dataType: 'json',
          data: function(params) {
              return {
                  q: params.term,
                  term: params.term,
                  _type: params._type,
                  dat_type: 'representatives'
              }
          },
          processResults: function(data) {
              return {
                  results: $.map(data, function(item) {
                      return {id: item.id, text: item.username + ' (' + item.first_name + ' ' + item.last_name + ')'};
                  })
              };
          }
      },
      minimumInputLength: 3
  });

  $('#id_representative').change(function () {
      let representative_value = $(this).val();
      $.ajax({
          url: '{% url 'pages_admin_set_ceid_user_association' %}',
          data: {
              'term': representative_value,
              'dat_type': 'user-ceid-association-container',
          },
          success: function(result) {
              $('#user-ceid-association-container').css('display', 'block');
              $('#User').text(result.representative);
              $('#ceids').empty();
              if (result.ceids.length > 0) {
                  for(let i=0; i < result.ceids.length; i++) {
                  $('#ceids').append('<li class="card-text">' + result.ceids[i] + '</li>');
              }}
              else {
                  $('#ceids').append('<li class="card-text">This user has no CEIDs associated to them</li>');
              }

              return
          },
      });
  });

  $('#id_ceid').select2({
      ajax: {
          url: '{% url 'pages_admin_set_ceid_user_association' %}',
          dataType: 'json',
          data: function(params) {
              return {
                  q: params.term,
                  term: params.term,
                  _type: params._type,
                  dat_type: 'ceids'
              }
          },
          processResults: function(data) {
              return {
                  results: $.map(data, function(item) {
                      console.log(item)
                      return {id: item.id, text: item.process + ' ' + item.ceid};
                  })
              };
          }
      },
      minimumInputLength: 3
  });
</script>

{% endblock content %}

这似乎已经成功了!