I’d like to know how I can design my Django model to achieve the following:
Road -> Category (required): Highway (select list)
Road -> Attribute (optional): Traffic -> Heavy + Moderate (checkboxes)
Road -> Attribute (optional): Condition -> Smooth + Rough + Average(checkboxes)
Does it make sense to include TRAFFIC_CHOICES, CONDITION_CHOICES under the Road class vs creating separate classes for each set of choices vs creating a generic Attribute class?
How do I display choices as checkboxes?
The end goal of this model is to be able to create queries such as “Highway roads that are smooth with no traffic“
Here is my attempt:
class Category(models.Model):
CATEGORY_CHOICES = (
('highway', 'Highway'),
('parkway', 'Parkway'),
)
name = models.CharField(max_length=1, choices=CATEGORY_CHOICES, blank=False)
class Road(models.Model):
name = models.TextField(blank=False)
TRAFFIC_CHOICES = (
('moderate', 'Moderate'),
('busy', 'Busy'),
)
traffic = models.CharField(max_length=1, choices=TRAFFIC_CHOICES)
CONDITION_CHOICES = (
('smooth', 'Smooth'),
('rough', 'Rough'),
('average', 'Average'),
)
condition = models.CharField(max_length=1, choices=CONDITION_CHOICES)
First, change the first
models.TextFieldto aCharFieldlike the others.Category does not have to be a separate model, unless you intend to add new categories after your application is finished, in which case it must be a separate model and you should use a ForeignKey relationship from the Road to the Category and ditch the CATEGORY_CHOICES.
Assuming you do not ever intend to add new categories, you can get rid of the Category model entirely and put the CATEGORY_CHOICES into Road. Then change name = to category = and put that into Road too.
You have a max_length of 1 for all of those fields, which is fine, but in that case you need to make the CHOICES map to single characters so they fit in the field. For instance:
Why do you want to use checkboxes for your traffic and condition choices? Checkboxes mean that you can select multiple answers instead of being forced to select just one. This doesn’t make sense conceptually for road condition or traffic, and it isn’t compatible with a CharField (because a CharField can only store one value, without some very contrived setup). You could keep the system you have and use radio buttons if you prefer them over dropdowns, but you can’t use checkboxes without getting rid of the choices and instead making each possible checked box its own BooleanField or NullBooleanField.
I usually put my choices outside of the class definition. I don’t know if it works how you expect it to work when it’s inside. I’m going to move them outside the class definition for my example; this may not be required, so feel free to experiment.
To summarize (and I’m changing the
namefield to aCharFieldbecauseTextFieldis only for really large blocks and not for names):Edit: If you really are sure that checkboxes are the best fit, then you have two main choices. As above, if you intend to add choices later after your application is finished, then your strategy is different (you need to use a ManyToManyField). Otherwise you could implement them like this:
The part where you display them as grouped checkboxes specifically happens when you’re displaying your form, not in the model.
You could also use some kind of bit field, but that’s not included in Django by default — you’d have to install an extension.