views:

254

answers:

2

Hello all,

I have the following code:

class GroupDepartmentManager(models.Manager):
  def get_query_set(self):
    return super(GroupDepartmentManager, self).get_query_set().filter(group='1')

class Department(models.Model):
 name = models.CharField(max_length=128)
 group = models.ForeignKey(Group)
 def __str__(self):
    return self.name
 objects = GroupDepartmentManager()

... and it works fine. Only thing is that I need to replace group='1' with group=(the group specified by group = models.ForeignKey(Group)). I am having quite a time trying to determine whether that foreign key needs to be passed into the class, or into the get_query_set function, or what. I know that you can accomplish this with group.department_set.filter(group=desired group), but I am writing this model for the admin site, so I need to use a variable and not a constant after the = sign.

Thanks in advance for any advice you all can provide.

+2  A: 

I have a hunch that replacing the default Manager on objects in this manner might not be good idea, especially if you're planning on using the admin site... Even if it helps you with your Employees, it won't help you at all when handling Departments. How about a second property providing a restricted view on Departments alongside the usual objects? Or move the standard Manager from objects to _objects and rename from_same_group to objects if you really prefer your original approach for your app.

class Department(models.Model):
    name = models.CharField(max_length=128)
    group = models.ForeignKey(Group)
    def __str__(self):
        return self.name
    objects = models.Manager()

    @property
    def from_same_group(self):
        return Department.objects.filter(group__exact=self.group)

Also, I understand you know how to set up the admin site to take advantage of the funny Manager; if not (or if I misunderstood your question somehow), leave a comment, I'll try to follow up sometime soon.


EDIT: OK, to make this more clear: if you do absolutely insist on replacing objects, you'd probably want to do this:

class Department(models.Model):
    name = models.CharField(max_length=128)
    group = models.ForeignKey(Group)
    def __str__(self):
        return self.name

    _objects = models.Manager()

    @property
    def objects(self):
        # note the _objects in the next line
        return Department._objects.filter(group__exact=self.group)
Michał Marczyk
I'm afraid I haven't a clue. I changed from_same_publisher to from_same_group. But wouldn't I want to say objects = from_same_publisher()?
John
Ouch, the publisher bit comes from where I used similar code... Anyway, I'll edit to make things more clear.
Michał Marczyk
Thanks, but I added this to the Department class, and the select box is still showing all Department objects. I think that I still have to set up the admin page to, as you indicated, take advantage of this setup. I'm confused because I thought that all Manager business took place inside models.py, without changes in admin.py.
John
+2  A: 

You might want to reconsider the relationship between the groups and departments if you find that trying to create a custom manager is too complex. Managers excel at simplifying common queries, but flop at displaying complex relationships between models and instances of models.

However, I think this article about filtering model objects with a custom manager will point you in the right direction. The author proposes a technique to perform a function call that returns a customized manager class that has the filter parameters you specify saved in the class so they don't get passed to the instance. Do it!

jathanism
Great link, thanks. It's definitely a hack, but I will try this and report back.
John
No way! It's way too dynamic to be a hack! I actually think it's quite clever.
jathanism
Fair enough! I implemented this with "objects = get_filter_manager(group=group)" in the Department class and received the same stumbling block that I've always received before: "'str' object has no attribute 'creation_counter'". I can't seem to get the code to indent, or I would post all of it here.
John