#26 define foreign keys in Style

closed-out-of-date
None
5
2007-02-22
2005-11-11
Pau Aliagas
No

I don't like to use attrID all along the code to access related tables, I want to be able use the nomeclature I like taking advantage of the nice Style idea. This is especially true when you create RelatedJoins when you use a nomeclature like I do (table.id_table), but it's the same for all the nomeclatures you can imagine.

In styles.py it warns:

def instanceAttrToIDAttr(self, attr):
# @@: Right now, because of how names are created for foreign
# keys, you can't really change this style.
return attr + "ID"

With this patch you can define how you want the foreign keys generated, they won't be mandatorily generated as attrID.

Example:

class LongStyle(Style):
"""
This style is derived from Style, that does not do any translation,
but constructs the table ids like id_table.
"""
def instanceAttrToIDAttr(self, attr):
return "id_" + attr

def tableReference(self, table):
# str.rsplit is python 2.4+ only
if version_info >= (2, 4):
return "id_" + table.rsplit(".", 1)[-1]
else:
return "id_" + rsplit(table, ".", 1)[-1]

class mm_server(SQLObject):
class sqlmeta:
table = "smsarena.mm_server"
style = LongStyle(longID = True)
_connection = conn_smsarena
server = StringCol(alternateID = True, varchar = True, length = 255, alternateMethodName = "by_server")
tz = StringCol(length = 20, default = 'CET', notNone = True)
conutry_code = StringCol(length = 2, varchar = False, default = '', notNone = True)
# until now I had to do this
# mm_server_aliases = SQLMultipleJoin("mm_server_alias", joinColumn = "mm_serverID", orderBy = "server")
# now it's perfect!
mm_server_aliases = SQLMultipleJoin("mm_server_alias", orderBy = "server")

class mm_server_alias(SQLObject):
class sqlmeta:
table = "smsarena.mm_server_alias"
style = LongStyle(longID = True)
_connection = conn_smsarena
# until now I had to do this
# mm_server = ForeignKey("mm_server", dbName = "id_mm_server")
mm_server = ForeignKey("mm_server")
server = StringCol(alternateID = True, varchar = True, length = 255, alternateMethodName = "by_server")

I hope it's clear :)

Pau

Discussion

<< < 1 2 (Page 2 of 2)
  • Pau Aliagas

    Pau Aliagas - 2006-02-17
    • status: open-accepted --> open-invalid
     
  • Pau Aliagas

    Pau Aliagas - 2006-02-17

    Logged In: YES
    user_id=140558

    Ok, another test mistery solved:

    This is the culprit that test_SQLMultipleJoin.py fails:
    assert str(hibrid.fightersAsSResult.sum('power')) == '23'

    In pgsql hibrid.fightersAsSResult.sum('power') returns 23.
    In sqlite-3.1.2 and mysql-4.1 it returns 23.0.

    So we should either fix the test or the sum function.
    Fixing the test could be as easy as casting the float to int:
    assert str(int(hibrid.fightersAsSResult.sum('power'))) == '23'

    but I'mn not sure if this would hide a bug. Should sum
    return float or int?

     
  • Oleg Broytman

    Oleg Broytman - 2006-02-17
    • status: open-invalid --> open-accepted
     
  • Oleg Broytman

    Oleg Broytman - 2006-02-17

    Logged In: YES
    user_id=4799

    SUM() should return whtaver the DB returns. I think summing
    an INT column returns an int, summing a FLOAT column returns
    a float.

     
  • Pau Aliagas

    Pau Aliagas - 2006-02-17

    Logged In: YES
    user_id=140558

    Answering your concerns about the API...

    The only change is the one I have explained when using
    addColumn(fieldID, ForeignKey..). If you put ID, the current
    default style rules would add it too, so you'd get fieldIDID.
    We could change the style rules and look at this case, but I
    think that the current behaviour (as it is now with the
    patch) is completly orthogonal and always acts the same way,
    no black magic required.

    For the rest this is a HUGE addition!! You don't need to
    worry anymore about namning styles, nothing is written in
    stone. the ID thing was everywhere in the code

    Combined with the other patch (select using the object, not
    the id), you can almost always avoid referring directly to
    foreign field names.

    I really feel much more comfortable with these changes
    applied, seeign fieldID in the code maed me feel that
    something was not competely right. Avoiding it makes the
    code look beautiful.

     
  • Pau Aliagas

    Pau Aliagas - 2006-02-17
    • status: open-accepted --> open-invalid
     
  • Oleg Broytman

    Oleg Broytman - 2006-02-17
    • status: open-invalid --> closed-accepted
     
  • Oleg Broytman

    Oleg Broytman - 2006-02-17

    Logged In: YES
    user_id=4799

    Even that's a big change, too big for 0.7 bugfix.

    Don't hesitate to post patches or at least bug reports for
    other issues.

     
  • Pau Aliagas

    Pau Aliagas - 2006-02-17

    Logged In: YES
    user_id=140558

    This can be solve with a onliner in default style:
    if not name.endswith("ID")...

    IMHO doing addColumn(fieldID, ForeignKey..) is a mistake
    You should do addColumn(field, ForeignKey..) and style takes
    care of it.

    If you want I can submit this oneliner for 0.7 only and you
    reconsider ading it to 0.7.

     
  • Oleg Broytman

    Oleg Broytman - 2006-02-17
    • status: closed-accepted --> open
     
  • Oleg Broytman

    Oleg Broytman - 2006-02-17

    Logged In: YES
    user_id=4799

    Please do. I reopened the patch.

    Instead of one-line patch for Style IWBN to make a smaller
    (than the original) patch that avoids patching .addColumn()
    in tests, isn't it?

     
  • Pau Aliagas

    Pau Aliagas - 2006-02-17

    Logged In: YES
    user_id=140558

    Ok, this is the patch for keeping the exact behaviour in 0.7.
    For 0.7, as you say, don't patch the tests.

    Please do not apply it to 0.8 :)

     
  • Oleg Broytman

    Oleg Broytman - 2006-02-20

    Logged In: YES
    user_id=4799

    Doesn't work in 0.7. First, you've mixed tabs and spaces and
    used the name 's' instead of 'attr'. These two are easy to fix.

    But unpatched test_auto.py and test_auto_old.py fail:

    def test_dynamicJoin(self):
    col = KeyCol('oldPersonID', foreignKey='OldPerson')
    OldPhone.addColumn(col, changeSchema=True)
    join = MultipleJoin('OldPhone')
    OldPerson.addJoin(join)
    for phone in OldPhone.select('all'):
    if phone.phone.startswith('555'):
    phone.oldPerson =
    OldPerson.selectBy(name='tim')[0]
    else:
    phone.oldPerson =
    OldPerson.selectBy(name='bob')[0]
    l = [p.phone for p in
    OldPerson.selectBy(name='tim')[0].oldPhones]
    l.sort()
    E assert l == ['555-394-2930', '555-555-5555']
    > assert [] == ['555-394-2930', '555-555-5555']

    You can work on it further. Or you can abandon it and it
    will not be applied in 0.7 branch.

     
  • Oleg Broytman

    Oleg Broytman - 2007-02-22
    • status: open --> closed-out-of-date
     
<< < 1 2 (Page 2 of 2)

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks