Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do you deal with circular imports ? #59

Closed
askz opened this issue Jun 30, 2017 · 6 comments
Closed

How do you deal with circular imports ? #59

askz opened this issue Jun 30, 2017 · 6 comments
Labels

Comments

@askz
Copy link
Contributor

askz commented Jun 30, 2017

For example I have models like this :

# modules/patients/models.py
class Patient(db.Model, OwnerMixin):	
	__owner_backref_name__ = "patients"

	id = db.Column(db.Integer, primary_key=True)

	phone = db.Column(db.String)
	email = db.Column(db.String)
	first_name = db.Column(db.String)
	last_name = db.Column(db.String)
	birthday = db.Column(db.DateTime)
	zip_code = db.Column(db.String)
	address = db.Column(db.String)

        # I would like to do this, but there's circular import....
       @aggregated('claims', db.Column(db.Integer))
	def unpaid_amount(self):
		return db.func.count('1')

# modules/accounting/models.py
class Claim(db.Model, OwnerMixin):
	__owner_backref_name__ = 'claims'

	id = db.Column(db.Integer, primary_key=True)

	date = db.Column(db.DateTime, nullable=False)
	label = db.Column(db.String, nullable=False)
	amount = db.Column(db.Float, nullable=False)
	ref = db.Column(db.String)	

	patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False)
	patient = db.relationship(
				Patient,
				backref=db.backref('claims', cascade="delete, delete-orphan")
	)

Patient is in dedicated module "patient"
and claim model is in 'accounting' modules with other models related to accounting.
The problem is I can't import claim model and I can't access to claim model in patient model in order to, for example, make the sum of claims amount.
I think this is some design issue, but I want to be sure if there's any workaround before rewriting....

@khorolets
Copy link
Collaborator

Hi!

In the example of @aggregated models are in the same file.

I'd try something like this http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.count in the query.

Probably @frol could suggest something more useful.

@frol
Copy link
Owner

frol commented Jun 30, 2017

I am not completely sure I got your question, but here are some ideas:

  1. You can pass a string as a first argument to the db.relationship (instead of the class object)
  2. The general approach to workaround circular dependency is to import inside a function.

@askz
Copy link
Contributor Author

askz commented Jun 30, 2017

Thanks for the quick answers.

Sorry for the missing examples.
Here it is :

@aggregated('unpaid_consultations', db.Column(db.Integer))
	def unpaid_consultations_count(self):
		return db.func.count(Patient.unpaid_consultations)
	
	unpaid_consultations = db.relationship(
		'Claim',
		primaryjoin=
				'and_(Claim.patient_id == Patient.id, Claim.invoice_id.is_(None))',
		viewonly=True
	)

This is actually working really fine.

I would like to be able to have maybe aggregate like this :

	@aggregated('unpaid_consultations', db.Column(db.Integer))
	def unpaid_sum(self):
		return db.func.sum('amount').label('unpaid_sum')

To return the sum of the amount column select by the above relationship...
I know I'm mixing things here but this is for the example.

(I know this isn't related to this project directly, I appreciate your help!)

@askz
Copy link
Contributor Author

askz commented Jun 30, 2017

In fact my query is something like :

 SELECT SUM(amount) FROM claim WHERE patient_id = %d AND invoice_id IS NOT NULL;

@khorolets
Copy link
Collaborator

@askz And what about @frol's advice about providing related model as string without importing it? Didn't it help?

patient = db.relationship(
    'Patient',
    backref=db.backref('claims', cascade="delete, delete-orphan")
)

@frol should it work?

@askz
Copy link
Contributor Author

askz commented Jun 30, 2017

Yes this is what I've been up these last minutes.
Many thanks. I resolved it with this solution plus :

	@aggregated('claims', db.Column(db.Integer))
	def unpaid_sum(self):
		return db.func.sum(Claim.amount)

@askz askz closed this as completed Jun 30, 2017
@frol frol added the question label Dec 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants