Best solution for a limited number of dynamic model fields in Django app

Hi all,

I’m using Django to build an app for outdoor professionals (educators, guides) to keep track of their experience. Basically a logbook but eventually with features like collaboration, mapping, and reporting. You can see what I have so far here!

Currently working on the Experience model. An Experience will have standard attributes like where did you go, when, was it a professional trip or your own personal recreation, who were your clients? But it should also have attributes specific to each outdoor pursuit. For paddling, canoes, kayaks, etc. For whitewater, what grade (1, 2, 3…)? For climbing, what grade (5.10, 5.11…) and how many pitches?

I’ll build in many of these attributes, but I also want the app to be flexible enough that users can add their own sport (e.g., barefoot snow skiing) and create fields based on what an employer would need to know about their experiences in that sport.

I’ve heard about solutions like EAV, but a lot of the advice online is like 12 years old. Given that most of my users won’t need custom fields, and those who do will define maybe 2-3 Experience types with 5-6 custom fields each, I’m wondering what would be the best way to do implement this today.

Currently on postges, but would love a database-agnostic solution in case I decide to use a different database for production. Note: I’m early enough in this project that I’m even open to using a platform other than Django, if there’s one that makes way more sense for this.

Thanks in advance!

at least from my understanding that the project is still fairly new and you have a ton of uncertainty to solve aside from the technical stuff, I’d suggest avoiding EAV to have the flexibility of switching the DB in the future,

my best guess would be to hit the ground, start putting the app to use and allow yourself the freedom to change your mind later… so I’d suggest something like:

from django.db import models
from django.contrib.postgres.fields import JSONField

class Experience(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateField()
    location = models.CharField(max_length=255)
    professional = models.BooleanField()
    clients = models.TextField()
    custom_fields = JSONField()

# {
#     "paddling": {
#         "boat_type": "kayak",
#         "something": True
#     },
#     "climbing": {
#         "grade": "5.10",
#         "also_something": 3
#     }
# }

Thanks very much for the ideas. It’s good to know that EAV might limit my options down the track, so I definitely don’t want that. You’re right that the project is pretty new. I’ll try to do some JSON fields for now!