Reputation: 13
I am writing an application to help employees track projects the are working on.
Part of the form should allow logged in employees to click a drop down and see all projects they are working on. This is the part I am struggling with; specifically getting ONLY the logged in user's projects populated in a drop down. Any help or insight is much appreciated. Thanks……
models.py
class Photo(models.Model):
image = models.ImageField(upload_to='uploads/images/photo')
title = models.CharField(max_length=50)
def __unicode__(self):
return self.title
class Employee(models.Model):
user = models.ForeignKey(User, unique=True)
photo = models.ImageField(upload_to='uploads/images')
department = models.ForeignKey(Department, null=True)
phone = PhoneNumberField("Phone")
def __unicode__(self):
return self.user.get_full_name()
class Projects(models.Model):
name = models.CharField(max_length=40)
student = models.ForeignKey(Student)
photos = models.ManyToManyField(Photo, blank=True, null=True)
forms.py
class ProjectsForm(forms.ModelForm):
employee = get_object_or_404(Employee, user=user)
employee_projects = employee.projects_set.all()
name = forms.ModelChoiceField(queryset=employee_projects,
empty_label="(Select a Project)", required=True)
class Meta:
model = Projects
Upvotes: 1
Views: 269
Reputation: 34032
You need to put first two lines from ProjectsForm
class definition to its initialization method and change them a bit.
class ProjectsForm(forms.ModelForm):
name = forms.ModelChoiceField(queryset=Employee.objects.all(),
empty_label="(Select a Project)", required=True)
class Meta:
model = Projects
def __init__(self, user, *args, **kwargs):
super(self, ProjectsForm).init(*args, **kwargs)
employee = get_object_or_404(Employee, user=user)
self.fields['name'].queryset = employee.projects_set.all()
Now, some explanation. Hope someone will find it useful.
In your original ProjectsForm
definition, you're trying to get employee's projects when your class is defined. But this happens once your forms.py file is compiled, which takes place rarely (when you change code, for example). Also, you of course have no data that is necessary to filter projects, i.e., no user
object, at that stage.
Instead, you need to do this each time the class is initialized. Initialization in Python takes place in special __init__()
method. For example, when you're doing something like
form = ProjectsForm(data=request.POST)
in your view, what happens is that ProjectsForm.__init__(data=request.POST)
is called to initialize ProjectsForm
into an instance.
So, in our new definition, we're requiring a new argument (user) to be passed to the form when it's instantiated. So you can do something like this in your view:
form = ProjectsForm(request.user, data=request.POST)
In new initialization method, first we're calling the initialization method of parent class (which does some internal django things and should be called anyway), then use argument user
to get related employee, and then assign a queryset with that employee's projects to the name
field.
Sorry if I'm being too verbose.
See also:
Upvotes: 1
Reputation: 113
Why not have a many to many field in the Employee model that points to all the projects the employee can work on?
https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField
I think that would be the best way to do it.
Upvotes: 0