-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Usability enhancements and hardening for Django models #11725 #11726
Conversation
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This migration does not produce any SQL
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This SQL looks like:
BEGIN;
--
-- Alter field data on tilemodel
--
ALTER TABLE "tiles" ALTER COLUMN "tiledata" SET DEFAULT '{}'::jsonb;
UPDATE "tiles" SET "tiledata" = '{}'::jsonb WHERE "tiledata" IS NULL; SET CONSTRAINTS ALL IMMEDIATE;
ALTER TABLE "tiles" ALTER COLUMN "tiledata" SET NOT NULL;
ALTER TABLE "tiles" ALTER COLUMN "tiledata" DROP DEFAULT;
COMMIT;
A db_default on this field didn't seem of much value, but I will circle back to #10958 to get moving on db defaults for primary key fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This avoids having two representations of no data--None
and {}
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could discuss whether to do the same thing for provisionaledits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where this actually came up in practice is that while dev'ing #11596 I occasionally created corrupt tiles with data = None, and this caused failures all over where we depend on calling .data.keys()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarified over slack with Cyrus, repeating here: this doesn't represent an intent to save any tiles with {}
in the data column, this is just a something-better-than-nothing way to get null=False
on this column, and then we can we add some other layer of protection against {}
later, e.g. as a check constraint.
@@ -99,11 +81,11 @@ def __init__(self, *args, **kwargs): | |||
if isinstance(self.cardid, str): | |||
self.cardid = uuid.UUID(self.cardid) | |||
|
|||
def save(self, *args, **kwargs): | |||
def save(self, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Positional arguments to save()
were deprecated in 5.1 and will raise errors in 6.
if self.pk == self.source_identifier_id: | ||
self.source_identifier_id = None | ||
add_to_update_fields(kwargs, "source_identifier_id") | ||
super(CardModel, self).save() | ||
super(CardModel, self).save(**kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noticed we were swallowing **kwargs
in several places.
arches/app/models/models.py
Outdated
related_name="children", | ||
related_query_name="child", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively if we prefer the verbosity we could do child_nodegroups
and child_nodegroup
.
@@ -1209,8 +1193,10 @@ class Meta: | |||
|
|||
|
|||
class ResourceInstance(models.Model): | |||
resourceinstanceid = models.UUIDField(primary_key=True) | |||
graph = models.ForeignKey(GraphModel, db_column="graphid", on_delete=models.CASCADE) | |||
resourceinstanceid = models.UUIDField(primary_key=True, blank=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blank=True lets us use built-in Django model validation without tripping over fields we expect a client to leave blank and have generated on the backend.
class Meta: | ||
managed = True | ||
db_table = "resource_instances" | ||
permissions = (("no_access_to_resourceinstance", "No Access"),) | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(ResourceInstance, self).__init__(*args, **kwargs) | ||
if not self.resourceinstanceid: | ||
self.resourceinstanceid = uuid.uuid4() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved this from the bottom of the class because I sort of expect to see it up before the other methods, but if others feel different, happy to shuffle it back.
def __repr__(self): | ||
return f"<{self.graph.name}: {self.name} ({self.pk})>" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<Scheme: AAT Entries (b73e741b-46da-496c-8960-55cc1007bec4)>
related_name="children", | ||
related_query_name="child", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same decision point as above (child_tile
, child_tiles
?) Or childtile
for symmetry with parenttile
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, the other one on NodeGroup already merged in #11614. But we can change it if we want to wordsmith a bit more.
self.assertIn(str(other_resource.pk), str(mock._mock_call_args)) | ||
# delete_resources() was called with the correct resource id. | ||
self.assertEqual(other_resource.pk, mock._mock_call_args[1]["resources"].pk) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Completely unrelated, but I had this lying around and didn't want to forget about it. When I wrote this test the assertion didn't really capture the issue.
0d47957
to
8d7a260
Compare
Also stop swallowing **kwargs in some cases. Refs django/django#17667
8d7a260
to
39ec076
Compare
39ec076
to
774e857
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thanks for all of your comments @jacobtylerwalls - made the review much easier.
Types of changes
Description of Change
I found some usability improvements to make to our Django models while working on #11596, and I wanted to discuss them separately.
Issues Solved
Closes #11725
Checklist
Ticket Background
Further comments
See commit messages for descriptions