Skip to content

Commit

Permalink
Added flake8 and fixed endpoints.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsuhoi committed Jul 21, 2023
1 parent 8c8202f commit c86a21f
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 119 deletions.
3 changes: 3 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
max-line-length = 120
ignore = E203,E402,C901,W503,W504,E116,E501,E702,E731,W613,W102,R903,R902,R914,R915,R205,W703,W702,W603
8 changes: 2 additions & 6 deletions backend/core/init_data_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@
import pathlib

import geoalchemy2 as gsa
# import geopandas
import shapely
import sqlalchemy as sa

from core.auth import get_password_hash
from core.model_utils import get_count

from .database import async_session, init_db
from .model_utils import get_city_and_districts
from .models import City, City_property, District, District_property, User

DATA_DIR = pathlib.Path(__file__).parent.parent.joinpath("data")
Expand All @@ -34,16 +31,15 @@ async def __spb_example_init_data():
geom=dist["geometry"],
)
)

spb = City(
city = City(
title="Санкт-Петербург",
properties=City_property(population=5600044, area=1439),
districts=districts,
blocks=[],
geom=gsa.shape.from_shape(shapely.geometry.MultiPolygon(), srid=4326),
)
async with async_session() as db:
db.add(spb)
db.add(city)
await db.commit()
print("Successful init data!")

Expand Down
105 changes: 47 additions & 58 deletions backend/core/model_utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from types import FunctionType

import sqlalchemy as sa
from sqlalchemy.ext.asyncio import AsyncSession

from .database import Base
from .models import City, City_property, District, District_property, User
from .models import (Block, Block_property, City, City_property, District,
District_property, User)


async def get_user_by_id(id: int, db: AsyncSession) -> User:
Expand All @@ -19,8 +22,12 @@ async def get_count(db: AsyncSession, model: Base):
return (await db.scalars(sa.sql.func.count(model.id))).first()


async def get_where(db: AsyncSession, model: Base, condition: FunctionType):
return (await db.scalars(sa.select(model).where(condition(model)))).first()


async def get_by_id(db: AsyncSession, model: Base, id: int):
return (await db.scalars(sa.select(model).where(model.id == id))).first()
return await get_where(db, model, lambda x: x.id == id)


async def get_all(db: AsyncSession, model: Base, limit: int = None):
Expand All @@ -29,7 +36,19 @@ async def get_all(db: AsyncSession, model: Base, limit: int = None):
return (await db.scalars(sa.select(model))).all()


async def get_all_where(
db: AsyncSession, model: Base, condition: FunctionType = None, limit: int = None
):
if limit:
return (
await db.scalars(sa.select(model).where(condition(model)).limit(limit))
).all()
return (await db.scalars(sa.select(model).where(condition(model)))).all()


def exec_query_geojson(func_query):
"""Getting data from the database in the form of GeoJSON"""

async def wrapper(db: AsyncSession, *args, **kwargs):
query = func_query(*args, **kwargs)
data = (await db.execute(query)).first()[0]
Expand All @@ -42,17 +61,12 @@ async def wrapper(db: AsyncSession, *args, **kwargs):


@exec_query_geojson
def get_blocks_geojson():
return


@exec_query_geojson
def get_districts_geojson():
def get_blocks_geojson(city_id: int):
return (
sa.select(
sa.func.json_build_object(
"type",
"FeatuerCollection",
"FeatureCollection",
"features",
sa.func.json_agg(
sa.func.json_build_object(
Expand All @@ -61,30 +75,31 @@ def get_districts_geojson():
"properties",
sa.func.json_build_object(
"title",
District.title,
Block.title,
"population",
District_property.population,
Block_property.population,
"area",
District_property.area,
Block_property.area,
),
"geometry",
sa.func.ST_AsGeoJSON(District.geom).cast(sa.JSON),
sa.func.ST_AsGeoJSON(Block.geom).cast(sa.JSON),
)
),
)
)
.select_from(District)
.outerjoin(District_property, District.id == District_property.district_id)
.select_from(Block)
.outerjoin(Block_property, Block.id == Block_property.block_id)
.where(Block.city_id == city_id)
)


@exec_query_geojson
def get_cities_geojson():
def get_districts_geojson(city_id: int):
return (
sa.select(
sa.func.json_build_object(
"type",
"FeatuerCollection",
"FeatureCollection",
"features",
sa.func.json_agg(
sa.func.json_build_object(
Expand All @@ -93,41 +108,28 @@ def get_cities_geojson():
"properties",
sa.func.json_build_object(
"title",
City.title,
District.title,
"population",
City_property.population,
District_property.population,
"area",
City_property.area,
District_property.area,
),
"geometry",
sa.func.ST_AsGeoJSON(City.geom).cast(sa.JSON),
sa.func.ST_AsGeoJSON(District.geom).cast(sa.JSON),
)
),
)
)
.select_from(City)
.outerjoin(City_property, City.id == City_property.city_id)
.select_from(District)
.outerjoin(District_property, District.id == District_property.district_id)
.where(District.city_id == city_id)
)


async def get_city_and_districts(db: AsyncSession, city_title: str):
query = (
@exec_query_geojson
def get_cities_geojson():
return (
sa.select(
sa.func.json_build_object(
"type",
"Feature",
"properties",
sa.func.json_build_object(
"title",
City.title,
"population",
City_property.population,
"area",
City_property.area,
),
"geometry",
sa.func.ST_AsGeoJSON(City.geom).cast(sa.JSON),
),
sa.func.json_build_object(
"type",
"FeatureCollection",
Expand All @@ -139,35 +141,22 @@ async def get_city_and_districts(db: AsyncSession, city_title: str):
"properties",
sa.func.json_build_object(
"title",
District.title,
City.title,
"population",
District_property.population,
City_property.population,
"area",
District_property.area,
City_property.area,
),
"geometry",
sa.func.ST_AsGeoJSON(District.geom).cast(sa.JSON),
sa.func.ST_AsGeoJSON(City.geom).cast(sa.JSON),
)
),
),
)
)
.select_from(City)
.outerjoin(District, City.id == District.city_id)
.outerjoin(District_property, District.id == District_property.district_id)
.outerjoin(City_property, City.id == City_property.city_id)
.where(City.title == city_title)
.group_by(
City.title,
City.geom,
City_property.population,
City_property.area,
)
)

