[Fixed]-How to have extra django model fields depending on the value of a field?

1👍

You have some options:

1. OneToOneField on various category models:

  • Pro:
    allows other models to have FK to Job model. E.g. you could retrieve all of a person jobs via person.jobs.all() no matter which category.

  • Con:
    Allows instances of different categories to relate to the same Job instance: Extra work is needed to maintain data integrity

    More tables, more joins, slower queries

    Adding a category always entails a migration!

2. Multi-Table inheritance:

Uses OneToOneField under the hood.

  • Pro:
    as above + but each instance of a category will autocreate its own Job instance, so no collisions between categories.

  • Con:
    More tables, more joins, slower queries. Obscures some of the db stuff that’s going on.

    Adding a category always entails a migration!

3. Job as an abstract base model

  • Pro: Single table for each category, faster queries

  • Con: separate relations need to be maintained for each category, no grouping possible at the db level.

    Adding a category always entails a migration!

4. Put all the category specific fields in Job (and make them nullable)

  • Pro: One Table, easy relations, Queries for special categories via filter on category field still possible.

    You can use specific model managers to handle categories: Job.tutoring.all()

    Possibly many categories share various subsets of fields

    No overengineering, easy maintainability.

    Adding a new category will only require a migration if it requires a field that is not there yet. You could have a generic CharField used by multiple categories for different semantic purposes and access it via propertys with meaningful names. These cannot, however, be used in filters or qs-updates.

À la:

class Job(models.Model):
    # ...
    attribute = models.CharField(...)

    def _get_attribute(self):
        return self.attribute

    def _set_attribute(self, value):
        self.attribute = value

    # for shopping
    shop_name = property(_get_attribute, _set_attribute)

    # for babysitting
    family_name = property(_get_attribute, _set_attribute)

# then you can use
babysitting_job.family_name = 'Miller'
  • Con: Some fields are null for each job

While options 1-3 may better model the real world and make you feel good about the sophisticated model structure you have cooked up, I would not discard option 4 too quickly.

If the category fields are few and commonly shared between categories, this would be my way to go.

0👍

The optimal thing to do would be to use a OneToOneField. Before further explanation, I’ll just use this example:

    from django.db import models

    class Menu(models.Model):
        name = models.CharField(max_length=30)


    class Item(models.Model):
        menu = models.OneToOneField(Menu)
        name = models.CharField(max_length=30)
        description = models.CharField(max_length=100)

Menu here could compare to your Job model. Once an item in the menu is chosen, the Menu model basically extends the chosen Item’s fields. Item here can be compared to your Job category.

You can read more on this stuff here.

👤Nifled

Leave a comment