Django несколько одинаковых зависимых выпадающих списков в одной форме

#django #drop-down-menu

Вопрос:

У меня проблема со следующим; У меня есть зависимое выпадающее меню в форме модели Django. Теперь я хочу использовать его несколько раз в одной и той же форме, но я не могу заставить его работать, если я загружу более одного, то смогу ввести/использовать только один. И у меня есть 2-я проблема, если это работает, как мне получить различные значения в списке/массиве, чтобы я мог хранить их в БД? Конечная цель состоит в том, чтобы выбрать, сколько пучков требуется, и на этой основе иметь возможность вводить желаемые часы, виды ионов, энергию и поток на пучок.

Мой код выглядит следующим образом:

models.py

 from django.db import models
from smart_selects.db_fields import ChainedForeignKey


class IonSpecies(models.Model):
#   ionspecie = models.CharField(max_length=10)
    Name = models.CharField(max_length=10)


    def __str__(self):
#       return self.ionspecie
        return self.Name

class Energys(models.Model):
    Ion_Species = models.ForeignKey(IonSpecies, on_delete=models.CASCADE)
    Name = models.CharField(max_length=50)

    def __str__(self):
#       return self.energy
        return self.Name

        
# Create your models here.
class CreateBeamRequestModel(models.Model):

    #status choices
    SELECT      = 'Select'
    REQUEST     = 'Request'
    TENTATIVE   = 'Tentavive'
    ACCEPTED    = 'Accepted'
    CONFIRMED   = 'Confirmed'
    CANCELLED   = 'Cancelled'
    COMPLETED   = 'Completed'
    QUEUED      = 'Queued'

    STATUS_CHOICES = [
        (SELECT, ('Select an option')),
        (REQUEST, ('Request')),
        (TENTATIVE, ('Tentative')),
        (ACCEPTED,  ('Accepted')),
        (CONFIRMED, ('Confirmed')),
        (CANCELLED, ('Cancelled')),
        (COMPLETED, ('Completed')),
        (QUEUED, ('Queued')),
    ]

    #different beam choices (1 to 4)
    DIFBEAMS_CHOICES = [tuple([x,x]) for x in range(1,5)]

    #shift choices (1 to 16 is max a week)
    SHIFTS_CHOICES = [tuple([x,x]) for x in range(1,17)]

    #fields of the model
    Project_Code = models.CharField(unique=True, max_length=20, blank = True)
    Pac_Rate = models.CharField(max_length=10, blank = True)
    Partrec_Contact_Name = models.CharField(max_length=50, blank = True)
    Partrec_Contact_Email = models.EmailField(blank = True)
    Previous_Experiment = models.CharField(max_length=200, blank = True)
    Status = models.CharField(max_length=25, choices=STATUS_CHOICES, default='SELECT')
    Project_Title = models.CharField(max_length=100, blank = True)
    Spokesperson_Name = models.CharField(max_length=50, blank = True)
    Spokesperson_Adress = models.CharField(max_length=50, blank = True)
    Spokesperson_Phonenumber = models.CharField(max_length=20, blank = True)
    Spokesperson_Email = models.EmailField(blank = True)
    Collaborator_Name = models.TextField(blank = True)
    Collaborator_Nationality = models.TextField(blank = True)
    Collaborator_Home_Institute = models.TextField(blank = True)
    Different_Beams = models.IntegerField(choices=DIFBEAMS_CHOICES, default='1')
