-
Notifications
You must be signed in to change notification settings - Fork 28
Fix EmbeddedModelField crash when retrieving model where field name isn't present in db data #407
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
Conversation
Please give complete steps to reproduce the issue, including the traceback. Logically, it seems incorrect that adding |
Not all documents contain a fixed format, sometimes there is no need to specify a field. Django does not know how to support this, because it was created for relational databases. This implementation can partially eliminate the need for this. I agree that blank is not suitable for this idea. Perhaps you need to come up with another parameter for this solution, for example, void=True |
What does your model look like? |
|
Got it. We've been considering whether or not to try to support this sort of sparse data that wasn't written by Django. We've identified some other problems in passing (#275, #401) but it's unclear that supporting this use case is worth it. Writing rigorous tests for sparse data would be a large effort. |
Definitely needed. Mongo is non-relational database for a reason |
I'm guessing the exception is similar to this:
(where "num" is a field of Thus a suitable patch might be: diff --git a/django_mongodb_backend/operations.py b/django_mongodb_backend/operations.py
index 4b494c3..6d4f033 100644
--- a/django_mongodb_backend/operations.py
+++ b/django_mongodb_backend/operations.py
@@ -189,7 +189,8 @@ class DatabaseOperations(GISOperations, BaseDatabaseOperations):
field_expr
) + field_expr.get_db_converters(connection)
for converter in converters:
- value[field.attname] = converter(value[field.attname], field_expr, connection)
+ if field.attname in value:
+ value[field.attname] = converter(value[field.attname], field_expr, connection)
return value
def convert_jsonfield_value(self, value, expression, connection): I gather that you're trying to build a Django application with some data that Django didn't write. Is it otherwise going okay? |
That's right, it's a type of error. In principle, this option can also work, but I would move the condition outside the loop, as there will be unnecessary empty iterations in the loop. However, I don't think this is a good solution, as not everyone expects this behavior, and many follow a strict pattern, which would prevent the error. |
All the data that Django writes expects converters to run. If converters don't run, field data will be in an unexpected time (e.g. DateField values will be datetime rather than date, DecimalField will be Decimal128 rather than Decimal). This is why your proposed solution of checking |
I agree with blank=True that it is incorrect to specify it, but your decision is also incorrect. I think the best solution would be to inherit from 'from django.db.models.fields import Field' and add a new attribute to solve the problem |
As I explained, by disabling an embedded model field's converters, you're going to break those fields. Instead, for example, if you want a version of DecimalField that uses Decimal128 instead of Decimal, you'll instead want to write a custom field (Decimal128Field) and use that on your embedded model. Nonetheless, you can implement your own custom embedded model field if you believe your proposed solution is suitable for your project. |
I'm not talking about converters, I'm talking about:
Not everyone expects this behavior, and many follow a strict schema of the model. |
Please check if #409 solves your issue. If not, you'll need to explain a bit more. I'm not sure what a "strict schema of the model" means. The lines you quoted is where database converters are run on each embedded model field. These cannot be disabled if a field has any data, otherwise the data won't be converted as required (e.g. an EmbeddedModel's DecimalField value would be loaded as Decimal128 instead of Decimal). |
This solution is suitable for me, BUT: |
The idea of the fix is to avoid running converters on fields that aren't in the data. I'm not sure why this is unclear or why you think this approach may result in some other error. |
I'm not talking about converters. |
Hey, @ddrondo thanks for taking the time to point out this issue. I want to specifically address your concern here:
I don't think this will be an error folks run into as there's two primary ways for data to appear in the database. Let's walk through the cases: If someone needs to maintain rigid schema, they should be enforcing & providing default values through the ORM. 2. Data provided externally and used by the ORM In both of these cases, the fix @timgraham provided does not introduce a new or unexpected regression. If anything, it maintains that if a field returns as a Below is an example of what happens when a field is not present.
See above that we no longer crash on missing key retrieval. The only time an error would occur is if iterating on a |
(The conversation can continue if need be, but the problem should addressed by #409.) |
If the field is embedded and empty, it gave an error about the absence of this field.