Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django multiple choice and multi-select field in model and form

Tags:

django

I am learning Django and have hit an inssue that I don't know what to Google for. I have the standard User model and a Profile model that points into the User model via a OneToOne field. That part plus the profile's Form and the CBVs all work.

A profile holder can have one or more professional affiliations. This is not for a union but my Dad, for example, as a welder, was affiliated with: "The Iron Workers", "Steam Fitters", "Boiler Makers", "Pipe Fitters" and a couple other specific unions that used welders. So if I want the profile and form to allow multiple choices and multiple selected results for affiliations then I see that you might use

class Profile(models.Model):
    GROUPS = (
        ('IW', 'Iron Workers'),
        ('PF', 'Pipe Fitters'),
        ...
    )
    affiliation = models.CharField(
        max_length=3,
        choices=RANK,
        default='U',
        blank=True,
        null=True,
    )
    ...

In the associated form it looks like you use a

    GROUPS = (
        ('IW', 'Iron Workers'),
        ('PF', 'Pipe Fitters'),
        ...
    )
    affiliation = forms.MultipleChoiceField(
        choices=GROUPS
    )

What if I want a db table of these choice items instead of tuples? If I have to add to a list of choices then editing the code might not be the most convenient response. Maybe the list of groups should be in the Django admin area.

How do I tell the model and form to look in a separate db table for the possible values and then how do I modify the model and form to allow for zero or more group affiliations?

like image 524
7 Reeds Avatar asked Aug 26 '18 02:08

7 Reeds


Video Answer


1 Answers

You need to create a many-to-many relationship to a new model, let's call it Skill, that represents the available skills that can be dynamically created.

class Profile(models.Model):
    # ...

    skills = models.ManyToManyField(
        to='myapp.Skill',  # use a string in the format `app_name.model_name` to reference models to avoid issues using the model before it was defined
        related_name='user_profiles',  # the name for that relation from the point of view of a skill
    )

class Skill(models.Model):
    name = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=3)

Then in your form you can just add that many-to-many field skills. It will by default be a multiple choice field in the django admin.

The relation can have zero to n entries for each pair of profile and skill. In other words, every user can have zero to n skills and vice versa.

To allow for a default value you will have to write a custom migration that creates that default entity of a Skill to make sure it is in the database at runtime.

like image 124
trixn Avatar answered Sep 18 '22 17:09

trixn