acidjunk
acidjunk

Reputation: 1880

How to limit choices to Foreign keys in Django admin

I run into a problem when using the Django admin. I'm building a small ScrumBoard. It has projects, with statuses, stories and tasks.

Consider the following model:

@python_2_unicode_compatible
class Project(models.Model):
    name = models.CharField(max_length=100)

    class Meta:
        verbose_name = _('Project')
        verbose_name_plural = _('Projects')

    def __str__(self):
        return self.name

@python_2_unicode_compatible
class Status(models.Model):
    name = models.CharField(max_length=64) # e.g. Todo, In progress, Testing Done
    project = models.ForeignKey(Project)

    class Meta:
        verbose_name = _('Status')
        verbose_name_plural = _('Statuses')

    def __str__(self):
        return self.name


@python_2_unicode_compatible
class Story(models.Model):
    """Unit of work to be done for the sprint. Can consist out of smaller tasks"""
    project = models.ForeignKey(Project)
    name=models.CharField(max_length=200)
    description=models.TextField()
    status = models.ForeignKey(Status)

    class Meta:
        verbose_name = _('Story')
        verbose_name_plural = _('Stories')

    # represent a story with it's title
    def __str__(self):
        return self.name

The problem: when an admin user creates a story he will see statuses from all the projects instead of the status from one project.

Upvotes: 1

Views: 1296

Answers (2)

christophe31
christophe31

Reputation: 6467

To filter statuses by project, you need your story to already exist so django know which project we are talking about. If you set status nullalble, you can do like this (implying, you do save and continue on first save to set status)

class StatusAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super(StatusAdmin, self).get_form(request, obj, **kwargs)
        if obj and obj.project:
            form.base_fields['status'].queryset = \
                form.base_fields['status'].queryset.filter(project=obj.project)
        elif obj is None and 'status' in form.base_fields: # on creation
            del form.base_fields['status']
        return form

Upvotes: 2

abidibo
abidibo

Reputation: 4287

You will need something like django-smart-selects

Upvotes: 0

Related Questions