версия ленивого Кирилла
This commit is contained in:
@@ -1,33 +0,0 @@
|
|||||||
"""initial
|
|
||||||
|
|
||||||
Revision ID: 16041bfd2411
|
|
||||||
Revises:
|
|
||||||
Create Date: 2023-07-13 01:26:56.342068
|
|
||||||
|
|
||||||
"""
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision = '16041bfd2411'
|
|
||||||
down_revision = None
|
|
||||||
branch_labels = None
|
|
||||||
depends_on = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.create_table('people',
|
|
||||||
sa.Column('id', sa.UUID(), nullable=False),
|
|
||||||
sa.Column('first_name', sa.Text(), nullable=False),
|
|
||||||
sa.Column('last_name', sa.Text(), nullable=False),
|
|
||||||
sa.PrimaryKeyConstraint('id')
|
|
||||||
)
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_table('people')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
32
migration/versions/3510de1e1ff1_fix_fk.py
Normal file
32
migration/versions/3510de1e1ff1_fix_fk.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
"""fix FK
|
||||||
|
|
||||||
|
Revision ID: 3510de1e1ff1
|
||||||
|
Revises: 58cc3bbaabd1
|
||||||
|
Create Date: 2023-07-16 01:28:47.704514
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '3510de1e1ff1'
|
||||||
|
down_revision = '58cc3bbaabd1'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_foreign_key(None, 'addresses', 'persons', ['person_id'], ['id'])
|
||||||
|
op.create_foreign_key(None, 'contacts', 'persons', ['person_id'], ['id'])
|
||||||
|
op.create_foreign_key(None, 'documents', 'persons', ['person_id'], ['id'])
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_constraint(None, 'documents', type_='foreignkey')
|
||||||
|
op.drop_constraint(None, 'contacts', type_='foreignkey')
|
||||||
|
op.drop_constraint(None, 'addresses', type_='foreignkey')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
"""person, address, contact, document v1
|
||||||
|
|
||||||
|
Revision ID: 58cc3bbaabd1
|
||||||
|
Revises: c74556e04b57
|
||||||
|
Create Date: 2023-07-16 01:19:02.307879
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '58cc3bbaabd1'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('addresses',
|
||||||
|
sa.Column('category', sa.String(length=30), nullable=False),
|
||||||
|
sa.Column('region', sa.String(length=100), nullable=True),
|
||||||
|
sa.Column('city', sa.String(length=100), nullable=True),
|
||||||
|
sa.Column('street', sa.String(length=100), nullable=True),
|
||||||
|
sa.Column('house', sa.String(length=100), nullable=True),
|
||||||
|
sa.Column('flat', sa.String(length=100), nullable=True),
|
||||||
|
sa.Column('person_id', sa.UUID(), nullable=False),
|
||||||
|
sa.Column('id', sa.UUID(), nullable=False),
|
||||||
|
sa.Column('created_at', sa.TIMESTAMP(), nullable=False),
|
||||||
|
sa.Column('updated_at', sa.TIMESTAMP(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_index(op.f('ix_addresses_id'), 'addresses', ['id'], unique=False)
|
||||||
|
op.create_table('contacts',
|
||||||
|
sa.Column('category', sa.String(length=30), nullable=False),
|
||||||
|
sa.Column('value', sa.String(length=100), nullable=False),
|
||||||
|
sa.Column('person_id', sa.UUID(), nullable=False),
|
||||||
|
sa.Column('id', sa.UUID(), nullable=False),
|
||||||
|
sa.Column('created_at', sa.TIMESTAMP(), nullable=False),
|
||||||
|
sa.Column('updated_at', sa.TIMESTAMP(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_index(op.f('ix_contacts_id'), 'contacts', ['id'], unique=False)
|
||||||
|
op.create_table('documents',
|
||||||
|
sa.Column('category', sa.String(length=30), nullable=False),
|
||||||
|
sa.Column('series', sa.String(length=30), nullable=False),
|
||||||
|
sa.Column('number', sa.String(length=50), nullable=False),
|
||||||
|
sa.Column('issued_by', sa.String(length=200), nullable=False),
|
||||||
|
sa.Column('issued_at', sa.Date(), nullable=True),
|
||||||
|
sa.Column('person_id', sa.UUID(), nullable=False),
|
||||||
|
sa.Column('attachments', postgresql.ARRAY(sa.String(length=200)), nullable=True),
|
||||||
|
sa.Column('id', sa.UUID(), nullable=False),
|
||||||
|
sa.Column('created_at', sa.TIMESTAMP(), nullable=False),
|
||||||
|
sa.Column('updated_at', sa.TIMESTAMP(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_index(op.f('ix_documents_id'), 'documents', ['id'], unique=False)
|
||||||
|
op.create_table('persons',
|
||||||
|
sa.Column('first_name', sa.String(length=100), nullable=False),
|
||||||
|
sa.Column('last_name', sa.String(length=100), nullable=False),
|
||||||
|
sa.Column('patronymic', sa.String(length=100), nullable=True),
|
||||||
|
sa.Column('gender', sa.String(length=50), nullable=True),
|
||||||
|
sa.Column('birth_date', sa.Date(), nullable=True),
|
||||||
|
sa.Column('photos', postgresql.ARRAY(sa.String(length=200)), nullable=True),
|
||||||
|
sa.Column('id', sa.UUID(), nullable=False),
|
||||||
|
sa.Column('created_at', sa.TIMESTAMP(), nullable=False),
|
||||||
|
sa.Column('updated_at', sa.TIMESTAMP(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_index(op.f('ix_persons_id'), 'persons', ['id'], unique=False)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_index(op.f('ix_persons_id'), table_name='persons')
|
||||||
|
op.drop_table('persons')
|
||||||
|
op.drop_index(op.f('ix_documents_id'), table_name='documents')
|
||||||
|
op.drop_table('documents')
|
||||||
|
op.drop_index(op.f('ix_contacts_id'), table_name='contacts')
|
||||||
|
op.drop_table('contacts')
|
||||||
|
op.drop_index(op.f('ix_addresses_id'), table_name='addresses')
|
||||||
|
op.drop_table('addresses')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -2,6 +2,7 @@ export PYTHONPATH='/home/dd/astra/personal_information/src'
|
|||||||
export POSTGRES_DB='personal_info_db'
|
export POSTGRES_DB='personal_info_db'
|
||||||
docker run -itd -e POSTGRES_USER=barbie -e POSTGRES_PASSWORD=redStar4,1 -p 5432:5432 -v /home/dd/astra/postgresql_db:/var/lib/postgresql/data --name personal_info_db postgres
|
docker run -itd -e POSTGRES_USER=barbie -e POSTGRES_PASSWORD=redStar4,1 -p 5432:5432 -v /home/dd/astra/postgresql_db:/var/lib/postgresql/data --name personal_info_db postgres
|
||||||
docker exec -it personal_info_db bash
|
docker exec -it personal_info_db bash
|
||||||
|
docker start 9a9653ea37ca
|
||||||
psql -U barbie -d barbie
|
psql -U barbie -d barbie
|
||||||
CREATE DATABASE personal_info_db;
|
CREATE DATABASE personal_info_db;
|
||||||
|
|
||||||
@@ -10,6 +11,8 @@ alembic revision --autogenerate -m 'initial'
|
|||||||
alembic init alembic
|
alembic init alembic
|
||||||
в alembic.ini правим sqlalchemy.url
|
в alembic.ini правим sqlalchemy.url
|
||||||
alembic revision -m "add columns to checkup table"
|
alembic revision -m "add columns to checkup table"
|
||||||
|
alembic revision --autogenerate -m "person, address, contact, document v1"
|
||||||
|
|
||||||
alembic upgrade ae1 (можно часть версии, лишь бы однозначно указывала)
|
alembic upgrade ae1 (можно часть версии, лишь бы однозначно указывала)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,76 @@
|
|||||||
import uuid
|
import uuid
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
import datetime
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy.dialects.postgresql import UUID
|
from sqlalchemy.dialects.postgresql import UUID, ARRAY
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship, DeclarativeBase
|
||||||
from sqlalchemy.sql.schema import ForeignKey
|
from sqlalchemy.sql.schema import ForeignKey
|
||||||
|
|
||||||
Base: Any = declarative_base()
|
#Base: Any = declarative_base()
|
||||||
|
class Base(DeclarativeBase):
|
||||||
|
pass
|
||||||
|
|
||||||
class Person(Base):
|
class BaseModel(Base):
|
||||||
__tablename__ = 'people'
|
__abstract__ = True
|
||||||
|
|
||||||
id = sa.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
id = sa.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
|
||||||
first_name = sa.Column(sa.Text, nullable=False)
|
created_at = sa.Column(sa.TIMESTAMP, nullable=False, default=datetime.datetime.now())
|
||||||
last_name = sa.Column(sa.Text, nullable=False)
|
updated_at = sa.Column(sa.TIMESTAMP, nullable=False, default=datetime.datetime.now(), onupdate=datetime.datetime.now())
|
||||||
|
|
||||||
|
|
||||||
|
class Person(BaseModel):
|
||||||
|
__tablename__ = 'persons'
|
||||||
|
|
||||||
|
first_name = sa.Column(sa.String(100), nullable=False)
|
||||||
|
last_name = sa.Column(sa.String(100), nullable=False)
|
||||||
|
patronymic = sa.Column(sa.String(100))
|
||||||
|
gender = sa.Column(sa.String(50))
|
||||||
|
birth_date = sa.Column(sa.Date)
|
||||||
|
addresses = relationship('Address', back_populates='person')
|
||||||
|
contacts = relationship('Contact', back_populates='person')
|
||||||
|
documents = relationship('Document', back_populates='person')
|
||||||
|
photos = sa.Column(ARRAY(sa.String(200)))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'Person {self.last_name} {self.first_name} {self.id}'
|
||||||
|
|
||||||
|
class Address(BaseModel):
|
||||||
|
__tablename__ = 'addresses'
|
||||||
|
category = sa.Column(sa.String(30), nullable=False)
|
||||||
|
region = sa.Column(sa.String(100))
|
||||||
|
city = sa.Column(sa.String(100))
|
||||||
|
street = sa.Column(sa.String(100))
|
||||||
|
house = sa.Column(sa.String(100))
|
||||||
|
flat = sa.Column(sa.String(100))
|
||||||
|
person_id = sa.Column(UUID(as_uuid=True), sa.ForeignKey("persons.id"), nullable=False)
|
||||||
|
person = relationship('Person', back_populates='addresses')
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'Address {self.city} {self.street} {self.id}'
|
||||||
|
|
||||||
|
class Contact(BaseModel):
|
||||||
|
__tablename__ = 'contacts'
|
||||||
|
category = sa.Column(sa.String(30), nullable=False)
|
||||||
|
value = sa.Column(sa.String(100), nullable=False)
|
||||||
|
person_id = sa.Column(UUID(as_uuid=True), sa.ForeignKey("persons.id"), nullable=False)
|
||||||
|
person = relationship('Person', back_populates='contacts')
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'Contact {self.category} {self.value} {self.id}'
|
||||||
|
|
||||||
|
class Document(BaseModel):
|
||||||
|
__tablename__ = 'documents'
|
||||||
|
|
||||||
|
category = sa.Column(sa.String(30), nullable=False)
|
||||||
|
series = sa.Column(sa.String(30), nullable=False)
|
||||||
|
number = sa.Column(sa.String(50), nullable=False)
|
||||||
|
issued_by = sa.Column(sa.String(200), nullable=False)
|
||||||
|
issued_at = sa.Column(sa.Date)
|
||||||
|
person_id = sa.Column(UUID(as_uuid=True), sa.ForeignKey("persons.id"), nullable=False)
|
||||||
|
person = relationship('Person', back_populates='documents')
|
||||||
|
attachments = sa.Column(ARRAY(sa.String(200)))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'Document {self.category} {self.number} {self.id}'
|
||||||
@@ -1,20 +1,56 @@
|
|||||||
from datetime import datetime
|
from datetime import date
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field, ConfigDict
|
||||||
from pydantic.types import UUID4
|
from pydantic.types import UUID4
|
||||||
|
|
||||||
class Person(BaseModel):
|
class Person(BaseModel):
|
||||||
id: UUID4
|
|
||||||
first_name: str
|
first_name: str
|
||||||
last_name: str
|
last_name: str
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
orm_mode = True
|
orm_mode = True
|
||||||
|
|
||||||
class PersonCreate(BaseModel):
|
class PersonBase(BaseModel):
|
||||||
first_name: str
|
first_name: str
|
||||||
last_name: str
|
last_name: str
|
||||||
|
patronymic: Optional[str]
|
||||||
|
gender: Optional[str]
|
||||||
|
birth_date: Optional[date]
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
validate_assignment=True
|
||||||
|
revalidate_instances='always'
|
||||||
|
orm_mode = True
|
||||||
|
# extra='ignore'
|
||||||
|
|
||||||
|
class AddressCreate(BaseModel):
|
||||||
|
category: str
|
||||||
|
region: Optional[str]
|
||||||
|
city: Optional[str]
|
||||||
|
street: Optional[str]
|
||||||
|
house: Optional[str]
|
||||||
|
flat: Optional[str]
|
||||||
|
|
||||||
|
class ContactCreate(BaseModel):
|
||||||
|
category: str
|
||||||
|
value: str
|
||||||
|
|
||||||
|
class DocumentCreate(BaseModel):
|
||||||
|
category: str
|
||||||
|
series: str
|
||||||
|
number: str
|
||||||
|
issued_by: str
|
||||||
|
issued_at: Optional[date]
|
||||||
|
attachments: Optional[List[str]]
|
||||||
|
|
||||||
|
class PersonCreate(PersonBase):
|
||||||
|
|
||||||
|
addresses: Optional[List[AddressCreate]] = []
|
||||||
|
contacts: Optional[List[ContactCreate]] = []
|
||||||
|
documents: Optional[List[DocumentCreate]] = []
|
||||||
|
photos: Optional[List[str]] = []
|
||||||
|
|
||||||
|
|
||||||
class PersonDetail(Person):
|
class PersonDetail(Person):
|
||||||
id: UUID4
|
id: UUID4
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ router = APIRouter(prefix='/persons')
|
|||||||
async def list_persons(
|
async def list_persons(
|
||||||
persons_service: PersonService = Depends(get_persons_service),
|
persons_service: PersonService = Depends(get_persons_service),
|
||||||
) -> List[models.Person]:
|
) -> List[models.Person]:
|
||||||
print('=======================================')
|
|
||||||
print(persons_service.list())
|
|
||||||
return persons_service.list()
|
return persons_service.list()
|
||||||
|
|
||||||
@router.get('/{person_id}', response_model=PersonDetail)
|
@router.get('/{person_id}', response_model=PersonDetail)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from sqlalchemy.orm import Session
|
|||||||
|
|
||||||
from personal_info.db.session import get_session
|
from personal_info.db.session import get_session
|
||||||
|
|
||||||
from .people import PersonService
|
from .persons import PersonService
|
||||||
|
|
||||||
def get_persons_service(db_session: Session = Depends(get_session)) -> PersonService:
|
def get_persons_service(db_session: Session = Depends(get_session)) -> PersonService:
|
||||||
return PersonService(db_session)
|
return PersonService(db_session)
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
from typing import Any
|
|
||||||
|
|
||||||
from sqlalchemy.orm import Session
|
|
||||||
|
|
||||||
from personal_info.db.models import Person
|
|
||||||
from personal_info.db.schemas import PersonCreate
|
|
||||||
|
|
||||||
from personal_info.services.base import BaseService
|
|
||||||
|
|
||||||
class PersonService(BaseService[Person, PersonCreate, Any]):
|
|
||||||
def __init__(self, db_session: Session):
|
|
||||||
super(PersonService, self).__init__(Person, db_session)
|
|
||||||
|
|
||||||
# def create(self, obj: PersonCreate) -> Person:
|
|
||||||
|
|
||||||
# person: Person = Person()
|
|
||||||
# self.db_session.add(person)
|
|
||||||
# self.db_session.flush()
|
|
||||||
# self.db_session.commit()
|
|
||||||
# return person
|
|
||||||
39
src/personal_info/services/persons.py
Normal file
39
src/personal_info/services/persons.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from personal_info.db.models import Person, Address, Document, Contact
|
||||||
|
from personal_info.db.schemas import PersonCreate, PersonBase
|
||||||
|
|
||||||
|
from personal_info.services.base import BaseService
|
||||||
|
|
||||||
|
class PersonService(BaseService[Person, PersonCreate, Any]):
|
||||||
|
def __init__(self, db_session: Session):
|
||||||
|
super(PersonService, self).__init__(Person, db_session)
|
||||||
|
|
||||||
|
def create(self, obj: PersonCreate) -> Person:
|
||||||
|
print('= raw' * 3 )
|
||||||
|
print(obj)
|
||||||
|
person_obj = PersonBase(**obj.dict())
|
||||||
|
person = super(PersonService, self).create(person_obj)
|
||||||
|
|
||||||
|
addresses = [
|
||||||
|
Address(**address.dict(), person_id=person.id) for address in obj.addresses
|
||||||
|
]
|
||||||
|
self.db_session.add_all(addresses)
|
||||||
|
self.db_session.commit()
|
||||||
|
|
||||||
|
documents = [
|
||||||
|
Document(**document.dict(), person_id=person.id) for document in obj.documents
|
||||||
|
]
|
||||||
|
self.db_session.add_all(documents)
|
||||||
|
self.db_session.commit()
|
||||||
|
|
||||||
|
contacts = [
|
||||||
|
Contact(**contact.dict(), person_id=person.id) for contact in obj.contacts
|
||||||
|
]
|
||||||
|
self.db_session.add_all(contacts)
|
||||||
|
self.db_session.commit()
|
||||||
|
|
||||||
|
return person
|
||||||
|
|
||||||
Reference in New Issue
Block a user