Repository: django-money/django-money (Python)

Issue:
Regression in 3.5 - AttributeError: type object 'Meta' has no attribute 'model'
Looks to be caused by https://github.com/django-money/django-money/pull/722.

Django - 4.2.11
DRF - 3.14.0

```
  File "/Users/phillip/Library/Caches/pypoetry/virtualenvs/shipwell-backend-core-cpwchxt0-py3.11/lib/python3.11/site-packages/rest_framework/serializers.py", line 426, in run_validation
    value = self.to_internal_value(data)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/phillip/Library/Caches/pypoetry/virtualenvs/shipwell-backend-core-cpwchxt0-py3.11/lib/python3.11/site-packages/rest_framework/serializers.py", line 481, in to_internal_value
    primitive_value = field.get_value(data)
                      ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/phillip/Library/Caches/pypoetry/virtualenvs/shipwell-backend-core-cpwchxt0-py3.11/lib/python3.11/site-packages/djmoney/contrib/django_rest_framework/fields.py", line 70, in get_value
    model_meta = self.parent.Meta.model._meta
                 ^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'Meta' has no attribute 'model'
```

I think this is an edge case when using a `MoneyField` with a `Meta` and outside of a `ModelSerializer`. `ModelSerializer` is the only case where a `model` is used in DRF.

This should be the reproduction case:

```python
class NonModelSerializer(serializers.Serializer):
    invoice_amount = MoneyField(
        max_digits=constants.DIGIT_SIZE_10,
        decimal_places=constants.DIGIT_SIZE_2,
        required=False,
        allow_null=True,
    )

    class Meta:
        fields = (
            "invoice_amount"
        )
```


Discussion:
The fix should be pretty easy by gating both `self.parent.Meta` and `self.parent.Meta.model`.
Makes sense, and sorry about the regression. Seems that despite the test coverage, it's actually hard to change this code much.

I don't use DRF, so I hope that someone else will fix this. Would be happy to do a patch release.
And thanks for reporting so quickly :+1: 
@benjaoming loved how easy it was to contribute!! Candidate fix at #758.
Nice to avoid this crashing with a simple change, but is a Meta class outside of using a model serializer even valid/meaningful code in drf? Is it not only used to define how to auto-generate a serailizer class from a model?
> but is a Meta class outside of using a model serializer even valid/meaningful code in drf

@stianjensen yes, there are multiple examples from the DRF docs like [multi-field validators](https://www.django-rest-framework.org/api-guide/serializers/#validators).

Also consider inheritance, where maybe a parent serializer class declares some fields as read only and a subclass declares them as not (or vice-versa).



Patch:
diff --git a/djmoney/contrib/django_rest_framework/fields.py b/djmoney/contrib/django_rest_framework/fields.py
index d196bfbb6..44f4e23ef 100644
--- a/djmoney/contrib/django_rest_framework/fields.py
+++ b/djmoney/contrib/django_rest_framework/fields.py
@@ -66,7 +66,9 @@ def to_internal_value(self, data):
 
     def get_value(self, data):
         default_currency = None
-        if hasattr(self.parent, "Meta"):
+        parent_meta = getattr(self.parent, "Meta", None)
+
+        if parent_meta and hasattr(parent_meta, "model"):
             model_meta = self.parent.Meta.model._meta
             field = model_meta.get_field(self.field_name)
             default_currency = field.default_currency


Test patch:
diff --git a/tests/contrib/test_django_rest_framework.py b/tests/contrib/test_django_rest_framework.py
index ca2e86430..30685efe1 100644
--- a/tests/contrib/test_django_rest_framework.py
+++ b/tests/contrib/test_django_rest_framework.py
@@ -261,3 +261,15 @@ class Meta:
         else:
             assert not serializer.is_valid()
             assert serializer.errors["second_money"][0] == "Ensure this value is greater than or equal to 0."
+
+    def test_no_model_serializer(self):
+        from djmoney.contrib.django_rest_framework import MoneyField
+
+        class NormalSerializer(serializers.Serializer):
+            the_money = MoneyField(decimal_places=2, max_digits=10, min_value=0)
+
+            class Meta:
+                fields = ("the_money",)
+
+        serializer = NormalSerializer(data={"the_money": "0.01", "the_money_currency": "EUR"})
+        assert serializer.is_valid()