7

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
            ]
        }
    }
]
thedeepfield
  • 6,138
  • 25
  • 72
  • 107
  • Maybe you could do that in the view, something similar as [here](http://stackoverflow.com/questions/5329586/django-modelchoicefield-filtering-query-set-and-setting-default-value-as-an-obj) (Yuji's second solution : you probably can explore EmployeeInlineFormSet's attributes and find what you need) – Arthur Mar 14 '12 at 23:49

1 Answers1

16

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))
jpic
  • 32,891
  • 5
  • 112
  • 113
  • while this makes sense to me and looks clean, it does not work... the other department projects show up... – thedeepfield Mar 15 '12 at 16:30
  • could you post some json fixtures so that I can actually test it ? Also I thought of another solution: use a regular formset instead of an inlineformset since you're crafting the queryset. Then, set the Employee manually before saving. – jpic Mar 15 '12 at 16:32
  • while this makes sense to me and looks clean, it does not work... the other department projects show up... in shell print queryset returns the right membership objects, but in print f, you can still all membership.project options (other departments projects). Sorry.. new to programing.. what is a json? i thought about using a regular formset, but i thought inlineformset was used for this purpose? – thedeepfield Mar 15 '12 at 16:42
  • You can get some json fixture with this command: manage.py dumpdata appname --indent=4. It is true that inlineformset is made for this purpose, but it's also supposed to mess with the queryset. Another solution is to implement a BaseInlineFormset subclass. But i'd need some json fixtures and do some actual tests before I can point you toward a precise solution. – jpic Mar 15 '12 at 17:07
  • that manage.py dumpdata command is pretty cool! you learn something new every day. is there a way to import that data back into a program? I've edited the question to post the dumpdata. I will attempt to go the formsetroute. – thedeepfield Mar 15 '12 at 18:05
  • It works for me. The formset uses the queryset. Maybe you could detail the issue ? – jpic Mar 17 '12 at 09:47