From 758b652026b7bcd4f058e9b048f0676a078a0309 Mon Sep 17 00:00:00 2001 From: rwparrish <60946750+rwparrish@users.noreply.github.com> Date: Sun, 11 Jun 2023 19:24:22 -0600 Subject: [PATCH 1/4] tables and seed data --- lib/freebies.db | Bin 20480 -> 28672 bytes ..._remove_name_column_from_freebies_table.py | 32 +++++++++++++ .../a6406e795d69_add_freebies_table.py | 38 ++++++++++++++++ ...8ab_connect_tables_has_many_to_has_many.py | 28 ++++++++++++ lib/models.py | 35 +++++++++++++- lib/seed.py | 43 +++++++++++++++++- 6 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 lib/migrations/versions/4ecf6d961128_remove_name_column_from_freebies_table.py create mode 100644 lib/migrations/versions/a6406e795d69_add_freebies_table.py create mode 100644 lib/migrations/versions/f0ede71968ab_connect_tables_has_many_to_has_many.py diff --git a/lib/freebies.db b/lib/freebies.db index 12beb1c963e832db481e7a7493e3029e691ac4dc..a047c633058316fb444b4d3f69fda1089e538b16 100644 GIT binary patch delta 459 zcmZozz}WDBae}lU7Xt$WI}o!0F(ZgQQO8)4i$O2kgO~pY11rxC27X@toqY9tQan4j zl{Yr7=3?Rh!SsD&V>u&`!B{iVQLMfxo{e2xR+h0bDk#B(l@v6%I5SfeJpDpk-Ccte{QN@{{6c+vbQFNXC8@dbd5O8H3So{x z&K{0IAi=W4oYGX7a*#lBer`cxUZrR}!W58jN@^KUWb%7HnR*b{+21cXB*+nHjY3*> zJk0iZh$;|Otl;J!BO8oRfnqp9HOK}o&CODLw*+}iQj^onQY_634UH@|DSY8a5m;oPuvx+20sq7a I3X2>B0B9wMs{jB1 delta 94 zcmZp8z}T>Wae}lUD+2=q2*UvLL>*&MRtCLzSzi7h3@m(74E((OJNfGQq&5o*EaTlQ e#dk}P$285{DB08^Db2(pd6U8yeiVU41_}U7@f6zt diff --git a/lib/migrations/versions/4ecf6d961128_remove_name_column_from_freebies_table.py b/lib/migrations/versions/4ecf6d961128_remove_name_column_from_freebies_table.py new file mode 100644 index 000000000..12c9271d6 --- /dev/null +++ b/lib/migrations/versions/4ecf6d961128_remove_name_column_from_freebies_table.py @@ -0,0 +1,32 @@ +"""remove name column from freebies table + +Revision ID: 4ecf6d961128 +Revises: f0ede71968ab +Create Date: 2023-06-11 19:13:55.598121 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '4ecf6d961128' +down_revision = 'f0ede71968ab' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('freebies', schema=None) as batch_op: + batch_op.drop_column('name') + + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('freebies', schema=None) as batch_op: + batch_op.add_column(sa.Column('name', sa.VARCHAR(), nullable=True)) + + # ### end Alembic commands ### diff --git a/lib/migrations/versions/a6406e795d69_add_freebies_table.py b/lib/migrations/versions/a6406e795d69_add_freebies_table.py new file mode 100644 index 000000000..4c4892fa9 --- /dev/null +++ b/lib/migrations/versions/a6406e795d69_add_freebies_table.py @@ -0,0 +1,38 @@ +"""add freebies table + +Revision ID: a6406e795d69 +Revises: 5f72c58bf48c +Create Date: 2023-06-11 18:43:32.597726 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'a6406e795d69' +down_revision = '5f72c58bf48c' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('freebies', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(), nullable=True), + sa.Column('item_name', sa.String(), nullable=True), + sa.Column('value', sa.Integer(), nullable=True), + sa.Column('company_id', sa.Integer(), nullable=True), + sa.Column('dev_id', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['company_id'], ['companies.id'], name=op.f('fk_freebies_company_id_companies')), + sa.ForeignKeyConstraint(['dev_id'], ['devs.id'], name=op.f('fk_freebies_dev_id_devs')), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('freebies') + # ### end Alembic commands ### diff --git a/lib/migrations/versions/f0ede71968ab_connect_tables_has_many_to_has_many.py b/lib/migrations/versions/f0ede71968ab_connect_tables_has_many_to_has_many.py new file mode 100644 index 000000000..fdec628f2 --- /dev/null +++ b/lib/migrations/versions/f0ede71968ab_connect_tables_has_many_to_has_many.py @@ -0,0 +1,28 @@ +"""connect tables has_many to has_many + +Revision ID: f0ede71968ab +Revises: a6406e795d69 +Create Date: 2023-06-11 18:57:46.065689 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'f0ede71968ab' +down_revision = 'a6406e795d69' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### diff --git a/lib/models.py b/lib/models.py index 2681bee5a..28f7e4727 100644 --- a/lib/models.py +++ b/lib/models.py @@ -1,6 +1,7 @@ from sqlalchemy import ForeignKey, Column, Integer, String, MetaData from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.associationproxy import association_proxy convention = { "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", @@ -15,15 +16,47 @@ class Company(Base): id = Column(Integer(), primary_key=True) name = Column(String()) founding_year = Column(Integer()) + + freebies = relationship('Freebie', back_populates='company', cascade='all, delete-orphan') + + # not sure I can explain this: + devs = association_proxy('freebies', 'dev', + creator=lambda dv: Freebie(dev=dv)) def __repr__(self): return f'' + class Dev(Base): __tablename__ = 'devs' id = Column(Integer(), primary_key=True) - name= Column(String()) + name = Column(String()) + + freebies = relationship('Freebie', back_populates='dev', cascade='all, delete-orphan') + # not sure I can explain this: + companies = association_proxy('freebies', 'company', + creator=lambda cpy: Freebie(company=cpy)) def __repr__(self): return f'' + + +class Freebie(Base): + __tablename__ = 'freebies' + + id = Column(Integer(), primary_key=True) + item_name = Column(String()) + value = Column(Integer()) + + company_id = Column(Integer(), ForeignKey('companies.id')) + dev_id = Column(Integer(), ForeignKey('devs.id')) + + company = relationship('Company', back_populates='freebies') + dev = relationship('Dev', back_populates='freebies') + + def __repr__(self): + return f'' + + + \ No newline at end of file diff --git a/lib/seed.py b/lib/seed.py index b16becbbb..c57573ac4 100644 --- a/lib/seed.py +++ b/lib/seed.py @@ -1,3 +1,44 @@ #!/usr/bin/env python3 +import Faker +from random import choice as rc + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker + +from models import Company, Freebie, Dev + +engine = create_engine('sqlite:///freebies.db') +Session = sessionmaker(bind=engine) +session = Session() + +fake = Faker() + + +def delete_records(): + session.query(Company).delete() + session.query(Freebie).delete() + session.query(Dev).delete() + session.commit() + +def create_records(): + companies = [Company(fake.name(), fake.random_int(min=1930, max=2023)) for i in range(20)] + freebies = [Freebie(fake.name(), fake.random_int(min=1, max=117)) for i in range(100)] + devs = [Dev(fake.name()) for i in range(50)] + session.add_all(companies + freebies + devs) + session.commit() + return companies, freebies, devs + +def relate_records(companies, freebies, devs): + for freebie in freebies: + freebie.dev = rc(devs) + freebie.company = rc(companies) + + session.add_all(freebies) + session.commit() + +if __name__ == '__main__': + delete_records() + companies, freebies, devs = create_records() + relate_records(companies, freebies, devs) + -# Script goes here! From 1b154dc1438a9356f6bbf8a99a2f4c54aa64966c Mon Sep 17 00:00:00 2001 From: rwparrish <60946750+rwparrish@users.noreply.github.com> Date: Sun, 11 Jun 2023 19:35:18 -0600 Subject: [PATCH 2/4] working seed data --- lib/freebies.db | Bin 28672 -> 28672 bytes lib/seed.py | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/freebies.db b/lib/freebies.db index a047c633058316fb444b4d3f69fda1089e538b16..9d83daf121d2d6c194dfcaa24be884bfe970e396 100644 GIT binary patch literal 28672 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 K+43HQrvC>e6i|Es delta 59 zcmZp8z}WDBae_1>*F+g-My`zsOZ1r-1U54U{NiWhWdH&Y`#=9?fq)PE69c#rV!!wS D{4EdK diff --git a/lib/seed.py b/lib/seed.py index c57573ac4..c90ab87af 100644 --- a/lib/seed.py +++ b/lib/seed.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -import Faker +from faker import Faker from random import choice as rc from sqlalchemy import create_engine @@ -21,9 +21,9 @@ def delete_records(): session.commit() def create_records(): - companies = [Company(fake.name(), fake.random_int(min=1930, max=2023)) for i in range(20)] - freebies = [Freebie(fake.name(), fake.random_int(min=1, max=117)) for i in range(100)] - devs = [Dev(fake.name()) for i in range(50)] + companies = [Company(name=fake.name(), founding_year=fake.random_int(min=1930, max=2023)) for i in range(20)] + freebies = [Freebie(item_name=fake.name(), value=fake.random_int(min=1, max=117)) for i in range(100)] + devs = [Dev(name=fake.name()) for i in range(50)] session.add_all(companies + freebies + devs) session.commit() return companies, freebies, devs From 11f64b31cfe4cf96f9031f010bfaef172927532e Mon Sep 17 00:00:00 2001 From: rwparrish <60946750+rwparrish@users.noreply.github.com> Date: Sun, 11 Jun 2023 20:51:01 -0600 Subject: [PATCH 3/4] just because --- lib/debug.py | 11 +++++++---- lib/models.py | 30 ++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/debug.py b/lib/debug.py index 4f922eb69..58da5ca0b 100644 --- a/lib/debug.py +++ b/lib/debug.py @@ -1,9 +1,12 @@ #!/usr/bin/env python3 - +from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine - -from models import Company, Dev +import ipdb +from models import Company, Dev, Freebie if __name__ == '__main__': engine = create_engine('sqlite:///freebies.db') - import ipdb; ipdb.set_trace() + Session = sessionmaker(bind=engine) + session = Session() + + ipdb.set_trace() diff --git a/lib/models.py b/lib/models.py index 28f7e4727..d7df23ef0 100644 --- a/lib/models.py +++ b/lib/models.py @@ -1,7 +1,14 @@ from sqlalchemy import ForeignKey, Column, Integer, String, MetaData -from sqlalchemy.orm import relationship, backref +from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.associationproxy import association_proxy +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +import ipdb + +engine = create_engine('sqlite:///freebies.db') +Session = sessionmaker(bind=engine) +session = Session() convention = { "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", @@ -26,6 +33,22 @@ class Company(Base): def __repr__(self): return f'' + def give_freebie(self, dev, item_name, value): + freebie = Freebie(item_name, value) + freebie.dev = dev + freebie.company = self + + @classmethod + def oldest_company(cls): + return session.query(cls).order_by(cls.founding_year).first() + # the code below was my best try - I think this has something to do with + # fine tuning the query object before execution VS grabbing all the records + # and then doing iteration... + # companies = session.query(cls) + # comp = min(companies, key=lambda x: x["founding_year"]) + # return comp + +Company.oldest_company() class Dev(Base): __tablename__ = 'devs' @@ -56,7 +79,10 @@ class Freebie(Base): dev = relationship('Dev', back_populates='freebies') def __repr__(self): - return f'' + return f'' + def print_details(self): + return f'{self.dev.name} owns a {self.item_name} from {self.company.name}' + # {dev name} owns a {freebie item_name} from {company name} \ No newline at end of file From 767306546cdffc0932df77a945b1ef4dd7cace8b Mon Sep 17 00:00:00 2001 From: rwparrish <60946750+rwparrish@users.noreply.github.com> Date: Tue, 13 Jun 2023 18:23:44 -0600 Subject: [PATCH 4/4] green baby --- lib/models.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/models.py b/lib/models.py index d7df23ef0..31335999f 100644 --- a/lib/models.py +++ b/lib/models.py @@ -48,7 +48,7 @@ def oldest_company(cls): # comp = min(companies, key=lambda x: x["founding_year"]) # return comp -Company.oldest_company() + class Dev(Base): __tablename__ = 'devs' @@ -63,6 +63,19 @@ class Dev(Base): def __repr__(self): return f'' + + def received_one(self, item_name): + dev_freebie = session.query(Freebie).filter(Freebie.dev_id == self.id, Freebie.item_name == item_name).all() + if dev_freebie: + return True + else: + return False + + def give_away(self, dev, freebie): + if self.id == freebie.dev_id: + freebie.dev_id = dev.id + + class Freebie(Base): @@ -84,5 +97,5 @@ def __repr__(self): def print_details(self): return f'{self.dev.name} owns a {self.item_name} from {self.company.name}' - # {dev name} owns a {freebie item_name} from {company name} + \ No newline at end of file