On 09/06/2016 11:12 AM, TomS. wrote:
Hi,

In my model I am not allowed to use FK. I've been trying to figure out
how one to many/many to one relationship should be properly defined or
in which class to be sure that it works as expected. I've recently used
very similar example - here it is:

class DepTest(db.Model):

    __tablename__ = u'deptest'
    __bind_key__ = u'section'

    department_pk_id = db.Column(db.Integer, primary_key=True)
    department_id = db.Column(db.Integer)
    department_name = db.Column(db.String(1000))

    # @declared_attr
    # def ppl(clss):
    #     return relationship(u'Level1',
    # primaryjoin=u'and_(Level1.department_id==DepTest.department_id,'
    #                                     u'
Level1.person_include_flag==1)',
    #                         foreign_keys=[clss.department_id],
    #                         backref=u'department')


class PPLTest(db.Model):

    __abstract__ = True

    person_pk_id = db.Column(db.Integer, primary_key=True)
    person_name = db.Column(db.String(1000))
    person_surname = db.Column(db.String(1000))
    person_include_flag = db.Column(db.Integer)
    department_id = db.Column(db.Integer)

    @hybrid_property
    def person_name_surname(self):
        return self.person_name + u' ' + self.person_surname


class Level1(PPLTest):

    __tablename__ = u'ppl_level1'
    __bind_key__ = u'section'

    # @declared_attr
    # def department(clss):
    #     return relationship(u'DepTest',
    # primaryjoin=u'and_(Level1.department_id==DepTest.department_id,'
    #                                     u'
Level1.person_include_flag==1)',
    #                         foreign_keys=[clss.department_id],
    #                         backref=u'ppl')

I am looking for the comprehensive answer to be sure that result is not
coincidental.

If @declared_attr part in DepTest is uncommented (while in Level1 is
commented), I get only one person/scalar (although there are more ppl)
after running:

q = DepTest.query.all()
print q[0].ppl

and list here:

q = Level1.query.all()
print q[1].department

In case if @declared_attr part in Level1 is uncommented (while in
DepTest is commented) it behaves according to my intentions:

# list
q = DepTest.query.all()
print q[0].ppl

# scalar
q = Level1.query.all()
print q[1].department

In docs the difference between 1 to many, many to 1 depends on (if I
understand it correctly) in which class ForeignKey is defined (because
usage of backref creates bidirectional behaviour). So what is the rule
in the cases without FK? Should @declared_attr be put in class which
represents "many" entities (thus get ppl as a list).

to reduce confusion I'd use the foreign() annotation in the primary join directly:

@declared_attr
def department(clss):
        return relationship(
                u'DepTest',
                
primaryjoin=u'and_(foreign(Level1.department_id)==DepTest.department_id,'
                u'Level1.person_include_flag==1)',
        backref=u'ppl')


the reason you're getting opposite results is because you're setting foreign_keys to "clss.department_id" on both sides, which has the opposite meaning. In this case, you indicate you would have the FOREIGN KEY constraint on Level1.department_id. So on DepTest you'd need to have "foreign_keys="Level1.department_id" as well.

Also because you are using backref, you should only use one or the other of these relationships - using both will create a collision as backref is already building a second relationship.





Any links to doc, info would be very helpful.


--
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to