sqlalchemy Object with OrderingList - Session.commit() method fails - sqlalchemy

Model that has attribute in type of sqlalchemy OrderingList fails on Database Session Commit step (as Database I am using PostgreSQL 13):
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import relationship
from database.base_class import Base
from sqlalchemy.ext.orderinglist import ordering_list
class ContentType(Enum):
SCENE_HEADING = 'scene_heading'
ACTION = 'action'
CHARACTER = 'character'
PARENTHETICAL = 'parenthetical'
DIALOGUE = 'dialogue'
SHOT = 'shot'
TRANSITION = 'transition'
TEXT = 'text'
class EditorElement(Base):
"""
Class that represents the Table of Editor Elements.
"""
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
content = Column(String, nullable=True)
content_type = Column(ContentType, nullable=True)
screenplay_id = Column(Integer, ForeignKey('screenplays.id', ondelete="CASCADE"), nullable=False)
screenplay = relationship("Screenplay", back_populates="elements")
class Screenplay(Base):
"""
Class that represents the screenplay table in the database.
"""
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
name = Column(String, index=True, nullable=False)
elements = relationship("EditorElement", back_populates="screenplay", order_by="EditorElement.content_type",
collection_class=ordering_list('content_type'))
I am using FastAPI framework and in the CRUD file where the Screenplay is created, I have the following class:
class CRUDScreenplay(CRUDBase[models.Screenplay, schemas.ScreenplayBase, schemas.ScreenplayBase]):
#staticmethod
def create(db: Session, *, obj_in: schemas.ScreenplayCreate) -> models.Screenplay:
db_obj = models.Screenplay()
db_obj.name = obj_in['name']
for element in obj_in.get('elements'):
e = models.EditorElement(
content=element.content,
content_type=element.content_type,
screenplay_id=db_obj.id
)
db_obj.elements.append(e)
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
Using the PyCharm debugger I was able to check when the error occurs, it seems to appear after Session.commit(). Here is the object elements before the commit() method
And here is the elements object after the commit() method.
And the error in the console:
INFO: 127.0.0.1:52649 - "POST /api/v1/screenplays/ HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\sql\sqltypes.py", line 1649, in _object_value_for_elem
return self._object_lookup[elem]
KeyError: 'scene_heading'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 372, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 75, in __call__
return await self.app(scope, receive, send)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\fastapi\applications.py", line 261, in __call__
await super().__call__(scope, receive, send)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
raise exc
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\middleware\cors.py", line 84, in __call__
await self.app(scope, receive, send)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\exceptions.py", line 82, in __call__
raise exc
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
raise e
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\routing.py", line 656, in __call__
await route.handle(scope, receive, send)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\routing.py", line 259, in handle
await self.app(scope, receive, send)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\routing.py", line 61, in app
response = await func(request)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\fastapi\routing.py", line 235, in app
response_data = await serialize_response(
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\fastapi\routing.py", line 130, in serialize_response
value, errors_ = await run_in_threadpool(
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\starlette\concurrency.py", line 39, in run_in_threadpool
return await anyio.to_thread.run_sync(func, *args)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\anyio\to_thread.py", line 28, in run_sync
return await get_asynclib().run_sync_in_worker_thread(func, *args, cancellable=cancellable,
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\anyio\_backends\_asyncio.py", line 818, in run_sync_in_worker_thread
return await future
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\anyio\_backends\_asyncio.py", line 754, in run
result = context.run(func, *args)
File "pydantic\fields.py", line 854, in pydantic.fields.ModelField.validate
File "pydantic\fields.py", line 1071, in pydantic.fields.ModelField._validate_singleton
File "pydantic\fields.py", line 1118, in pydantic.fields.ModelField._apply_validators
File "pydantic\class_validators.py", line 313, in pydantic.class_validators._generic_validator_basic.lambda12
File "pydantic\main.py", line 678, in pydantic.main.BaseModel.validate
File "pydantic\main.py", line 562, in pydantic.main.BaseModel.from_orm
File "pydantic\main.py", line 1001, in pydantic.main.validate_model
File "pydantic\utils.py", line 409, in pydantic.utils.GetterDict.get
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\orm\attributes.py", line 481, in __get__
return self.impl.get(state, dict_)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\orm\attributes.py", line 941, in get
value = self._fire_loader_callables(state, key, passive)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\orm\attributes.py", line 977, in _fire_loader_callables
return self.callable_(state, passive)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\orm\strategies.py", line 911, in _load_for_state
return self._emit_lazyload(
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\orm\strategies.py", line 1051, in _emit_lazyload
result = result.unique().scalars().all()
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\engine\result.py", line 1371, in all
return self._allrows()
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\engine\result.py", line 401, in _allrows
rows = self._fetchall_impl()
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\engine\result.py", line 1284, in _fetchall_impl
return self._real_result._fetchall_impl()
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\engine\result.py", line 1696, in _fetchall_impl
return list(self.iterator)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\orm\loading.py", line 147, in chunks
fetch = cursor._raw_all_rows()
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\engine\result.py", line 393, in _raw_all_rows
return [make_row(row) for row in rows]
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\engine\result.py", line 393, in <listcomp>
return [make_row(row) for row in rows]
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\sql\sqltypes.py", line 1768, in process
value = self._object_value_for_elem(value)
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\sql\sqltypes.py", line 1651, in _object_value_for_elem
util.raise_(
File "C:\Users\userh\Playground\screenplay-writer\backend\.venv\lib\site-packages\sqlalchemy\util\compat.py", line 207, in raise_
raise exception
LookupError: 'scene_heading' is not among the defined enum values. Enum name: None. Possible values: None
However, the data was successfully created in the database, but FastAPI does not return anything due to this error.
There are some related issues in GitHub but I am was not able to figure out what is going on there:
Issue 1
Issue 2
Issue 3
Issue 4
UPDATE
Alembic (which is often used with FastAPI) or SLQAlchemy created the PostgreSQL ENUM Type in Uppercase.
I changed the definition of ContentType(enum.Enum) as it was in the example of the official documentation LINK. Thanks to #fchancel for pointing on that:
class ContentType(str, enum.Enum):
HEADING = 'HEADING'
ACTION = 'ACTION'
CHARACTER = 'CHARACTER'
PARENTHETICAL = 'PARENTHETICAL'
DIALOGUE = 'DIALOGUE'
SHOT = 'SHOT'
TRANSITION = 'TRANSITION'
TEXT = 'TEXT'
So, now my code works

It seems that when creating your elements, the content_type section is a problem, since it can't find heading_scene. To understand this, we need to see how you call your function and what obj_in contains.
However, it's possible that the source of the error is just your class ContentType(Enum) which to work properly should be class ContentType(str, Enum)

Related

SQLalchemy | fastAPI. Trying to add a new row in association table gives KeyError

So I have a fastAPI project that uses sqlalchemy to connect to a postgresql database.
I use alembic to build the database and have version control on it.
My issue is now that everything works quite like it should with the many to many relationship. All stocks show the portfolio they belong to, and all portfolios show the stocks they have in them (This was tested with manually entering the data in PGAdmin).
The issue now is that every time I try to add a new connection (add a stock to a portfolio) it throws me a "Key-Error".
Here is the models.py:
class PortfolioStock(Base):
__tablename__ = "portfolio_stocks"
id = Column(Integer, primary_key=True)
stock_id = Column(Integer, ForeignKey("stocks.id", ondelete="CASCADE"))
portfolio_id = Column(Integer, ForeignKey("portfolios.id", ondelete="CASCADE"))
count = Column(Integer, nullable=True)
buy_in = Column(Float, nullable=True)
stock = relationship("Stock", back_populates="portfolios")
portfolio = relationship("Portfolio", back_populates="stocks")
#a lot of these proxy associations here because of another bug I encountered
#basically every column in the two models associated here have a association proxy row.(couldn't find another fix)
stock_created_at = association_proxy(target_collection="stock", attr="created_at")
portfolio_name = association_proxy(target_collection="portfolio", attr="name")
def __init__(self, portfolio=None, stock=None, buy_in=None, count=None):
self.portfolio = portfolio
self.stock = stock
self.buy_in = buy_in
self.count = count
class Stock(Base):
__tablename__ = "stocks"
id = Column(Integer, primary_key=True, nullable=False)
...
status = Column(Integer, nullable=False, server_default="0")
portfolios = relationship("PortfolioStock", back_populates="stock")
class Portfolio(Base):
__tablename__ = "portfolios"
id = Column(Integer, primary_key=True, nullable=False)
name = Column(String, nullable=False)
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
monetary_goal = Column(Float, nullable=True)
dividends_goal = Column(Float, nullable=True)
created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=text("now()"))
stocks = relationship("PortfolioStock", back_populates="portfolio")
Here are some snippets to show what I do in the fastapi route.
First i get the portfolio in question and the stocks that are passed into the body.
I iterate over the stocks and grab the corresponding entry in the DB for each one.
And finally I try to just add these stocks to the list that contains all the models that are in the portfolio.
portfolio = db.query(models.Portfolio).filter(models.Portfolio.id == portfolio_id).first()
for stock in stock_ids:
stock = db.query(models.Stock).filter(models.Stock.id == stock_id).first()
portfolio.stocks.append(stock)
setattr(stock, "status", "1")
db.add(portfolio)
db.commit()
db.refresh(portfolio)
return portfolio
And here is the error message that I receive when I try to call this route from postman.
Traceback (most recent call last):
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 375, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
return await self.app(scope, receive, send)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/fastapi/applications.py", line 259, in __call__
await super().__call__(scope, receive, send)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in __call__
raise exc
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/middleware/cors.py", line 84, in __call__
await self.app(scope, receive, send)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
raise exc
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
raise e
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/routing.py", line 656, in __call__
await route.handle(scope, receive, send)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/routing.py", line 259, in handle
await self.app(scope, receive, send)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/routing.py", line 61, in app
response = await func(request)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/fastapi/routing.py", line 222, in app
raw_response = await run_endpoint_function(dependant=dependant, values=values, is_coroutine=is_coroutine)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/fastapi/routing.py", line 159, in run_endpoint_function
return await run_in_threadpool(dependant.call, **values)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/starlette/concurrency.py", line 39, in run_in_threadpool
return await anyio.to_thread.run_sync(func, *args)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/anyio/to_thread.py", line 28, in run_sync
return await get_asynclib().run_sync_in_worker_thread(func, *args, cancellable=cancellable,
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 818, in run_sync_in_worker_thread
return await future
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 754, in run
result = context.run(func, *args)
File "/home/maxi/dev/./api/routers/stock.py", line 151, in add_stock_to_portfolio
portfolio.stocks.append(stock)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/sqlalchemy/orm/collections.py", line 1169, in append
item = __set(self, item, _sa_initiator)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/sqlalchemy/orm/collections.py", line 1134, in __set
item = executor.fire_append_event(item, _sa_initiator)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/sqlalchemy/orm/collections.py", line 753, in fire_append_event
return self.attr.fire_append_event(
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/sqlalchemy/orm/attributes.py", line 1330, in fire_append_event
value = fn(state, value, initiator or self._append_token)
File "/home/maxi/dev/captstone_venv/lib/python3.8/site-packages/sqlalchemy/orm/attributes.py", line 1632, in emit_backref_from_collection_append_event
child_impl = child_state.manager[key].impl
KeyError: 'portfolio'
I have already tried to rename all relationships to figure out where exactly the error is coming from.
And it seems to be that t he relationship of stock = relationship("Stock", back_populates="portfolios") is a culprit of the issue.
Looking in debugging mode it seems that the model I'm trying to access is not having the correct keys in it, so my guess is that I'm either making the new association wrong and it's not portfolio.stocks.append(stock) (which worked before I fixed another issue) or that the relationships are wrong / something is missing to make it work.
I would really greatly appreciate some suggestions.
If you need additional information please let me know.

How to use marshmallow-sqlalchemy with async code?

I'm trying to use marshmallow-sqlalchemy with aiohttp and I have followed their docs with the basic example and I'm getting an error.
I have this schema:
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema
from db.customer import Customer
class CustomerSchema(SQLAlchemyAutoSchema):
class Meta:
model = Customer
include_relationships = True
load_instance = True
And then the following code for the query:
from sqlalchemy import select
from db import db_conn
from db.customer import Customer
from queries.schema import CustomerSchema
customer_schema = CustomerSchema()
async def get_all_users():
async with db_conn.get_async_sa_session() as session:
statement = select(Customer)
results = await session.execute(statement)
_ = (results.scalars().all())
print(_)
response = customer_schema.dump(_, many=True)
print(response)
For the first print statement I'm getting
[<db.customer.Customer object at 0x10a183340>, <db.customer.Customer object at 0x10a183940>, <db.customer.Customer object at 0x10b0cd9d0>]
But then it fails with
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 60, in await_only
raise exc.MissingGreenlet(
sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_() here. Was IO attempted in an unexpected place? (Background on this error at: http://sqlalche.me/e/14/xd2s)
So how can I use marshmallow-sqlalchemy to serialize the SqlAlchemy reponse?
Another options (packages, etc) or a generic custom solutions are OK too.
For the time being I'm using this:
statement = select(Customer)
results = await session.execute(statement)
_ = (results.scalars().all())
response = {}
for result in _:
value = {k: (v if not isinstance(v, sqlalchemy.orm.state.InstanceState) else '_') for k, v in result.__dict__.items()}
response[f'customer {value["id"]}'] = value
return response
Full traceback:
Traceback (most recent call last):
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/aiohttp/web_protocol.py", line 422, in _handle_request
resp = await self._request_handler(request)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/aiohttp/web_app.py", line 499, in _handle
resp = await handler(request)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/aiohttp/web_urldispatcher.py", line 948, in _iter
resp = await method()
File "/Users/ruslan/OneDrive/Home/Dev/projects/code/education/other/cft/views/user.py", line 24, in get
await get_all_users()
File "/Users/ruslan/OneDrive/Home/Dev/projects/code/education/other/cft/queries/user.py", line 18, in get_all_users
response = customer_schema.dump(_, many=True)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow/schema.py", line 547, in dump
result = self._serialize(processed_obj, many=many)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow/schema.py", line 509, in _serialize
return [
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow/schema.py", line 510, in <listcomp>
self._serialize(d, many=False)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow/schema.py", line 515, in _serialize
value = field_obj.serialize(attr_name, obj, accessor=self.get_attribute)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow/fields.py", line 310, in serialize
value = self.get_value(obj, attr, accessor=accessor)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow_sqlalchemy/fields.py", line 27, in get_value
return super(fields.List, self).get_value(obj, attr, accessor=accessor)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow/fields.py", line 239, in get_value
return accessor_func(obj, check_key, default)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow/schema.py", line 472, in get_attribute
return get_value(obj, attr, default)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow/utils.py", line 239, in get_value
return _get_value_for_key(obj, key, default)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/marshmallow/utils.py", line 253, in _get_value_for_key
return getattr(obj, key, default)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/orm/attributes.py", line 480, in __get__
return self.impl.get(state, dict_)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/orm/attributes.py", line 931, in get
value = self.callable_(state, passive)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/orm/strategies.py", line 879, in _load_for_state
return self._emit_lazyload(
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/orm/strategies.py", line 1036, in _emit_lazyload
result = session.execute(
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1689, in execute
result = conn._execute_20(statement, params or {}, execution_options)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1582, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/sql/lambdas.py", line 481, in _execute_on_connection
return connection._execute_clauseelement(
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1451, in _execute_clauseelement
ret = self._execute_context(
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1813, in _execute_context
self._handle_dbapi_exception(
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1998, in _handle_dbapi_exception
util.raise_(exc_info[1], with_traceback=exc_info[2])
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1770, in _execute_context
self.dialect.do_execute(
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 717, in do_execute
cursor.execute(statement, parameters)
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 449, in execute
self._adapt_connection.await_(
File "/Users/ruslan/.local/share/virtualenvs/cft-RKlbQ9iX/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 60, in await_only
raise exc.MissingGreenlet(
sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_() here. Was IO attempted in an unexpected place? (Background on this error at: http://sqlalche.me/e/14/xd2s)
The problem in this case is that the Marshmallow schema is configured to load related models (include_relationships=True). Since the initial query doesn't load them automatically, the schema triggers a query to fetch them, and this causes the error.
The simplest solution, demonstrated in the docs, is to eagerly load the related objects with their "parent":
async def get_all_users():
async with db_conn.get_async_sa_session() as session:
# Let's assume a Customer has a 1 to many relationship with an Order model
statement = select(Customer).options(orm.selectinload(Customer.orders))
results = await session.execute(statement)
_ = (results.scalars().all())
print(_)
response = customer_schema.dump(_, many=True)
print(response)
There is more discussion in the Preventing Implicit IO when Using AsyncSession section of the docs.

The database backend does not accept 0 as a value for AutoField

I have a model:
class Tour(models.Model):
INACTIVE = 0
ACTIVE = 1
ARCHIVE = 2
STATUS = (
(INACTIVE, "Inactive"),
(ACTIVE, "Active"),
(ARCHIVE, "Archive"),
)
AIR_TOUR = 0
GROUND_TOUR = 1
SEA_TOUR = 2
T_TYPES = (
(AIR_TOUR, "Air_tour"),
(GROUND_TOUR, "Ground_tour"),
(SEA_TOUR, "Sea_tour"),
)
title = models.CharField(max_length=200)
tour_from = models.ForeignKey(Airport, related_name='from_location')
tour_to = models.ForeignKey(Airport, related_name='to_location')
duration_day = models.IntegerField(default=1, blank=True, null=True)
duration_night = models.IntegerField(default=1, blank=True, null=True)
transport_type = models.IntegerField(default=AIR_TOUR, choices=T_TYPES, blank=True, null=True)
documents = models.TextField(default='', blank=True, null=True)
description = models.TextField(blank=True, null=True, default='')
services = models.TextField(blank=True, null=True, default='')
airline = models.ForeignKey(Airline, null=True, blank=True)
train = models.ForeignKey(Train, null=True, blank=True)
bus = models.ForeignKey(Bus, null=True, blank=True)
user = models.ForeignKey(User, related_name='user')
creator = models.ForeignKey(User, related_name='creator')
status = models.IntegerField(default=INACTIVE, choices=STATUS, blank=True, null=True)
create_at = models.DateTimeField(default='2000-10-10')
update_at = models.DateTimeField(default='2000-10-10')
I try to change status to ARCHIVE by this code:
test = Tour.objects.get(id=self.kwargs['pk'])
test.status = ARCHIVE
test.save()
and get this error:
The database backend does not accept 0 as a value for AutoField.
status field is not AutoField. Why this error happend?
UPDATE:
full stack trace:
Django version 1.11, using settings 'project.settings_local'
Starting development server at http://0.0.0.0:8888/
Quit the server with CONTROL-C.
Internal Server Error: /dashboard/tour/delete/1/
Traceback (most recent call last):
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/views/generic/base.py", line 88, in dispatch
return handler(request, *args, **kwargs)
File "/home/py/project/dashboard/views_tour.py", line 196, in post
tour.save()
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py", line 806, in save
force_update=force_update, update_fields=update_fields)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py", line 836, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py", line 903, in _save_table
forced_update)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py", line 953, in _do_update
return filtered._update(values) > 0
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/query.py", line 661, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1191, in execute_sql
cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 863, in execute_sql
sql, params = self.as_sql()
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1157, in as_sql
val = field.get_db_prep_save(val, connection=self.connection)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/fields/related.py", line 963, in get_db_prep_save
return self.target_field.get_db_prep_save(value, connection=connection)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 766, in get_db_prep_save
prepared=False)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 955, in get_db_prep_value
value = connection.ops.validate_autopk_value(value)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/backends/mysql/operations.py", line 155, in validate_autopk_value
raise ValueError('The database backend does not accept 0 as a '
ValueError: The database backend does not accept 0 as a value for AutoField.
Internal Server Error: /dashboard/tour/delete/1/
Traceback (most recent call last):
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/views/generic/base.py", line 88, in dispatch
return handler(request, *args, **kwargs)
File "/home/py/project/dashboard/views_tour.py", line 196, in post
tour.save()
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py", line 806, in save
force_update=force_update, update_fields=update_fields)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py", line 836, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py", line 903, in _save_table
forced_update)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py", line 953, in _do_update
return filtered._update(values) > 0
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/query.py", line 661, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1191, in execute_sql
cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 863, in execute_sql
sql, params = self.as_sql()
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1157, in as_sql
val = field.get_db_prep_save(val, connection=self.connection)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/fields/related.py", line 963, in get_db_prep_save
return self.target_field.get_db_prep_save(value, connection=connection)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 766, in get_db_prep_save
prepared=False)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 955, in get_db_prep_value
value = connection.ops.validate_autopk_value(value)
File "/home/.virtualenvs/project/lib/python3.6/site-packages/django/db/backends/mysql/operations.py", line 155, in validate_autopk_value
raise ValueError('The database backend does not accept 0 as a '
ValueError: The database backend does not accept 0 as a value for AutoField.
You likely have a foreign key field that contains a 0 (instead of null, or a valid value). If you don't have the proper foreign key constraints at the DB level (or you turned off foreign key checks when you added the constraints), there is nothing preventing invalid foreign key references from existing in that row.
Check the data in the all your foreign key fields for a 0: tour_from, tour_to,
airline, train, bus, user, creator.
What you're doing should work. Since the object is already in the database, it's strange that updating it with the same fields leads to a 0 somewhere (probably one of the foreign keys).
You should debug this and there are two ways to go at it:
Inspect your database using raw SQL. manage.py dbshell opens a SQL shell where you can do SELECT * FROM my_app_tour WHERE id = 1. Look at the particular row, maybe you can spot the issue.
Try test.save(update_fields=['status']). If that works, add more fields to update one by one, e.g. test.save(update_fields=['status', 'tour_from'], then test.save(update_fields['status', 'tour_from', 'tour_to'])... until the error is thrown again.
I suspect a database corruption, but there might be some other more serious issue in the way you create the objects. That would cause problems down the line.
Check your django_content_type table, look for 0's in the id column. Django logs database operations after each call, and it writes the ID of the content type.
I found that I had several entries with a 0 id. Updating these with unique numbers after the end of the sequence and restarting Django fixed this for me.
Honestly, I have no idea how it got that way. I'm using Django 2.2.

I do not understand where the slashes in json come from in the server's response

In the main function, i call a function in which another application is called, as a result i get data in json format.
But I don’t understand where the slashes come from in front of each double quotation "
in the browser, I see data with quotes
Example: {\"192.168.43.1\":[\"53\":{\"state\":\"open\"...
If I do not send the data but write to the file, data is written to the file WITHOUT slashes
Example: {"192.168.43.1":["53":{"state":"open"...
This is normal?
How do I remove the slashes?
This data must accept
another application and deserialize them.
def get_ip(ip, port):
return os.system("some_app")
#hug.get('/scan')
def main(ip: hug.types.text, port: hug.types.text):
json = get_ip(ip, port)
#JUST FOR TEST WITH PARAM safe=False
return JsonResponse("{\"192.168.1.1\":[\"80\":{\"state\":\"open\",\"reason\":\"syn-ack\",\"name\":\"http\",\"product\":\"\"}]}", safe=False)
Errors without parametr safe=False:
Traceback (most recent call last):
File "/usr/lib/python3.6/wsgiref/handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "/usr/local/lib/python3.6/dist-packages/falcon/api.py", line 244, in __call__
responder(req, resp, **params)
File "/usr/local/lib/python3.6/dist-packages/hug/interface.py", line 793, in __call__
raise exception
File "/usr/local/lib/python3.6/dist-packages/hug/interface.py", line 766, in __call__
self.render_content(self.call_function(input_parameters), context, request, response, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/hug/interface.py", line 703, in call_function
return self.interface(**parameters)
File "/usr/local/lib/python3.6/dist-packages/hug/interface.py", line 100, in __call__
return __hug_internal_self._function(*args, **kwargs)
File "script.py", line 181, in main
return JsonResponse("{\"192.168.1.1\":[\"80\":{\"state\":\"open\",\"reason\":\"syn-ack\",\"name\":\"http\",\"product\":\"\"}]}")
File "/usr/local/lib/python3.6/dist-packages/django/http/response.py", line 552, in __init__
'In order to allow non-dict objects to be serialized set the '
TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.
Errors with parametr safe=False:
return JsonResponse("{\"192.168.1.1\":[\"80\":{\"state\":\"open\",\"reason\":\"syn-ack\",\"name\":\"http\",\"product\":\"\"}]}", safe=False)
File "/usr/lib/python3.6/wsgiref/handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "/usr/local/lib/python3.6/dist-packages/falcon/api.py", line 244, in __call__
responder(req, resp, **params)
File "/usr/local/lib/python3.6/dist-packages/hug/interface.py", line 793, in __call__
raise exception
File "/usr/local/lib/python3.6/dist-packages/hug/interface.py", line 766, in __call__
self.render_content(self.call_function(input_parameters), context, request, response, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/hug/interface.py", line 703, in call_function
return self.interface(**parameters)
File "/usr/local/lib/python3.6/dist-packages/hug/interface.py", line 100, in __call__
return __hug_internal_self._function(*args, **kwargs)
File "script.py", line 181, in main
return JsonResponse("{\"192.168.1.1\":[\"80\":{\"state\":\"open\",\"reason\":\"syn-ack\",\"name\":\"http\",\"product\":\"\"}]}", safe=False)
File "/usr/local/lib/python3.6/dist-packages/django/http/response.py", line 559, in __init__
super().__init__(content=data, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/django/http/response.py", line 291, in __init__
self.content = content
File "/usr/local/lib/python3.6/dist-packages/django/http/response.py", line 321, in content
content = self.make_bytes(value)
File "/usr/local/lib/python3.6/dist-packages/django/http/response.py", line 236, in make_bytes
return bytes(value.encode(self.charset))
File "/usr/local/lib/python3.6/dist-packages/django/http/response.py", line 85, in charset
return settings.DEFAULT_CHARSET
File "/usr/local/lib/python3.6/dist-packages/django/conf/__init__.py", line 57, in __getattr__
self._setup(name)
File "/usr/local/lib/python3.6/dist-packages/django/conf/__init__.py", line 42, in _setup
% (desc, ENVIRONMENT_VARIABLE))
django.core.exceptions.ImproperlyConfigured: Requested setting
DEFAULT_CHARSET, but settings are not configured. You must either define the
environment variable DJANGO_SETTINGS_MODULE or call settings.configure()
before accessing settings.
Your return "result {json}" would return string value which contains json. Since returned value is string, browser shows you extra backslashes in order to properly handle double quotes.
To solve this problem you could handle string response in client side and extract json values from string.
JSON.parse(response);
But since another application is expecting json format you'd better to use JsonResponse to make sure return response is not string but json format
from django.http import JsonResponse
return JsonResponse(json)

Getting error from sqlalchemy

Here is the error log i get this error when i try to create a new user when i do:
u = User (...)
Error log:
Traceback (most recent call last)
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1994, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/quechon/PycharmProjects/untitled3/myapp/login/routes.py", line 66, in _register_process
timecreated=datetime.datetime.utcnow()
File "<string>", line 4, in __init__
File "/usr/lib/python3.6/site-packages/sqlalchemy/orm/state.py", line 414, in _initialize_instance
manager.dispatch.init_failure(self, args, kwargs)
File "/usr/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/usr/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 186, in reraise
raise value
File "/usr/lib/python3.6/site-packages/sqlalchemy/orm/state.py", line 411, in _initialize_instance
return manager.original_init(*mixed[1:], **kwargs)
File "/home/quechon/PycharmProjects/untitled3/myapp/models.py", line 80, in __init__
self.follow(self)
File "/home/quechon/PycharmProjects/untitled3/myapp/models.py", line 47, in follow
if not self.is_following(user):
File "/home/quechon/PycharmProjects/untitled3/myapp/models.py", line 57, in is_following
return self.followed.filter_by(followed_id=user.id).first() is not None
File "/usr/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 1517, in filter_by
return self.filter(sql.and_(*clauses))
File "<string>", line 2, in filter
File "/usr/lib/python3.6/site-packages/sqlalchemy/orm/base.py", line 198, in generate
self = args[0]._clone()
File "/usr/lib/python3.6/site-packages/sqlalchemy/orm/dynamic.py", line 278, in _clone
orm_util.instance_str(instance), self.attr.key))
sqlalchemy.orm.exc.DetachedInstanceError: Parent instance <User at 0x7fe2ac0e6e80> is not bound to a Session, and no contextual session is established; lazy load operation of attribute 'followed' cannot proceed
This is the model:
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), unique=True)
email = db.Column(db.String(100))
password = db.Column(db.Binary)
profilepic = db.Column(db.String)
timecreated = db.Column(db.DateTime)
#picture = db.relationship('Picture', backref='owner', lazy='dynamic')
comment = db.relationship('Comment', backref='user', lazy='dynamic')
post = db.relationship('Post', backref='user', lazy='dynamic')
followed = db.relationship('Follow', foreign_keys=[Follow.follower_id],
backref=db.backref('follower', lazy='joined'),
lazy='dynamic',
cascade='all, delete-orphan')
followers = db.relationship('Follow',
foreign_keys=[Follow.followed_id],
backref=db.backref('followed', lazy='joined'),
lazy='dynamic',
cascade='all, delete-orphan')
def follow(self, user):
if not self.is_following(user):
f = Follow(follower=self, followed=user)
db.session.add(f)
def unfollow(self, user):
f = self.followed.filter_by(followed_id=user.id).first()
if f:
db.session.delete(f)
def is_following(self, user):
return self.followed.filter_by(followed_id=user.id).first() is not None
def is_followed_by(self, user):
return self.followers.filter_by(follower_id=user.id).first() is not None
#property
def followed_posts(self):
return Post.query.join(Follow.followed_id == Post.user_id)\
.filter(Follow.follower_id == self.id)
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return str(self.id)
def __init__(self, **kwargs):
self.follow(self)
def __repr__(self):
return f'<id - {self.id} | - {self.username}>'
I would like to know why that happened and how to avoid this error next time
The only thing i found online about was to use lazy='subquery' instead of lazy='dynamic' but using that wont allow my query to use filter_by attribute.
It looks like you are trying to interact with your flask app via the interactive shell. You can do this using the command line interface (CLI).
See docs:
http://flask.pocoo.org/docs/0.12/shell/