Michel Rugenbrink
Michel Rugenbrink

Reputation: 446

Natural Key causes Django tests to fail

Consider a clean django 1.7.7 project with one app called testrunner.

The models look like this:

class Contact(AbstractBaseUser, PermissionsMixin, models.Model):
    relation = models.ForeignKey('tests.Relation', related_name='contacts')
    username = models.CharField(max_length=200, unique=True)
    first_name = models.CharField(max_length=30, null=True, blank=True)
    last_name = models.CharField(max_length=30, null=True, blank=True)
    email = models.EmailField(null=True, blank=True, unique=True)

    is_staff = models.BooleanField('staff status', default=False,
                                   help_text='Designates whether the user can log into this admin site.')
    is_active = models.BooleanField('active', default=True,
                                    help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.')

    USERNAME_FIELD = 'username'

    def get_full_name(self):
        pass

    def get_short_name(self):
        pass

    def get_name(self):
        pass

class Relation(models.Model):
    name = models.CharField(max_length=200, unique=True)
    created_by = models.ForeignKey('tests.Contact', null=True, related_name='created_%(class)s')
    modified_by = models.ForeignKey('tests.Contact', null=True, related_name='modified_%(class)s')

    def natural_key(self):
        return (self.name,)

In the settings.py I've set 'tests.Contact' to by the AUTH_USER_MODEL.

This setup is a clean test to replicate the error I get within a larger environment. The problem is that I cannot run the django tests without it failing on the creation of the test database:

manage.py test
Testing started at 14:39 ...
Creating test database for alias 'default'...
CommandError: Can't resolve dependencies for tests.Contact, admin.LogEntry, tests.Relation in serialized app list.

Process finished with exit code 1
Empty test suite.

When I remove the def natural_key(self) from the Relation model everything works fine. We would like to use the natural_key on the Relation model for our fixtures, but are unable to get it to work with django tests.

What am I doing wrong?

Upvotes: 2

Views: 507

Answers (2)

Matthijs Kooijman
Matthijs Kooijman

Reputation: 2795

The problem here is a circular dependency involving natural keys that Django fails to handle properly. Since this post was made, the loading of such data was already much improved, but serialization still breaks on a (now pretty obsolete) check for circular dependencies.

This is an open bug and reported here: https://code.djangoproject.com/ticket/31051

Upvotes: 0

eldar
eldar

Reputation: 195

A very simple solution, yet took me some time to come up with.

tl;dr

  • Dynamically import serializers.
  • Dynamically define natural_keys method & assign to model.

def method_where_serializers_is_being_used():
    # import serlializers
    from django.core import serializers
    
    # define natural_key method
    def natural_key(self):
        return some_unique_id

    DjangoModel.natural_key = natural_key  

It's a kind of a hack, but its working fine

Upvotes: 2

Related Questions