Our SAAS site utilizes a DRF backend with a Vue frontend. We have fields that do not require a value from the user, but do require a value in the database. I'd like to know where's the best place to supply such dynamic defaults. I've read in other posts that "save() is not always called" - though I don't yet know the circumstances where it would not be called.
So, consider the following model:
class Tenant(models.Model):
name = models.CharField(max_length=100)
subdomain = models.CharField(max_length=100, blank=True, null=True)
schema_name = models.CharField(max_length=63, unique=True)
In this case, only "name" is required (from the user); "schema_name", if left blank in the frontend form, can be derived from "name" (converting it to lowercase). Likewise, "subdomain" can be derived from "schema_name". "subdomain" can be blank/null because the "public" schema doesn't reference a subdomain, but its value will be required for all tenants other than "public".)
So where should I put the code that populates those fields if they are blank when it comes time to create or update a Tenant?
Save will be called unless you do bulk updates, so you can put it there just fine. I prefer not to if there is a choice, but sometimes there isn't.
If you want to put it in the serializer, you can write something like this, and then use a ModelViewSet
to handle the details:
class TenantSerializer(ModelSerializer):
name = CharField(required=True, min_length=1)
sub_domain = CharField(required=False)
class Meta:
model = Tenant
fields = ['id', 'name', 'sub_domain']
def validate(self, attrs):
# attrs is all fields parsed & validated on a per-field level
# in here you can do validation that depends on >1 field
# values returned will be passed to the serializer create()/update()
# via the common serializer.save() method
if self.instance:
# doing an update, maybe different logic, or just ignore?
else:
if not attrs.get('sub_domain'): # missing or blank
attrs['sub_domain'] = parse_subdomain(attrs.get('name'))
return attrs