Search code examples
djangoviewmodeldjango-querysetinline-formset

DJANGO: how to limit inlineformset queryset


An EU can use this form to select the roles (Project Manager, Developer etc) they play for any given project. I want to limit the project field options to only those in the employees department. Right now, the EU can select any departments' project (but not the department, I've excluded that entirely) How can I do that? queryset=blabla doesnt work..

MODELS:

class Department(models.Model):
    name = models.CharField(max_length=20)
    def __unicode__(self):
        return self.name

class Employee(models.Model):
    fname = models.CharField(max_length=15)
    department = models.ForeignKey(Department)
    def __unicode__(self):
        return self.fname

class Projecttype(models.Model):
    name = models.CharField(max_length=20)
    def __unicode__(self):
        return self.name

class Project(models.Model):
    projecttype = models.ForeignKey(Projecttype)
    department = models.ForeignKey(Department)
    members = models.ManyToManyField(Employee, through='Membership')
    def __unicode__(self):
       return "%s > %s" % (self.department, self.projecttype)

class Role(models.Model):
    name = models.CharField(max_length=20)
    def __unicode__(self):
       return self.name

class Membership(models.Model):
    project = models.ForeignKey(Project, null=True)
    department = models.ForeignKey(Department)
    employee = models.ForeignKey(Employee)
    role = models.ManyToManyField(Role, blank=True, null=True)
    class Meta:
        unique_together = (("project", "employee",),)

VIEW:

def employee_edit(request, employee_id):
    i = get_object_or_404(Employee, pk=employee_id)
    EmployeeInlineFormSet = inlineformset_factory(Employee, Membership, extra=1, exclude=('department',), queryset=Membership.objects.filter(department=i.department))
    if request.method == "POST":
        f = EmployeeInlineFormSet(request.POST, instance=i)
        if f.is_valid():
            f.save()
    else:
        f = EmployeeInlineFormSet(instance=i)
    return render_to_response('testdb/edit.html', {'item': i, 'formset': f, }, context_instance=RequestContext(request))

JSON: MANAGE.PY DUMPDATA TESTDB --INDENT=4

[
    {
        "pk": 1,
        "model": "testdb.department",
        "fields": {
            "name": "IT Department"
        }
    },
    {
         "pk": 2,
        "model": "testdb.department",
        "fields": {
            "name": "Operations Department"
        }
    },
    {
        "pk": 1,
        "model": "testdb.employee",
        "fields": {
            “department”: 1,
            "fname": "Alice"
        }
    },
    {
        "pk": 2,
        "model": "testdb.employee",
        "fields": {
            “department”: 2,
            "fname": "Eve"
        }
    },
    {
        "pk": 3,
        "model": "testdb.employee",
        "fields": {
            “department”: 1,
            "fname": "Bob"
        }
    },
    {
        "pk": 1,
        "model": "testdb.projecttype",
        "fields": {
            "name": "PROCESS IMPROVEMENT"
        }
    },
    {
        "pk": 2,
        "model": "testdb.projecttype",
        "fields": {
            "name": "DATA CLEANUP"
        }
    },
    {
        "pk": 1,
        "model": "testdb.project",
        "fields": {
            “projecttype”: 1,
            “department”: 1
        }
    },
    {
        "pk": 2,
        "model": "testdb.project",
        "fields": {
            “projecttype”: 1,
            “department”: 2
        }
    },
    {
        "pk": 3,
        "model": "testdb.project",
        "fields": {
            “projecttype”: 2,
            “department”: 1
        }
    },
    {
        "pk": 1,
        "model": "testdb.role",
        "fields": {
            "name": "Project Manager"
        }
    },
    {
        "pk": 2,
        "model": "testdb.role",
        "fields": {
            "name": "Analyst"
        }
    },
    {
        "pk": 1,
        "model": "testdb.membership",
        "fields": {
            "employee": 1,
            “department”: 1,
            “project”: 1,
            "role": [
                1,
                2
            ]
        }
    },
    {
        "pk": 2,
        "model": "testdb.membership",
        "fields": {
            "employee": 2,
            “department”: 2,
            “project”: 2,
            "role": [
                1
            ]
        }
    },
    {
        "pk": 3,
        "model": "testdb.membership",
        "fields": {
            "employee": 3,
            “department”: 1,
            “project”: 1,
            "role": [
                1
            ]
        }
    }
]

Solution

  • Don't pass the queryset when you're creating the formset class here:

    EmployeeInlineFormSet = inlineformset_factory(Employee, Membership, extra=1, exclude=('department',))
    

    Pass the queryset when instantiating the formset:

    f = EmployeeInlineFormSet(instance=i, queryset=Membership.objects.filter(department=i.department))
    

    e.g.:

    def employee_edit(request, employee_id):
        i = get_object_or_404(Employee, pk=employee_id)
        queryset=Membership.objects.filter(department=i.department)
        EmployeeInlineFormSet = inlineformset_factory(Employee, Membership, extra=1, exclude=('department',))
        if request.method == "POST":
            f = EmployeeInlineFormSet(request.POST, instance=i, queryset=queryset)
            if f.is_valid():
                f.save()
        else:
            f = EmployeeInlineFormSet(instance=i, queryset=queryset)
        return render_to_response('testdb/edit.html', {'item': i, 'formset': f, }, context_instance=RequestContext(request))