10

Is it possible to alias (My)SQL columns or SQLAlchemy object attributes in either the table's schema or the model's class definition?

For instance, given the following table:

Users
---------------------
username | ...

I would like to have the following table representation:

Users
---------------------
id | username | ...

Where User.id maps to User.username without duplicating this data.

Embedding this into the table schema would be ideal, but a solution with the ORM would be sufficient.

class User():
    __tablename__ = 'Users'
    username = Column(STRING, primary_key=True, alias='id')

For the details

My use case is that I'm storing scraped data from various websites. I'm indexing this data with the best user ID that I have, which may be a username, numeric ID, or even a full name.

However, in order to normalize operations across tables I'd like each table to have an 'id' field, mapped to the best possible ID.

Of course I have two alternatives:

  1. Renaming the selected ID as 'Users.id', losing readability for analysts.
  2. Duplicating the data from the selected ID into 'Users.id', making database write operations more complex in addition to wasting storage space.
bsuire
  • 1,383
  • 2
  • 18
  • 27
  • 1
    I think you need to give an example of what you mean. It's possible to "alias" columns, but probably not in the way that you meant it. – univerio May 24 '16 at 18:04
  • is it clearer now? But indeed, I'm not at all interested in aliasing field names inside a select query, if that's what you were refering to. – bsuire May 25 '16 at 10:10

1 Answers1

20

Here is an elegant solution described in the SQLAlchemy Docs, which does exactly what you want:

from sqlalchemy.orm import synonym
class User():
    __tablename__ = 'Users'
    username = Column(STRING, primary_key=True)
    id = synonym('username')

It works just as expected:

>>> john = session.query(User).filter_by(id='John Doe').first()
>>> print([john.id, john.username])
['John Doe', 'John Doe']
>>> john.id is john.username
True

By the way, the User class must be a subclass of SQLAlchemy declarative_base() class:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
    ...

Go to docs for further reference.

arrakis_sun
  • 556
  • 3
  • 8
  • perfect! I guess I didn't use the right keywords ("mirror" & "synonym" rather than the conflicting "alias". Otherwise I was just looking. Also, I do know about declarative_base, but thanks for pointing it out. – bsuire May 25 '16 at 17:22
  • * Otherwise I was just looking at hybrid attributes which seem like they could offer a hack way to achieve this. – bsuire May 26 '16 at 07:59
  • Kinda very manual job, but works for my requirements! – Franco Gil Nov 24 '21 at 20:44