Django Materialize Multiple Dropdowns

Это может быть довольно обширным - поэтому любая помощь будет высоко оценена.

Похожие:

  1. Материализация CSS (с django) выпадающая форма не работает
  2. Как реализовать трехсторонний зависимый/цепной выпадающий список с помощью Django?

Я работаю над проектом, включающим зависимые выпадающие меню, следуя этому учебнику по django.

Единственное отличие в том, что я работаю с materialize css/js. Проблема в том, что выпадающие окна не заполняются, а заполняются только после того, как я размещу форму - Pre-"post", и Post-"post". Когда я не инициирую materialize - форма работает . Materialize css/js все еще необходим, так как он поддерживает согласованность между другими страницами.

Даже после того, как я инициализировал 'select' после загрузки Materialize js: (Materialize docs here)

HTMLs

Base.html

<head>
  {% load static %}

  <!-- Prism CSS -->
  <link href="{% static "tinymce/css/prism.css" %}" rel="stylesheet">
  <!-- Compiled and minified JavaScript -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
  <script>
    {% comment %} $(document).ready(function(){
      $('select').formSelect();
    }); {% endcomment %}
    document.addEventListener('DOMContentLoaded', function() {
      var elems = document.querySelectorAll('select');
      var instances = M.FormSelect.init(elems);
    });
  </script>
  
  <!-- Compiled and minified CSS -->
  <link rel="stylesheet" href="{% static "main/css/materialize.css" %}">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
  <nav>
    <div class="nav-wrapper"
      
      <ul id="nav-mobile" class="right hide-on-med-and-down">
        {% include 'main/includes/navbar.html' %}
      </ul>
    </div>
  </nav>

  {% include 'main/includes/messages.html' %}

  <div class="container">
    {% block content %}
    {% endblock %}
  </div>
</body>

<script src="{% static "tinymce/js/prism.js" %}"></script>
<script>M.AutoInit();</script>

product_form.html


{% block content %}

<h2>Product Form</h2>

<form method="POST" id="productForm" data-plants-url="{% url 'ajax_load_plants' %}" data-business-url="{% url 'ajax_load_businesses' %}" novalidate>
    {% csrf_token %}
    <table>
        {{ form.as_table }}
    </table>
    
    <button class="btn-small waves-effect waves-light" type="submit" name="action">Submit
        <i class="material-icons right">send</i>
    </button>
    <a class="waves-effect waves-light btn-small" href="{% url 'product_changelist' %}">Cancel</a>
</form>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<script>
    $("#id_country").change(function () {
        var url = $("#productForm").attr("data-business-url");
        var countryId = $(this).val();

        $.ajax({
        url: url,
        data: {
            'country': countryId
        },
        success: function (data) {
            $("#id_business_unit").html(data);
            

            $("#id_business_unit").change(function () {
                var url2 = $("#productForm").attr("data-plants-url");
                var business_unitId = $(this).val();
        
                $.ajax({
                url: url2,
                data: {
                    'business_unit': business_unitId 
                },
                success: function (data) {
                    $("#id_plant").html(data);
                    
                    }
                });
            });
        }
    });
    });

    
</script>

{% endblock %}

drop_down_options-businessunit.html

{% for business in business_units %}
<option class=browser-default value="{{ business.pk }}">{{ business.name }}</option>
{% endfor %}

drop_down_options-plant.html

<option value="" disabled selected>---------</option>
{% for plant in plants %}
<option class=browser-default value="{{ plant.pk }}">{{ plant.name }}</option>
{% endfor %}

Python

models.py

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

# Create your models here.
class Country(models.Model):
    name = models.CharField(max_length = 50, default="")
    
    def __str__(self):
        return self.name

class Business_Unit(models.Model):
    country = models.ForeignKey(Country, on_delete=models.CASCADE)
    name =  models.CharField(max_length = 50)
    
    def __str__(self):
        return self.name

