mrisher
mrisher

Reputation: 1071

Correct way to store multi-select results in Django model

all:

What is the correct Model fieldtype to use with a CheckboxSelectMultiple widget for static data? I am receiving validation errors and feel I'm missing something simple.

The app is a simple Django 1.6 app in which a Campground object can have multiple eligible_days (e.g. Site #123 may be available on Monday & Tuesday, while Site #456 is available on Weds-Friday).

Because it's static data and I've ready that a ManyToManyField has unnecessary DB overhead, I'm trying to do this with choices defined inside the model, but when I try to save I get the validation error Select a valid choice. [u'5', u'6'] is not one of the available choices. every time.

Thank you for your help! /m

models.py

class CampgroundQuery(models.Model):
SUN = 0
MON = 1
TUE = 2
WED = 3
THU = 4
FRI = 5
SAT = 6

DAYS_OF_WEEK_CHOICES = (
    (SUN, 'Sunday'),
    (MON, 'Monday'),
    (TUE, 'Tuesday'),
    (WED, 'Wednesday'),
    (THU, 'Thursday'),
    (FRI, 'Friday'),
    (SAT, 'Saturday'),
)

# loads choices from defined list
eligible_days = models.CharField(max_length=14,choices=DAYS_OF_WEEK_CHOICES,
    blank=False, default='Saturday')
campground_id = models.SmallIntegerField()
stay_length = models.SmallIntegerField()
start_date = models.DateField()
end_date = models.DateField()

admin.py

from django.contrib import admin
from searcher.models import CampgroundQuery
from forms import CampgroundQueryAdminForm

class CampgroundQueryAdmin(admin.ModelAdmin):
    form = CampgroundQueryAdminForm

admin.site.register(CampgroundQuery, CampgroundQueryAdmin)

forms.py

from django import forms
from django.contrib import admin
from searcher.models import CampgroundQuery

class CampgroundQueryAdminForm(forms.ModelForm):
    class Meta:
        model = CampgroundQuery
        widgets = {
            'eligible_days': forms.widgets.CheckboxSelectMultiple
        }

Upvotes: 5

Views: 10793

Answers (2)

TAH
TAH

Reputation: 1746

I know this is an old question, but for those who wish to avoid using a ManyToManyField, there is a package to do this, django-multiselectfield, which is quick and easy to implement.

forms.py

from multiselectfield import MultiSelectFormField

class MyForm(forms.ModelForm):
    my_field = MultiSelectFormField(choices=MyModel.MY_CHOICES)

models.py

from multiselectfield import MultiSelectField

class MyModel(models.Model):
    MY_CHOICES = (
        ('a', "A good choice"),
        ...
        ('f', "A bad choice"),
    )
    my_field = MultiSelectField(choices=MY_CHOICES, max_length=11)

And that's it! It stores the keys of MY_CHOICES in a comma-separated string. Easy!

Upvotes: 9

Peter DeGlopper
Peter DeGlopper

Reputation: 37319

A ManyToManyField is the correct choice.

In theory you could create a compact representation, like a string field containing representations like "M,W,Th" or an integer that you'll set and interpret as seven binary bits, but that's all an immense amount of trouble to work with. ManyToManyFields are fine.

Upvotes: 5

Related Questions