Limiting the scope of a ForeignKey relationship?

I am developing a portfolio application. In this application, I have a model called "Project" that looks something like this:

class Project(models.Model):
    ... 
    images = models.ManyToManyField(Image)
    ...

      

therefore, basically, this Project can contain a set of images (any of these images can belong to another project).

Now, what I would like to add is a way to indicate that one of these "images" is "lead_image".

So, I could add something like this:

class Project(models.Model):
    ... 
    images = models.ManyToManyField(Image, related_name='images')
    lead_image = models.ForeignKey(Image, related_name='lead_image')
    ...

      

However, the problem is that lead_image can be ANY way in this case. I really want this to be one of the "images" associated with this model instance.

I think I need to use the "ForeignKey.limit_choices_to" argument, but I'm not sure how to use that ... especially since when the model is first instantiated there won't be any images in the "images" directory yet.

Any help would be greatly improved.

Arc

+2


source to share


2 answers


Another approach to your problem is to use a staging table with the is_lead_image boolean property.

class Image(models.Model):
    ...

class Project(models.Model):
    images = models.ManyToManyField(Image, through='ProjectImage')
    ...

class ProjectImage(models.Model):
    image = models.ForeignKey(Image)
    project = models.ForeignKey(Project)
    is_lead_image = models.Boolean(default=False)

    def save(self, *args, **kwargs):
        if self.is_lead_image:
            self._default_manager.filter(project=self.project).update(is_lead_image=False)
        return super(ProjectImage, self).save(*args, **kwargs)

      



* Note. If you like it and if you have access, you can simply add the is_lead_image field and save directly to the Image class.

+2


source


If you want to achieve extreme effect in the admin tool, you can override the formfield-for-foreignkey method and insert your own filter.

class ProjectAdmin(admin.ModelAdmin):

    # ...

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "lead_image":
            kwargs["queryset"] = self.model.images.all()
            return db_field.formfield(**kwargs)
        return super(ProjectAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

      

The problem I see here (with this general idea of ​​just sampling from selected images) is that for new models, the original models. Images will not be set on page load. You are likely to run into this problem no matter what you deal with on the server side.



It might work, but it requires an extra click: ManyToMany model.images will be selected when the model is first created. Once selected, if the Save and Continue button is clicked, then these images should appear in the FK field of the .lead-image model.

Another option is to override the default admin form and create something custom (just like custom javascript javascript to automatically update the host image combo box).

+2


source







All Articles