class Plant(models.Model):
    country = models.ForeignKey(Country, on_delete=models.CASCADE)
    business_unit = models.ForeignKey(Business_Unit, on_delete=models.CASCADE)
    name = models.CharField(max_length = 50)
    
    def __str__(self):
        return self.name

class Product(models.Model):
    country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True)
    business_unit = models.ForeignKey(Business_Unit, on_delete=models.SET_NULL, null=True)
    plant = models.ForeignKey(Plant, on_delete=models.SET_NULL, null=True)
    name = models.CharField(max_length = 200)
    
    class Meta:
        unique_together = [['country','business_unit','plant']]

    def __str__(self):
        return self.name

views.py

from django.shortcuts import get_object_or_404, render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm
from django.views.generic import ListView, CreateView, UpdateView
from django.urls import reverse_lazy
from django.contrib import messages

from .models import Country, Business_Unit, Plant, Product
from .forms import NewUserForm, productForm

class ProductListView(ListView):
    model = Product
    context_object_name = 'product'

class ProductSearchView(CreateView):
    model = Product
    form_class = productForm
    success_url = reverse_lazy('product_changelist')

class ProductCreateView(CreateView):
    model = Product
    form_class = productForm
    #fields = ('name', 'country', 'business_unit', 'plant')
    success_url = reverse_lazy('product_changelist')

class ProductUpdateView(UpdateView):
    model = Product
    form_class = productForm
    #fields = ('name', 'country', 'business_unit', 'plant')
    success_url = reverse_lazy('product_changelist')

def load_businesses(request):
    country_id = request.GET.get('country')
    business_units = Business_Unit.objects.filter(country_id=country_id).order_by('name')
    return render(request, 'main/drop_down_options-businessunit.html', {'business_units': business_units})

def load_plants(request):
    business_unit_id = request.GET.get('business_unit')
    plants = Plant.objects.filter(business_unit_id=business_unit_id).order_by('name')
    return render(request, 'main/drop_down_options-plant.html', {'plants': plants})

forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import Business_Unit, Product, Plant

class productForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ('name', 'country', 'business_unit', 'plant')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['business_unit'].queryset = Business_Unit.objects.none()
        self.fields['plant'].queryset = Plant.objects.none()

        if 'country' in self.data:
            try:
                country_id = int(self.data.get('country'))
                self.fields['business_unit'].queryset = Business_Unit.objects.filter(country_id=country_id).order_by('name')
            except (ValueError, TypeError):
                pass  # invalid input from the client; ignore and fallback to empty plant queryset
        elif self.instance.pk:
            self.fields['business_unit'].queryset = self.instance.country.business_unit_set.order_by('name')

        if 'business_unit' in self.data:
            try:
                business_unit = int(self.data.get('business_unit'))
                self.fields['plant'].queryset = Plant.objects.filter(business_unit=business_unit).order_by('name')
            except (ValueError, TypeError):
                pass  # invalid input from the client; ignore and fallback to empty plant queryset
        elif self.instance.pk:
            self.fields['plant'].queryset = self.instance.country.plant_set.order_by('name')

urls.py

from django.urls import path,include
from django.contrib import admin
from . import views
from .views import profile

urlpatterns = [
    path('',views.login_request, name="login"),
    path('main/', views.ProductListView.as_view(), name='product_changelist'),
    path('add/', views.ProductCreateView.as_view(), name='product_add'),
    path('search/', views.ProductSearchView.as_view(), name='product_search'),
    path('<int:pk>/', views.ProductUpdateView.as_view(), name='product_change'),
    
    path('ajax/load-businesses/', views.load_businesses, name='ajax_load_businesses'),
    path('ajax/load-plants/', views.load_plants, name='ajax_load_plants'),
]

Однако любая помощь будет принята с благодарностью. И я надеюсь, что я могу уточнить все, что запутано / упущено. Спасибо!

Вернуться на верх