1

I have 2 apps named social and instagram. The structure of models.py file is as follows :

In social app :

from instagram.models import User as instagramUser

class User(models.Model):
    # some fields

    class Meta:
         abstract = True

class Foo(models.Model):
    # Some fields

    def save(self, *args, **kwargs):
        # some validation on User models from instagram app (instagramUser)
        super(Foo, self).save(*args, **kwargs)

and in instagram app :

from social.models import User as socialUser

class User(socialUser):
    # Some additional fields

Conceptually this structure is correct and the model Foo should be located in social app. But as expected when running circular dependency occurs. I want to keep conceptual correctness while resolving the circular dependency. How can I do that?

mohammad
  • 2,232
  • 1
  • 18
  • 38
  • Where do you use instagramUser in social app ? – Sandeep Balagopal Nov 29 '17 at 13:30
  • # some validation on User models from instagram app – mohammad Nov 29 '17 at 13:31
  • try this https://stackoverflow.com/a/25787053/2282638 – Sandeep Balagopal Nov 29 '17 at 13:33
  • You need to be more specific. *How* are you using "validation from instagram app"? And why is it there rather than in the place you use it? – Daniel Roseman Nov 29 '17 at 13:40
  • @SandeepBalagopal following error happens : – mohammad Nov 29 '17 at 13:42
  • django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet. – mohammad Nov 29 '17 at 13:42
  • @DanielRoseman In other words I have an abstract app and a usual app. Usual app uses abstract app to implement itself. Also Abstract app needs models in usual app – mohammad Nov 29 '17 at 13:44
  • Well that isn't a thing. You need to rethink how you are doing this. An abstract class should not depend on a concrete class, that is completely backwards. (And, quite apart from this, validation shouldn't be done in the save method anyway.) – Daniel Roseman Nov 29 '17 at 13:45
  • In abstract app I have some abstarct models + some concrete models (app is not completely abstract) @DanielRoseman – mohammad Nov 29 '17 at 13:50
  • Your Foo class should only need to know about the abstract User class. Then you should define any method you're going to call on User in the User class, even if it's just an abstract method that calls `raise NotImplementedError`. That way you can actually call the method, but at runtime, since you'll have a concrete user, it'll call the actual concrete method implementation. – dirkgroten Nov 29 '17 at 13:59
  • @dirkgroten in the `User` model and `Foo` model I have username field. Validation in Foo `save` method is just checking if `foo` instance username is not present in one of instances of concrete users. How to do method you said in my case? – mohammad Nov 29 '17 at 14:05
  • 1
    if you are using instagramuser only inside 'Foo' class then, move the import statement after the 'User' class definition and before 'Foo' class. – Saji Xavier Nov 29 '17 at 14:18
  • oh, you actually need to make a query to check for uniqueness? then yes, i guess @SajiXavier solution works. – dirkgroten Nov 29 '17 at 15:42
  • wondering though if it wouldn't have been better to not make User an abstract class an make socialUser and Foo actual subclasses, that way you could have common things in User (like uniqueness of username). Note: what happens if a username that is unique is saved with Foo, but then later someone uses the same username in socialUser? – dirkgroten Nov 29 '17 at 15:44
  • am putting the circular dependency solution for any future reference. – Saji Xavier Nov 29 '17 at 18:03

1 Answers1

0

If the issue is with circular dependency, you can modify the social app to fix the issue.

class User(models.Model):
    # some fields

    class Meta:
         abstract = True

from instagram.models import User as instagramUser

class Foo(models.Model):
    # Some fields

    def save(self, *args, **kwargs):
        # some validation on User models from instagram app (instagramUser)
        super(Foo, self).save(*args, **kwargs)
Saji Xavier
  • 2,132
  • 16
  • 21