Database Schema Recommendations
Based on a review of the models and existing migrations, here are my recommendations for database schema improvements before the initial deployment.
General Recommendations
-
Review
blank=Trueandnull=True: Many models usenull=True, blank=Trueon character fields (CharField,TextField). For character fields, it's generally better to usedefault=""andblank=Trueinstead ofnull=True. This avoids having two different "empty" values (None and an empty string) for the same field. This is not a blocking issue, but it's a good practice for data consistency.- Affected Models:
RcrainfoProfile,WasteLine(many JSONFields),Player.
- Affected Models:
-
Abstract Base Models: The project already uses
BaseModelintrak/apps/teams/models.pyandpegasus/apps/employees/models.pyto addcreated_atandupdated_atfields. This is great! However, I noticed thatWasteLine,WasteCode,DotLookup,Profile,RcrainfoProfile,RcrainfoSiteAccess, andUserAPIKeydo not inherit fromBaseModel. It would be beneficial for all models to have these timestamp fields for auditing and debugging purposes. I recommend creating a common base model in a central place (e.g.,trak/apps/utils/models.py) and having all models inherit from it. -
UUIDs as Primary Keys:
TrakUser,Invitation,Profile, andRcrainfoProfileuseUUIDFieldas a primary key. This is a good practice, especially for models that might be exposed to the public. I recommend using UUIDs as primary keys for all new models. For existing models, it might be too much work to change them now, but it's something to consider for the future.
App-Specific Recommendations
rcra app (wasteline, manifest, rcrasite)
-
JSONFields: The
WasteLinemodel has manyJSONFields. This is fine, but it can make querying difficult. If you find yourself needing to query based on the contents of these fields, consider creating separate models for them. For example, if you need to query forWasteLines with a specificmanagement_method, it would be better to have aManagementMethodmodel with aForeignKeyfromWasteLine. Since this is the initial deployment, now is the time to make these changes. -
WasteCode.STATE_CHOICES: TheWasteCodemodel has a largeSTATE_CHOICESlist. This could be moved to a separate file or a more structured format if it becomes hard to manage. This is not a major issue, but something to keep in mind. -
on_deleteproperties: Intrak/apps/rcra/wasteline/models.pythemanifestfield on theWasteLinemodel hason_delete=models.CASCADE. This means if aManifestis deleted, all itsWasteLines will also be deleted. This seems reasonable. However, intrak/apps/profile/models.py,RcrainfoSiteAccess.profileison_delete=models.PROTECT. This will prevent the deletion of aRcrainfoProfileif it has anyRcrainfoSiteAccessobjects associated with it. This is a good way to prevent accidental data loss. I recommend reviewing allon_deleteproperties to ensure they match the intended behavior.SET_NULLis also a good option when you want to keep the object but remove the relationship.
profile app
-
ProfileandRcrainfoProfile: There are two profile models,ProfileandRcrainfoProfile, with a one-to-one relationship betweenProfileandTrakUser, and a one-to-one relationship betweenProfileandRcrainfoProfile. This seems a bit complex. It might be simpler to combineProfileandRcrainfoProfileinto a single model, or at least to haveRcrainfoProfilehave a directOneToOneFieldtoTrakUser. This would simplify queries and reduce the number of joins needed to get all of a user's profile information. -
rcrainfo_profileOneToOneField: Thercrainfo_profileon theProfilemodel is aOneToOneFieldwithon_delete=models.SET_NULL. This means that if aRcrainfoProfileis deleted, thercrainfo_profilefield on theProfilewill be set toNULL. However, the relationship is one-to-one, so it might be better to useon_delete=models.CASCADEand delete theProfileas well, or to useon_delete=models.PROTECTto prevent the deletion of theRcrainfoProfileif it's linked to aProfile.
teams app
BaseTeamModel: TheBaseTeamModelis a great way to ensure that models are associated with a team. I recommend that any new models that should be scoped to a team inherit from this model.
Summary of Recommendations
Before creating the first deployment, I recommend the following actions:
- Create a central
BaseModelwithcreated_atandupdated_atfields and have all models inherit from it. - Review
null=TrueonCharFieldsand consider usingdefault=""instead. - Simplify the
ProfileandRcrainfoProfilemodels. I would be happy to help with this refactoring. - Review
on_deleteproperties on allForeignKeyandOneToOneFieldfields. - Consider breaking out
JSONFielddata into separate models in theWasteLinemodel if you need to query that data.