2

I can't seem to figure out how to import two classes to each other. When running the application it simply says

  from room import Room
ImportError: cannot import name Room

It might be a design problem but I don't think there's another way to reference the two classes, so this needs to be as it is. The only reason the imports are needed is because they are required by the redisco module in the objects (they need to know the types)

#Room class.

class Room(models.Model):
    from player import Player
    players = models.ListField(Player, required = True)

#Player class
class Player(models.Model):
    from room import Room
    room = models.ReferenceField(Room, required = True)

How do I get this to work?

E:

The framework is Redisco (Redis)

chrs
  • 5,906
  • 10
  • 43
  • 74
  • 2
    Solution: put them in the same file. – nbro Dec 29 '14 at 18:55
  • Does ReferenceField accept a string instead of an object? At least SQLAlchemy does. @nbro: That's a dirty workaround. – ThiefMaster Dec 29 '14 at 18:55
  • You mean you want a *backreference* here? – Martijn Pieters Dec 29 '14 at 18:55
  • @ThiefMaster It's probably also fast. If also both classes are really related to need one another, it would also be the best solution – nbro Dec 29 '14 at 18:56
  • What framework is this? Are you using Django perhaps? – Martijn Pieters Dec 29 '14 at 18:56
  • Putting them in the same file is really a no go sorry. This is redisco (redis) so yes you can store ints, strings etc etc. It's just easier to work with references rather than querying all the time. I don't know what a backreference is sorry. – chrs Dec 29 '14 at 19:01
  • Move the imports out of the class definitions. If they're in the same file you only need one before the first class referencing `Room`. – martineau Dec 29 '14 at 20:09

4 Answers4

2

Most ORM models either support back references (where the target model of a reference field is given an extra attribute that points back to the referencing object), and / or lets you specify relationships through other means.

Redisco doesn't have back-references that I could discover, but it does support string references. If you pass in a string it'll be interpreted as a model name, matched against the __name__ attribute:

class Room(models.Model):
    players = models.ListField('Player', required = True)

This neatly bypasses the import problem altogether.

From the ListField docstring:

target_type -- can be a Python object or a redisco model class.

If target_type is not a redisco model class, the target_type should also a callable that casts the (string) value of a list element into target_type. E.g. str, unicode, int, float.

ListField also accepts a string that refers to a redisco model.

The code to resolve the name uses the function get_model_from_key() to resolve the string, which simply searches through all subclasses of models.Model, matching on __name__.

It'll resolve the name when validating new values or when retrieving existing values for the first time, by which time the Player subclass has already been imported.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

If they are in the same .py file then you don't need imports. If they are in different files in the same directory just use 'import room' (assuming its in a file called 'room.py'). If they are in separate files in separate directories you will need to use the imp module.

import imp
roomClass = imp.load_source('roomClass', [Path to room.py])

Then it can be called with something like:

aRoom = roomClass.Room(Model)
Jacobr365
  • 846
  • 11
  • 24
  • 2
    Depending on the framework, there are better ways to handle this; SQLAlchemy for example takes **string references**. – Martijn Pieters Dec 29 '14 at 19:02
  • Following the imp way it results in the same error I suspect the original way did. Infinit recursion: RuntimeError: maximum recursion depth exceeded while calling a Python object – chrs Dec 29 '14 at 19:15
0

First of all if you want to import a module to your program, they must be in the same directory.

Follow this for importing modules ;

from filename import classname

Which is the filename= your .py file that you want to import class

class is the specific class that you want to use.

Or;

from filename import *

Which is going to add all functions and classes.

Also check this topic. program is running fine but cannot being import with IndexError

Community
  • 1
  • 1
GLHF
  • 3,835
  • 10
  • 38
  • 83
-1

You can reference to this problem.

Pythonic way to resolve circular import statements?

Using import rather than from [...] import [...]

Community
  • 1
  • 1
BigTailWolf
  • 1,028
  • 6
  • 17