具有多个ManyToManyField表单的Django

时间:2017-11-13 02:32:54

标签: python django django-forms django-templates

这是我第一个向自己(和我的公司)证明我们应该采用Django的Django应用程序,但到目前为止它已被证明是棘手的。

我正在尝试创建一个应用程序,该应用程序显示公司的所有员工,以及每个员工在类别中组织的所有技能。 这是我的模特:

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=64)

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Skill(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    name = models.CharField(max_length=64)

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Employee(models.Model):
    login = models.CharField(max_length=16)
    fullname = models.CharField(max_length=64)
    skills = models.ManyToManyField(Skill, through='EmployeeSkill')

    def __str__(self):              # __unicode__ on Python 2
        return self.fullname

class EmployeeSkill(models.Model):
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
    skill    = models.ForeignKey(Skill,    on_delete=models.CASCADE)
    LEVELS = (
        ('0', 'None'),
        ('1', 'Very Basic Knowledge (hours)'),
        ('2', 'Basic Knowledge (days)'),
        ('3', 'Good Understanding Knowledge (weeks)'),
        ('4', 'Excellent Knowledge (months)'),
        ('5', 'Expert Knowledge (years)'),
    )
    level = models.CharField(max_length=1, choices=LEVELS)
    desired_level = models.CharField(max_length=1, choices=LEVELS)

    def __str__(self):
        return "{} level of knowledge for {} is {} / desired is {}".format(self.employee.fullname, self.skill.name, self.level, self.desired_level)

我能够创建一个员工,一个技能和一个EmployeeSkill,甚至可以显示给定员工的所有员工技能,但我正在努力的是我应该如何创建一个显示所有可能的EmployeeSkills的表单。员工并允许该员工更改与每个EmployeeSill关联的级别(和desired_level)。

请帮忙!

1 个答案:

答案 0 :(得分:1)

您可以为ManyToManyFIeld上的选项生成选项,并在select上呈现每个选项并使用AJAX添加值。

<select name="material" id="id_material" required>
    <option value="0" disabled selected>Selecciona el material</option>
     {% for material in materiales %}
       <option value="{{material.id}}">{{material.descripcion}} ({{material.id_tipo_material.unidad}}) -  Total = {{material.cantidad}}</option>
     {% endfor %}
</select>

AJAX请求:

function agrega_material(){

        var url = '{% url "paquetes:agrega_material_paquete" %}';

        var paquete = $('#id_cantidad').data('paquete');

        var material = $('#id_material').val();

        var cantidad = $('#id_cantidad').val();

        $.post(url,
        {
            paquete:paquete,
            material:material,
            cantidad:cantidad
        })
        .done(function( data ) {
            if(data['status'] == 'ko'){
                Materialize.toast('Cantidad es más grande que el material restante.', 4000)
            }else{
                $('#forma_material_paquete').html(data);
                $('select').material_select();
                Materialize.toast('El material ha sido agregado.', 4000)
            }
        });

        return false;
};

您将使用AJAX提交表单,将数据传递到django视图并添加元素或对视图进行修改,然后您可以在请求状态正常时弹出通知。视图示例:

def agrega_material_paquete(request):
if request.method == 'POST':
    #Procesar datos
    id_paquete = int(request.POST.get('paquete')) //Here you receive the data of the AJAX request.
    paquete = get_object_or_404(Paquete, id=id_paquete )
    id_material = int(request.POST.get('material'))
    material = get_object_or_404(Material, id=id_material)
    cantidad_material = int(material.cantidad)
    cantidad = int(request.POST.get('cantidad'))

    if cantidad_material >= cantidad:
        Material_por_paquete.objects.create(paquete=paquete,material=material,cantidad=cantidad)
        #Mostrar vista de nuevo
        form = FormaMateriales()
        materiales = Material.objects.filter(activo=True)
        id_paquete = request.POST.get('paquete')
        materiales_paquete = Material_por_paquete.materiales_paquete(id_paquete)
        html = render_to_string('paquetes/select_materiales.html', {'form': form,'materiales':materiales,'materiales_paquete':materiales_paquete,'paquete':paquete})
        return HttpResponse(html)
    else:
        return JsonResponse({'status':'ko'})
else:
    return JsonResponse({'status':'ko'})