if data := (await db.execute(query)).first():
return {"city": data[0], "districts": data[1]}
return {}


async def create_model(db: AsyncSession, model: Base):
db.add(model)
Expand Down
43 changes: 22 additions & 21 deletions backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,24 @@ def geom_init_decorator(cls):

def new_init(self, *args, geom, **kwargs):
if isinstance(geom, dict):
init(
self, *args, geom=gsa.shape.from_shape(shape(geom), srid=4326), **kwargs
)
else:
init(self, *args, geom=geom, **kwargs)
geom = gsa.shape.from_shape(shape(geom), srid=4326)
init(self, *args, geom=geom, **kwargs)

@property
def geometry(self):
shape = gsa.shape.to_shape(self.geom)
return shape.__geo_interface__

cls.geometry = geometry
cls.__init__ = new_init
return cls


class User(Base):
ROLE_TYPES = [(1, "admin"), (2, "user")]
__tablename__ = "users"

ROLE_TYPES = [(1, "admin"), (2, "user")]

id = sa.Column(sa.Integer, primary_key=True, index=True)
username = sa.Column(sa.String(32), unique=True, index=True)
hashed_password = sa.Column(sa.String)
Expand All @@ -49,6 +53,10 @@ class District_property(Base):
population = sa.Column(sa.Integer, nullable=True)
area = sa.Column(sa.Float, nullable=False)

@property
def title(self) -> str:
return self.district.title

district = sa.orm.relationship("District", back_populates="properties")


Expand All @@ -64,6 +72,10 @@ class Block_property(Base):
population = sa.Column(sa.Integer, nullable=True)
area = sa.Column(sa.Float, nullable=False)

@property
def title(self) -> str:
return self.block.title

block = sa.orm.relationship("Block", back_populates="properties")


Expand All @@ -76,6 +88,10 @@ class City_property(Base):
population = sa.Column(sa.Integer, nullable=True)
area = sa.Column(sa.Float, nullable=False)

@property
def title(self) -> str:
return self.district.title

city = sa.orm.relationship("City", back_populates="properties")


Expand All @@ -90,11 +106,6 @@ class District(Base):
gsa.Geometry(geometry_type="MULTIPOLYGON", srid=4326), nullable=False
)

@property
def geometry(self):
shape = gsa.shape.to_shape(self.geom)
return shape.__geo_interface__

city = sa.orm.relationship("City", back_populates="districts", lazy="selectin")
properties = sa.orm.relationship(
"District_property", back_populates="district", uselist=False, lazy="selectin"
Expand All @@ -111,11 +122,6 @@ class Block(Base):
gsa.Geometry(geometry_type="MULTIPOLYGON", srid=4326), nullable=False
)

@property
def geometry(self):
shape = gsa.shape.to_shape(self.geom)
return shape.__geo_interface__

city = sa.orm.relationship("City", back_populates="blocks", lazy="selectin")
properties = sa.orm.relationship(
"Block_property", back_populates="block", uselist=False, lazy="selectin"
Expand All @@ -132,11 +138,6 @@ class City(Base):
gsa.Geometry(geometry_type="MULTIPOLYGON", srid=4326), nullable=False
)

@property
def geometry(self):
shape = gsa.shape.to_shape(self.geom)
return shape.__geo_interface__

districts = sa.orm.relationship("District", back_populates="city", lazy="selectin")
blocks = sa.orm.relationship("Block", back_populates="city", lazy="selectin")
properties = sa.orm.relationship(
Expand Down
7 changes: 6 additions & 1 deletion backend/core/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Annotated

import shapely
from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, HttpUrl

Lat = Annotated[float, Field(example=10.345, description="Широта")]
Lng = Annotated[float, Field(example=10.345, description="Долгота")]
Expand Down Expand Up @@ -55,6 +55,7 @@ class LoginResponse(BaseModel):


class Properties(BaseModel):
# title: str
population: int = Field(ge=0, description="Население")
area: float = Field(gt=0, description="Площадь(км^2)")

Expand Down Expand Up @@ -127,3 +128,7 @@ class City(BaseModel):

class Config:
from_attributes = True


class LinksList(BaseModel):
links: list[HttpUrl]
3 changes: 2 additions & 1 deletion backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from core.database import init_db
from core.init_data_db import init_data
from routers import geo, users
from routers import geo, others, users

app = FastAPI(
title="Аналитика гетто",
Expand All @@ -25,6 +25,7 @@
app.include_router(users.router)
app.include_router(geo.router)
# app.include_router(gql.router, prefix="/graphql")
app.include_router(others.router)


@app.on_event("startup")
Expand Down
1 change: 1 addition & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ geopandas = "^0.13.2"
[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"
pytest-asyncio = "^0.21.0"
flake8 = "^6.0.0"

[build-system]
requires = ["poetry-core"]
Expand Down
Loading

0 comments on commit c86a21f

Please sign in to comment.