#   Shifts = models.IntegerField(choices=SHIFTS_CHOICES, default='1')
    Hours = models.IntegerField(default='1')
    Ion_Species = models.ForeignKey(IonSpecies, on_delete=models.CASCADE)
    Energy = ChainedForeignKey(Energys, chained_field="Ion_Species", chained_model_field="Ion_Species", show_all=False, auto_choose=True)
    Flux = models.CharField(max_length=50, blank = True, null = True)
    Start_Date = models.DateTimeField(blank = True, null=True)
    End_Date = models.DateTimeField(blank = True, null=True)
    Requiered_Equipment = models.TextField(blank = True)
    Special_Requirements = models.TextField(blank = True)
    Special_Safety_Procedures = models.TextField(blank = True)
    Lab_Support_Requirements = models.TextField(blank = True)
    Funded = models.TextField(blank = True)
    Summary = models.TextField(blank = True)

    def __str__(self):
        return self.Project_Code

    def get_absolute_url(self):
        return f"/beamrequest/{self.Project_Code}"

    def get_edit_url(self):
        return f"{{self.get_absolute_url}}/update/"

    def get_delete_url(self):
#       return f"/beamrequest/{self.Project_Code}/delete/"
        return f"{{self.get_absolute_url}}/delete/"
 

forms.py

 {% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block extrahead %}
    
{% endblock %}

{% block title %}{{ title }}{% endblock %}

{% block content %}

    <form method="post" novalidate>
        {% csrf_token %}
        <div class="Error_Messages">
            {% for error in form.non_field_errors %}
                {{ error }}
            {% endfor %}
        </div>
        <br><br>
        <b>Internal contact information</b>
        <hr class="divider"></hr>

        <div class="row">
            <div class="col-6">
             {{ form.Project_Code|as_crispy_field }}
            </div>
            <div class="col-6">
             {{ form.Partrec_Contact_Name|as_crispy_field }}
         </div>
        </div>

        <div class="row">
            <div class="col-6">
             {{ form.Pac_Rate|as_crispy_field }}
            </div>
            <div class="col-6">
             {{ form.Partrec_Contact_Email|as_crispy_field }}
         </div>
        </div>

        <div class="row">
            <div class="col-6">
             {{ form.Previous_Experiment|as_crispy_field }}
            </div>
            <div class="col-6">
             
         </div>
        </div>

        <div class="row">
            <div class="col-6">
             {{ form.Status|as_crispy_field }}
            </div>
            <div class="col-6">
             
         </div>
        </div>
        <br><br>
        <b>External contact information</b>
        <hr class="divider"></hr>

        <div class="row justify-content-center">
         <div class="col-6">
            {{ form.Project_Title|as_crispy_field }}
         </div>
        </div>

        <div class="row">
         <div class="col-6">
            {{ form.Spokesperson_Name|as_crispy_field }}
         </div>
         <div class="col-6">
            {{ form.Spokesperson_Adress|as_crispy_field }}
         </div>
        </div>

        <div class="row">
         <div class="col-6">
            {{ form.Spokesperson_Phonenumber|as_crispy_field }}
         </div>
         <div class="col-6">
            {{ form.Spokesperson_Email|as_crispy_field }}
         </div>
        </div>
        <div class="row">
         <div class="col-4">
            {{ form.Collaborator_Name|as_crispy_field }}
         </div>
         <div class="col-4">
            {{ form.Collaborator_Nationality|as_crispy_field }}
         </div>
         <div class="col-4">
            {{ form.Collaborator_Home_Institute|as_crispy_field }}
         </div>
        </div>
         <br><br>
         <b>Beam information</b>
         <hr class="divider"></hr>

        <div class="row">
            <div class="col-6">
             {{ form.Start_Date|as_crispy_field }}
            </div>
            <div class="col-6">
             {{ form.End_Date|as_crispy_field }}
            </div>
        </div>
        <div class="justify-content-center">
            <div class="col-6">
            {{ form.Different_Beams|as_crispy_field }}
            </div>
        </div>
        <div class="row justify-content-center">
            <div id="hidden1">
                <div class="col-6">
                {{ form.Hours|as_crispy_field }}
                {{ form.Ion_Species|as_crispy_field }}
                {{ form.Energy|as_crispy_field }}
                {{ form.Flux|as_crispy_field }}
                </div>
            </div>
            <div id="hidden2">
                <div class="col-6">
                {{ form.Hours|as_crispy_field }}
                {{ form.Ion_Species|as_crispy_field }}
                {{ form.Energy|as_crispy_field }}
                {{ form.Flux|as_crispy_field }}
                </div>
            </div>
            <div id="hidden3">
                <div class="col-6">
                {{ form.Hours|as_crispy_field }}
                {{ form.Ion_Species|as_crispy_field }}
                {{ form.Energy|as_crispy_field }}
                {{ form.Flux|as_crispy_field }}
                </div>
            </div>
            <div id="hidden4">
                <div class="col-6">
                {{ form.Hours|as_crispy_field }}
                {{ form.Ion_Species|as_crispy_field }}
                {{ form.Energy|as_crispy_field }}
                {{ form.Flux|as_crispy_field }}
                </div>
            </div>
        </div>
        <div class="row justify-content-center">
          {{ form.Requiered_Equipment|as_crispy_field }}
          {{ form.Special_Requirements|as_crispy_field }}
          {{ form.Special_Safety_Procedures|as_crispy_field }}
          {{ form.Lab_Support_Requirements|as_crispy_field }}
          {{ form.Funded|as_crispy_field }}
          {{ form.Summary|as_crispy_field }}
        </div>
        <div class="row justify-content-center">
            <button type="submit" class="btn btn-success">Save New Request</button>
        </div>
    </form>
