paulocheque / django-dynamic-fixture

A complete library to create dynamic model instances for testing purposes.
http://django-dynamic-fixture.readthedocs.io/
Other
391 stars 67 forks source link

Proxy models ignore lessons of their base models #157

Closed PoByBolek closed 1 year ago

PoByBolek commented 1 year ago

In the Django docs it sounds like proxy models and regular models are basically equivalent when it comes to database access. The proxy models just add extra methods or managers that the regular models don't have.

Based on this I was also expecting that DDF reuses the lessons for concrete models for any proxy models they might have. But this doesn't seem to be the case 😞

G()etting a proxy model works just fine, but DDF ignores any lessons that I have taught for the concrete base model.

### models.py
from django.db import models

class Thing(models.Model):
    value = models.IntegerField()

class ProxyThing(Thing):
    class Meta:
        proxy = True

### tests.py
from django.test import TestCase
from django_dynamic_fixture import G, teach

from demo.models import ProxyThing, Thing

teach(Thing, value=1234)

class ProxyThingTest(TestCase):
    def test_stuff(self):
        self.assertEqual(1234, G(ProxyThing).value)

When I run the tests using python manage.py test, the test fails:

Found 1 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F
======================================================================
FAIL: test_stuff (demo.tests.ThingTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\demo\proxy-lessons\tests.py", line 13, in test_stuff
    self.assertEqual(1234, proxy.value)
AssertionError: 1234 != 1

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (failures=1)
Destroying test database for alias 'default'...

I currently work aroung this by specifically copying the lessons for proxy models from their concrete base models. But it would be nicer if DDF supported this out of the box 😸. Maybe if DDFLibrary.get_configuration() and DDFLibrary.add_configuration() checked for proxy models themselves?

from django.apps import apps
from django_dynamic_fixture import DDFLibrary

def _copy_lessons_for_proxy_models():
    library = DDFLibrary.get_instance()

    for model in apps.get_models():
        concrete_model = model._meta.concrete_model
        if not model._meta.proxy or not concrete_model or concrete_model == model:
            continue

        config = library.get_configuration(concrete_model)
        if config:
            library.add_configuration(model, config)
paulocheque commented 1 year ago

Nice catch! Would you have time to create a PR for this? I cleaned up the code for the new 4.0.0 version, removing compatibility of old Python/Django versions. That should help contributions.

PoByBolek commented 1 year ago

Seems like I do: #161

paulocheque commented 1 year ago

Awesome!