Sunil
Sunil

Reputation: 55

How to give user option to select a wagtail collection of images in page?

I am looking for a way to show a list of wagtail collection as a field in a page (just like it showing when you upload an image). A user can select a collection and I can programmatically filter the images to the selected collection. I am still new to wagtail and I am not sure how should I implement this in code.

Thank you in advance for your help.

Upvotes: 3

Views: 2285

Answers (3)

small mammal
small mammal

Reputation: 700

Aug 2022 - Wagtail 2.15.5 - display Wagtail hierarchical collection

enter image description here

from wagtail.admin.templatetags.wagtailadmin_tags import format_collection

class Meeting(models.Model):

    COLLECTION_CHOICES = []
    for c in Collection.objects.all():
        COLLECTION_CHOICES.append((c.id, format_collection(c)))

    title = models.CharField(max_length=100)
    collection = models.ForeignKey(Collection, on_delete=models.PROTECT, help_text="Choose the 'Collection' folder for the meeting's related documents", choices=COLLECTION_CHOICES)

Edit: If you add a new collection to collections and go back the this Meeting model the new collection will not be in the list. As the COLLECTION_CHOICES is only created once for optimization. If you want a dynamic collection choice you need to make a custom form on top of your model e.g.

from wagtail.admin.forms import WagtailAdminModelForm

class MeetingAdminForm(WagtailAdminModelForm):
    # This below field will be automatically added to the Meeting panel fields
    meeting_collection = forms.ChoiceField()

    def __init__(self, *args, **kwargs):
        super(MeetingAdminForm, self).__init__(*args, **kwargs)
        self.fields['meeting_collection'] = forms.ChoiceField(
            initial=self.instance.collection_id,
            choices=[(c.id, format_collection(c)) for c in Collection.objects.all()]
        )

    def save(self, commit=True):
        instance = super().save(commit=False)
        instance.collection_id = self.cleaned_data['meeting_collection']
        if commit:
            instance.save()
        return instance

class Meeting(models.Model):

    base_form_class = MeetingAdminForm

    class Meta:
        """ Meta options """
        ordering = ['title']

    title = models.CharField(max_length=100)
    meeting_datetime = models.DateTimeField()
    location = models.TextField(null=True)
    collection = models.ForeignKey(Collection, on_delete=models.PROTECT, help_text="Choose the 'Collection' folder for the meeting's agenda, minutes and related documents")
    committee = models.ForeignKey(Committee, on_delete=models.CASCADE)

    panels = [
        FieldPanel('title'),
        FieldPanel('meeting_datetime'),
        FieldPanel('location'),
        FieldPanel('meeting_collection'),
        FieldPanel('committee'),
    ]

Upvotes: 0

VictoriaChan
VictoriaChan

Reputation: 370

I've managed to do this using wagtail-generic-chooser just following the instructions on the README.md, and using wagtail core Collection model instead of People.

Upvotes: 1

Kalob Taulien
Kalob Taulien

Reputation: 1918

So there's a couple ways you can do this. The first, and probably the least-ideal way is to register Collection as a snippet and use a SnippetChooserPanel.

"""Register Collection snippet."""
from wagtail.snippets.models import register_snippet
from wagtail.core.models import Collection

# Register Collections as Snippets so we can use the SnippetChooserPanel to select a collection
register_snippet(Collection)

And then in your model you can use a SnippetChooserPanel, like so (note, this is all untested code)

from django.db import models
from wagtail.core.models import Page

class CustomPage(Page):

    # ...
    collection = models.ForeignKey(
        'wagtailcore.Collection',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    content_panels = Page.content_panels + [
        # ...
        SnippetChooserPanel('collection'),
    ]

@gasman's comment on the answer has a link to another solution that's much more elegant than mine.

Upvotes: 3

Related Questions