-
Notifications
You must be signed in to change notification settings - Fork 0
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
schema checks and unit tests. #3
base: embedded-model-field
Are you sure you want to change the base?
schema checks and unit tests. #3
Conversation
e2947b8
to
dd65bb7
Compare
a752b20
to
9a8ffd5
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.
Sorry for the delay in looking at this. Let's focus on the field validation (first commit) and move the querying bits to another PR.
@@ -82,18 +92,10 @@ def test_pre_save(self): | |||
self.assertEqual(obj.simple.auto_now_add, auto_now_add) | |||
self.assertGreater(obj.simple.auto_now, auto_now_two) | |||
|
|||
def test_foreign_key_in_embedded_object(self): |
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.
Why the deleted test?
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.
Inside of embedded object we cannot have foreign keys, If we want to support it, I think I have to add some validations in the try_transform. Maybe we have to raise an exception ?
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 agree; Let's raise an exception for now if a foreignkey is placed inside an embedded object. Otherwise, devs may try and it will fail.
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.
The new test expects an exception. 😄
@@ -35,11 +35,12 @@ class DecimalParent(models.Model): | |||
|
|||
class EmbeddedModelFieldModel(models.Model): | |||
simple = EmbeddedModelField("EmbeddedModel", null=True, blank=True) | |||
decimal_parent = EmbeddedModelField(DecimalParent, null=True, blank=True) | |||
decimal_parent = EmbeddedModelField(DecimalKey, null=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.
Why the change?
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.
Foreign key aren't supported in embedded fields, So I decided to change this fields. (Decimal parent has a FK to another table)
|
||
|
||
class KeyTransformFactory: | ||
def __init__(self, key_name): | ||
def __init__(self, key_name, ref_field=None): |
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.
Should ref_field
be a required arg?
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.
🤔 let me check, but I think you are right, I made some change in refactor to avoid nullability in ref_field.
bf71f56
to
86ac26a
Compare
I reorder the commits to have the first 5 for validation and the other 2 for testing. |
86ac26a
to
2d75b39
Compare
dd65bb7
to
62cafa8
Compare
2d75b39
to
4da45f2
Compare
I rebased embedded-model-field branch on main, so if you rebase your branch on that, it should fix the issue. |
4da45f2
to
d6f7812
Compare
Refresh my memory... we can't support foreign key because of the double underscore lookup syntax collision, correct? In that case, I'm wondering if we'll need to revisit how we do querying in order to allow foreign key (even if it's a future task) in embedded documents. (I'm not sure whether or not we need to support it... have to check with Jib + team.) |
🤔 Yes, the problem is when Django interprets the query. The setup_joins function handles it, but it always treats the I don’t know if we can define a foreign key as a field in a JSONField. I don’t think so, but if it’s possible, we should take a look. |
No foreign key in JSON. It's always just "data." See Djongo's EmbeddedField API for an alternate query syntax we could consider. |
🤔 This changes things a bit, I didn’t know this kind of syntax existed 😬. I have two questions: In Django, filtering usually works with an argument structured as column_field + lookup, and the value is just the value to filter by. But here, we have a mixed approach where the value part includes both field + value, while the argument name is embedded_field + lookup. Is that correct? entries = Entry.objects.filter(embedded_field__foreign_field__name__startswith={'name': 'Beatles'}) |
I don't think it needs to be supported as I'd rather we remove any opportunities to promote the |
What would be a use-case you'd imagine? If someone is using an EmbeddedModel in a JSONField that feels counterintuitive. I'm all for not supporting this usecase if it's too much work; work has already been done to support it, but if it's creating complications, you can take out the requirement. If someone is using EmbeddedField with JSONField, I'm hard-pressed to understand if that's worthwhile. |
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.
Added some comments. I haven't reviewed all the test cases yet, but will come back to it today. :)
@staticmethod | ||
def _validate_embedded_field(_, model): |
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 don't think this needs to be a static method since you're only ever calling the instanced self
version of the function.
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.
Don't worry about this functionality. I'm instead going to amend my PR to use the same system check approach that ArrayField uses to disallow relational fields.
msg = "Address has no field named 'president'" | ||
with self.assertRaisesMessage(FieldDoesNotExist, msg): | ||
Book.objects.filter(author__address__city__president="NYC") |
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.
shouldn't this be city has no field name president?
or address has no field named city.president?
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 think you are right. I will check this out.
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 used "Address.city has no field named 'president'"
if you don't like it, let me know is a easy change
@@ -229,3 +242,62 @@ def test_ordering_grouping_by_sum(self): | |||
.order_by("sum") | |||
) | |||
self.assertQuerySetEqual(qs, [0, 2, 4, 6, 8, 10], operator.itemgetter("sum")) | |||
|
|||
|
|||
class SubqueryExistsTestCase(TestCase): |
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.
TestCase -> Tests (a TestCase is a base class that's meant to be inherited)
@staticmethod | ||
def _validate_embedded_field(_, model): |
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.
Don't worry about this functionality. I'm instead going to amend my PR to use the same system check approach that ArrayField uses to disallow relational fields.
I agree, the use case is unusual, and maybe we should suggest avoiding it. But as long as the embedded fields are fully typed, the user might have a reason for wanting semi-structured data inside embedded field. |
I added the schema checks in get_transform, I didn't find any other place to put it.
The code got a bit dirty if we use embedded field with jsonfield. This use case is strange but possible.
I couldn't find any other way to do this task without breaking JSON.