<br>

<script type="text/javascript">
    $('#hidden2').css({
       'display': 'none'
    });
    $('#hidden3').css({
       'display': 'none'
    });
    $('#hidden4').css({
       'display': 'none'
    });
    $('#id_Different_Beams').on('change', function() {
       if (this.value === '2') {
           $('#hidden1').show();
           $('#hidden2').show();
           $('#hidden3').hide();
           $('#hidden4').hide();
       }
       else if ($(this).val() == '3') {
           $('#hidden1').show();
           $('#hidden2').show();
           $('#hidden3').show();
           $('#hidden4').hide();
       }
       else if ($(this).val() == '4') {
           $('#hidden1').show();
           $('#hidden2').show();
           $('#hidden3').show();
           $('#hidden4').show();
       }
       else {
           $('#hidden1').show();
           $('#hidden2').hide();
           $('#hidden3').hide();
           $('#hidden4').hide();
       }
    });
</script>
{% endblock %}
 

Views.py

 from django.http import Http404, HttpResponse

from django.shortcuts import render, get_object_or_404, redirect


from .models import CreateBeamRequestModel, IonSpecies, Energys
from .forms import CreateBeamRequestForm

# Create your views here.

#home page
def beam_request_home_page(request):
    page_title = 'Beam Request'
    template_name = 'request/home.html'
    context = {"title": page_title}
   
    return render(request, template_name, context)

#@login_required
#Create view
@staff_member_required
def beam_request_create_page(request):
    page_title = 'Create new Request'
    template_name = 'request/create.html'

    form = CreateBeamRequestForm(request.POST or None)
    if form.is_valid():
        print(form.cleaned_data)
        form.save()
        form = CreateBeamRequestForm()
    context = {"title": page_title, "form": form}
           
    return render(request, template_name, context)
 

Комментарии:

1. Я не уверен, что правильно понимаю ваш вопрос. Вам нужно несколько экземпляров Different_Beams поля? (Примечание сбоку: у вас есть несколько очень нестандартных соглашений об именах …)

2. Здравствуйте, то, что я хотел бы иметь, — это выбрать 1,2,3 или 4 разных луча. а затем для каждого луча выберите вид ионов и энергию. Поэтому, если у меня есть 2 выбранных луча, я хотел бы выбрать, например, ионный гелий с энергией 30 и ионный азот с энергией 50. И я новичок в программировании и просто использую имена, которые я могу легко понять. Я рассмотрю стандартные соглашения об именах.