From db9495d9bac9445388f4d729202b9ff7d6e55ba4 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Mon, 7 Aug 2023 11:29:03 -0700 Subject: [PATCH 1/5] create db, all three tables --- lib/debug.py | 5 ++- lib/freebies.db | Bin 20480 -> 24576 bytes .../versions/ee5b1e0f4931_create_freebies.py | 38 ++++++++++++++++++ lib/models.py | 25 +++++++++++- lib/seed.py | 38 +++++++++++++++++- lib/seed_db.db | 0 6 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 lib/migrations/versions/ee5b1e0f4931_create_freebies.py create mode 100644 lib/seed_db.db diff --git a/lib/debug.py b/lib/debug.py index 4f922eb69..9f85f7b32 100644 --- a/lib/debug.py +++ b/lib/debug.py @@ -1,9 +1,12 @@ #!/usr/bin/env python3 from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker -from models import Company, Dev +from models import Company, Dev, Freebie if __name__ == '__main__': engine = create_engine('sqlite:///freebies.db') + Session = sessionmaker(bind=engine) + session = Session() import ipdb; ipdb.set_trace() diff --git a/lib/freebies.db b/lib/freebies.db index 12beb1c963e832db481e7a7493e3029e691ac4dc..43349ede9871cfc4e5126d4427a33bbf52ac4117 100644 GIT binary patch delta 406 zcmZozz}Rqrae}lUI|Bm)8xX?)%S0Vxadrm1cv)Wl9}KKKyBPR+`FHZw^GWgS+SusA zW6~7M$}TP|%h<|Wl9-f}npTvWnv|JZ45QhcgIpa$TopnboqSvsprVr<`DC0jOHy;= z^AdAY6~Y{YoIMvb$LYY8!DY*Fuxq7<$DR{d^Y9JJ7Dg?Q@xdyrVIlBfc zK!ibxH8N8)@mK(KoH5WH@jx2YV2GWae}lUD+2=q2*UvLL>*&MRtCLzSzi7h3@m(74E((OJNfGQq&5o*EaTlQ e#dk}P$285{DB08^Db2(pd6U8yeiVU41_}T{Q53rX diff --git a/lib/migrations/versions/ee5b1e0f4931_create_freebies.py b/lib/migrations/versions/ee5b1e0f4931_create_freebies.py new file mode 100644 index 000000000..1e5d78572 --- /dev/null +++ b/lib/migrations/versions/ee5b1e0f4931_create_freebies.py @@ -0,0 +1,38 @@ +"""Create Freebies" + + +Revision ID: ee5b1e0f4931 +Revises: 5f72c58bf48c +Create Date: 2023-08-07 11:27:10.849308 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ee5b1e0f4931' +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('item_name', sa.String(), nullable=True), + sa.Column('value', sa.Integer(), nullable=True), + sa.Column('dev_id', sa.Integer(), nullable=True), + sa.Column('company_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/models.py b/lib/models.py index 2681bee5a..93c3d59e6 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", @@ -16,6 +17,11 @@ class Company(Base): name = Column(String()) founding_year = Column(Integer()) + freebies = relationship('Freebie', backref=backref('company')) + + devs = association_proxy('freebies', 'dev', + creator=lambda dev: Freebie(dev=dev)) + def __repr__(self): return f'' @@ -23,7 +29,24 @@ class Dev(Base): __tablename__ = 'devs' id = Column(Integer(), primary_key=True) - name= Column(String()) + name = Column(String()) + + freebies = relationship('Freebie', backref=backref('dev')) + + companies = association_proxy('freebies', 'company', + creator=lambda company: Freebie(company=company)) def __repr__(self): return f'' + +class Freebie(Base): + __tablename__ = 'freebies' + + id = Column(Integer(), primary_key=True) + item_name = Column(String()) + value = Column(Integer()) + dev_id = Column(Integer(), ForeignKey('devs.id')) + company_id = Column(Integer(), ForeignKey('companies.id')) + + def __repr__(self): + return f'' diff --git a/lib/seed.py b/lib/seed.py index b16becbbb..95f12e150 100644 --- a/lib/seed.py +++ b/lib/seed.py @@ -1,3 +1,39 @@ #!/usr/bin/env python3 -# Script goes here! +from random import choice as rc + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker + +from models import Dev, Company, Freebie + +engine = create_engine('sqlite:///seed_db.db') +Session = sessionmaker(bind=engine) +session = Session() + +def delete_records(): + session.query(Dev).delete() + session.query(Company).delete() + session.query(Freebie).delete() + session.commit() + +def create_records(): + devs = [Dev() for i in range(500)] + companies = [Company() for i in range(100)] + freebies = [Freebie() for i in range(1000)] + session.add_all(devs + companies + freebies) + session.commit() + return devs, companies, freebies + +def relate_records(devs, companies, freebies): + for freebie in freebies: + freebie.dev = rc(devs) + freebie.company = rc(companies) + + session.add_all(freebies) + session.commit() + +if __name__ == '__main__': + delete_records() + devs, companies, freebies = create_records() + relate_records(devs, companies, freebies) diff --git a/lib/seed_db.db b/lib/seed_db.db new file mode 100644 index 000000000..e69de29bb From 4a935aba359fd6584883ffc0f42016d9e61037a3 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Mon, 7 Aug 2023 12:17:27 -0700 Subject: [PATCH 2/5] populate db with seed file --- lib/freebies.db | Bin 24576 -> 69632 bytes lib/seed.py | 16 +++++++++++----- lib/seed_db.db | 0 3 files changed, 11 insertions(+), 5 deletions(-) delete mode 100644 lib/seed_db.db diff --git a/lib/freebies.db b/lib/freebies.db index 43349ede9871cfc4e5126d4427a33bbf52ac4117..fedd76e374f284edec5da48b8d9c8907db340773 100644 GIT binary patch literal 69632 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 delta 64 wcmZozz|wGlae_1}I|Bm)+e8I>M)r*fOZ1r-1U3sgJma4@L4=JLD1(y=00t%x;Q#;t diff --git a/lib/seed.py b/lib/seed.py index 95f12e150..130bbf3ae 100644 --- a/lib/seed.py +++ b/lib/seed.py @@ -1,26 +1,32 @@ #!/usr/bin/env python3 from random import choice as rc - +from faker import Faker from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from models import Dev, Company, Freebie -engine = create_engine('sqlite:///seed_db.db') +fake = Faker() + +engine = create_engine('sqlite:///freebies.db') Session = sessionmaker(bind=engine) session = Session() +devs = [Dev(name = fake.name()) for i in range(500)] +companies = [Company(name = fake.name(), founding_year = fake.random_int(1800, 2022)) for i in range(100)] +freebies = [Freebie(item_name = fake.name(), value = fake.random_int(0, 500)) for i in range(1000)] + def delete_records(): session.query(Dev).delete() session.query(Company).delete() session.query(Freebie).delete() + # session.delete(Dev) + # session.delete(Company) + # session.delete(Freebie) session.commit() def create_records(): - devs = [Dev() for i in range(500)] - companies = [Company() for i in range(100)] - freebies = [Freebie() for i in range(1000)] session.add_all(devs + companies + freebies) session.commit() return devs, companies, freebies diff --git a/lib/seed_db.db b/lib/seed_db.db deleted file mode 100644 index e69de29bb..000000000 From 477ae505a09bba2ab9256164df5679ae3e4baee4 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Mon, 7 Aug 2023 16:05:18 -0700 Subject: [PATCH 3/5] complete Dev, Freebie methods --- lib/models.py | 45 ++++++++++++++++++++++++++++++++++++++++----- lib/seed.py | 3 --- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/lib/models.py b/lib/models.py index 93c3d59e6..f0ff61f47 100644 --- a/lib/models.py +++ b/lib/models.py @@ -1,7 +1,7 @@ -from sqlalchemy import ForeignKey, Column, Integer, String, MetaData -from sqlalchemy.orm import relationship, backref +from sqlalchemy import ForeignKey, Column, Integer, String, MetaData, create_engine +from sqlalchemy.orm import relationship, backref, sessionmaker from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.ext.associationproxy import association_proxy +from sqlalchemy.ext.associationproxy import association_proxy convention = { "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", @@ -23,7 +23,26 @@ class Company(Base): creator=lambda dev: Freebie(dev=dev)) def __repr__(self): - return f'' + return f'Company {self.name}' + ', ' + f'{self.founding_year}' + + def give_freebie(self, dev, item_name, value): + + freebie = Freebie( + item_name=item_name, + value=value, + dev_id=dev.id, + company_id=self.id) + + return freebie + + @classmethod + def oldest_company(cls): + engine = create_engine('sqlite:///freebies.db') + Base.metadata.create_all(engine) + Session = sessionmaker(bind=engine) + session = Session() + + return session.query(Company).order_by(Company.founding_year).first() class Dev(Base): __tablename__ = 'devs' @@ -39,6 +58,12 @@ class Dev(Base): def __repr__(self): return f'' + def received_one(self, item_name): + pass + + def give_away(self, dev, freebie): + pass + class Freebie(Base): __tablename__ = 'freebies' @@ -49,4 +74,14 @@ class Freebie(Base): company_id = Column(Integer(), ForeignKey('companies.id')) def __repr__(self): - return f'' + return f'Freebie {self.id} ' + f'{self.item_name} ' + f'{self.value} ' + f'{self.dev_id} ' + f'{self.company_id} ' + + def print_details(self): + engine = create_engine('sqlite:///freebies.db') + Base.metadata.create_all(engine) + Session = sessionmaker(bind=engine) + session = Session() + + dev = session.query(Dev).filter(Dev.id == self.dev_id).first() + company = session.query(Company).filter(Company.id == self.company_id).first() + print(f'{dev.name} owns a {self.item_name} from {company.name}') diff --git a/lib/seed.py b/lib/seed.py index 130bbf3ae..b64e77b32 100644 --- a/lib/seed.py +++ b/lib/seed.py @@ -21,9 +21,6 @@ def delete_records(): session.query(Dev).delete() session.query(Company).delete() session.query(Freebie).delete() - # session.delete(Dev) - # session.delete(Company) - # session.delete(Freebie) session.commit() def create_records(): From e2414b9913a8b1bba8914c6581f44e9db8cbf6e4 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Mon, 7 Aug 2023 16:31:27 -0700 Subject: [PATCH 4/5] make received_one method --- lib/models.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/models.py b/lib/models.py index f0ff61f47..81a750214 100644 --- a/lib/models.py +++ b/lib/models.py @@ -59,7 +59,15 @@ def __repr__(self): return f'' def received_one(self, item_name): - pass + engine = create_engine('sqlite:///freebies.db') + Base.metadata.create_all(engine) + Session = sessionmaker(bind=engine) + session = Session() + + freebie = session.query(Freebie).filter(Freebie.dev_id == self.id).first() + if freebie.item_name == item_name: + return True + return False def give_away(self, dev, freebie): pass From c0ae1945d82e8572c34844eefa008afe1945cca8 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Mon, 7 Aug 2023 21:17:54 -0700 Subject: [PATCH 5/5] complete --- lib/freebies.db | Bin 69632 -> 69632 bytes lib/models.py | 14 +++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/freebies.db b/lib/freebies.db index fedd76e374f284edec5da48b8d9c8907db340773..a48a0edbf472cbc21bced6010ed5dacefec90d74 100644 GIT binary patch delta 33 ncmZozz|ydQWr8##|3n#QM*fWn0%eR=n+waXN&qSM{+$f~v8)SP delta 33 ncmZozz|ydQWr8##-$WT_M!t;+0%eSbn+waXN&qSM{+$f~u+|Gk diff --git a/lib/models.py b/lib/models.py index 81a750214..69e267eea 100644 --- a/lib/models.py +++ b/lib/models.py @@ -70,7 +70,19 @@ def received_one(self, item_name): return False def give_away(self, dev, freebie): - pass + engine = create_engine('sqlite:///freebies.db') + Base.metadata.create_all(engine) + Session = sessionmaker(bind=engine) + session = Session() + + devs_freebie = session.query(Freebie).filter(Freebie.dev_id == self.id).first() + if freebie == devs_freebie.item_name: + session.query(Freebie).filter(Freebie.dev_id == self.id).update({Freebie.dev_id : dev.id}) + session.commit() + print("Success") + else: + print("Fail") + class Freebie(Base): __tablename__ = 'freebies'