Creating dropdown buttons in django

I've been trying to figure out how to implement dropdown buttons in Django but has not figured out what works.

What I created is:

class AMLVideo(models.Model):

    LANGUAGE = (
        ('LAN', 'Language'),
        ('FR', 'French'),
        ('EN', 'English'),
        ('HIN', 'Hindi'),
        ('SPA', 'Spanish'),
        ('GER', 'German'),
    )

    LEVEL = (
        ('BEG', 'Beginner'),
        ('INT', 'Intermediary'),
        ('ADV', 'Advanced'),
    )

    CATEGORY = (
        ('ANI', 'Animal'),
        ('ENV', 'Environmental'),
        ('MOR', 'Moral'),
        ('FOLK', 'Folktales'),
        ('ADN', 'Adventure'),
        ('POE', 'Poems'),
        ('FUN', 'Funny'),
    )

    title = models.CharField(max_length=100, default=None)
    level = models.CharField(max_length=100, choices=LEVEL)
    language = models.CharField(max_length=100, choices=LANGUAGE)
    category = models.CharField(max_length=100, choices=CATEGORY)
    video = EmbedVideoField(verbose_name='Videos',
                        help_text='URL of Video')

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = "video"
        verbose_name_plural = "videos"

Then, my views are:

    def home(request):
        amlvideo = AMLVideo.objects.filter().order_by("-category", "-language", "-level")
        context = {"amlvideo": amlvideo}
        return render(request, "aml/home.html", context)

Basically what I want to do is to have default categories on the buttons and another user can add a category from his profile. These categories are then showed on the front end, from which the videos with the categories are "fixed" when a user chooses a category.

The example is this site: https://www.planetread.org/anibooks

Anyone can help me?

Upvotes: 0

Views: 292

Answers (1)

Toan Quoc Ho
Toan Quoc Ho

Reputation: 3378

You can use Django Form in this case to create dropdowns on client side. You can use a form to hold the filter data and then when you create a form, you can add categories, languages, levels from your user profile into the form and put it into view context. Like so:

Filter form:

from django import forms


class AMLVideoFilterForm(forms.Form):
    LANGUAGES = [
        ('', 'All'),
        ('LAN', 'Language'),
        ('FR', 'French'),
        ('EN', 'English'),
        ('HIN', 'Hindi'),
        ('SPA', 'Spanish'),
        ('GER', 'German'),
    ]

    LEVELS = [
        ('', 'All'),
        ('BEG', 'Beginner'),
        ('INT', 'Intermediary'),
        ('ADV', 'Advanced'),
    ]

    CATEGORIES = [
        ('', 'All'),
        ('ANI', 'Animal'),
        ('ENV', 'Environmental'),
        ('MOR', 'Moral'),
        ('FOLK', 'Folktales'),
        ('ADN', 'Adventure'),
        ('POE', 'Poems'),
        ('FUN', 'Funny'),
    ]

    language = forms.ChoiceField(required=False)
    level = forms.ChoiceField(required=False)
    category = forms.ChoiceField(required=False)

    def __init__(profile, *args, **kwargs):
        # Combine default choices and choices from user profile on form create
        self.fields['category'].choices = self.CATEGORIES + [(category.id, category.name) for category in profile.categories]
        self.fields['language'].choices = self.LANGUAGES + [(language.id, language.name) for language in profile.languages]
        self.fields['level'].choices = self.LEVELS + [(level.id, level.name) for level in profile.levels]

Your model will be like this:

class AMLVideo(models.Model):
    title = models.CharField(max_length=100, default=None)
    level = models.CharField(max_length=100)
    language = models.CharField(max_length=100)
    category = models.CharField(max_length=100)
    video = EmbedVideoField(verbose_name='Videos',
                        help_text='URL of Video')

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = "video"
        verbose_name_plural = "videos"

Then in your view:

from .forms import AMLVideoFilterForm
from .models import AMLVideo


def home_view(request):
    videos = AMLVideo.objects.all()

    # Get category from filter
    category = request.GET.get('category', '')
    if category:
        videos = videos.filter(
            category__exact=category
        )

    # Get language from filter
    language = request.GET.get('language', '')
    if language:
        videos = videos.filter(
            language__exact=language
        )

    # Get level from filter
    level = request.GET.get('level', '')
    if level:
        videos = videos.filter(
            level__exact=level
        )

    videos = videos.order_by("-category", "-language", "-level")

    # Create new filter and keep the current filter
    filter_form = AMLVideoFilterForm(profile=request.user.profile, initial={
        "category": category, "language": language, "level": level
    })
    context = {
        "videos": videos,
        "filter_form": filter_form
    }
    return render(request, 'aml/home.html', context=context)

In your aml/home.html, you can use the form like this:

<form>
    <ul>
        <li> Category: {{ filter_form.category }}</li>
        <li> Category: {{ filter_form.language }}</li>
        <li> Category: {{ filter_form.level }}</li>
    </ul>
    <input type="submit" value="Filter">
</form>
{% for video in videos %}
    <p>Filtered videos here!</p>
{% endfor %}

You can remove the submit input and trigger it on select change.

Hope that helps!

Upvotes: 3

Related Questions