'How to use a ManyToMany field in django with a through model, displaying it and saving it?

I am doing a basic system in Django for a Spa that requires me to have an inventory, massages that use different quantities of product in the inventory, and then a service which will be a combination of multiple massages. So the user of the spa, which is the staff, will be able to create a service, select which massages make that service, and that will instantly trigger the subtraction of that product from the inventory. I used a many to many relation to relate the massages and the items, with a through model to save the amount used as well. My question is, what would be the best way to display this in a form so the staff can add new massages in a way where they can choose many items and their respective quantity that the massage will use? And how can i save all of this afterwards into the DB? I'm using PostgreSQL. This is how my models look right now:

class Producto(models.Model):
    
    nombre = models.CharField(max_length=200, blank=False)
    línea = models.CharField(max_length=200, blank=False)

    proveedor = models.CharField(max_length=200, blank=False)
    costo_mxn =  models.DecimalField(blank=False, max_digits=10, decimal_places=2)

    unidad_de_medición_choices = [
        ("g", "g"),
        ("mL", "mL"),
        ("oz", "oz"),
    ]
    
    unidad_de_medición = models.CharField(max_length=20, choices=unidad_de_medición_choices,null=True, blank=True)
    cantidad_actual = models.DecimalField(blank=False, max_digits=10, decimal_places=2)
    cantidad_inicial = models.DecimalField(blank=False, max_digits=10, decimal_places=2)
    cantidad_alerta = models.DecimalField(blank=False, max_digits=10, decimal_places=2)

    fecha_de_registro = models.DateField(blank=True,null=True,default= datetime.today)
    def __str__(self):
            return self.nombre
class Masaje(models.Model):
    nombre = models.CharField(max_length=200, blank=False)
    productos = models.ManyToManyField(Producto, through='CantidadProducto',blank=True)
    costo = models.DecimalField(blank=False, max_digits=10, decimal_places=2)
    duracion = models.DurationField()
    descripcion = models.TextField(
        max_length=500, blank=True, null=True
    )

class CantidadProducto(models.Model):
    masaje = models.ForeignKey(Masaje,on_delete=models.CASCADE)
    producto = models.ForeignKey(Producto,on_delete=models.CASCADE)
    cantidad_usada = models.DecimalField(blank=False, max_digits=10, decimal_places=2)

Now I've been using simple forms to display other parts of the system that I've done that aren't as complex, for example the masseuse, like this:

class MasajistaForm(ModelForm):
    class Meta:
        model = Masajista
        fields = (
            'nombre',
            'telefono_celular',
            'fecha_de_nacimiento',
        )
        widgets = {
            'nombre': forms.TextInput(attrs={'class':''}),
            'telefono_celular': forms.TextInput(attrs={'class':''}),
            'fecha_de_nacimiento': forms.SelectDateWidget(years=range(1900, 2023),months = MONTHS,attrs={'class':''},empty_label=("Año", "Mes", "Dia"))
  
        }

With a result like this

Now, i know it doesn't look great but that's not the problem right now, I would like it so the staff can see a form like that where you could maybe hit a plus button or something like that where a new select box would appear with a selection of the already registered items, and an input box that could be filled by hand and then saved. What would be the way to go here?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source