SQLAlchemy 2.0 version of User.query.get(1) in Flask-SQLAlchemy? - flask

The Problem
The Query.get() method is deprecated in SQLAlchemy 2.0. Accordingly, the Flask-SQLAlchemy query interface is considered legacy. Thus, running User.query.get(1) in my Flask-SQLAlchemy project gives the legacy warning shown below:
>>> User.query.get(1)
<stdin>:1: LegacyAPIWarning: The Query.get() method
is considered legacy as of the 1.x series of SQLAlchemy
and becomes a legacy construct in 2.0. The method is
now available as Session.get() (deprecated since: 2.0)
(Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
<User spongebob>
My Question
What is the new, SQLAlchemy 2.0-compatible version of User.query.get(1) in Flask-SQLAlchemy? More specifically, why does the Flask-SQLAlchemy documentation recommend Approach #2 below, even though Approach #1 appears to be the new version based on my reading of the SQLAlchemy 2.0 migration guide?
Approach #1: db.session.get(User, 1)
This first approach comes from the SQLAlchemy docs, specifically the SQLAlchemy 2.0 Migration - ORM Usage guide. Translating the "2.0 style" example in that guide to my Flask-SQLAlchemy project yields the following code, which works fine:
>>> db.session.get(User, 1)
<User spongebob>
This approach with session.get() isn't mentioned in the Flask-SQLAlchemy 3.0.x documentation as far as I can tell, except briefly in the API reference section on get_or_404.
Approach #2: db.session.execute(db.select(User).filter_by(id=1)).scalar()
This approach comes from the Flask-SQLAlchemy documentation, which suggests using session.execute(select(...)) as a replacement for the legacy Model.query and session.query. This works fine, too:
>>> db.session.execute(db.select(User).filter_by(id=1)).scalar()
<User spongebob>
Approach #1 vs. Approach #2 vs. Legacy Approach
Approach #1 (db.session.get(User, 1)) appears to be most similar to the Legacy Approach (User.query.get(1)) because it caches the result in the session the first time it runs and won't emit additional calls to the database unnecessarily. This can be seen in the REPL with the echo turned on, i.e. db.engine.echo = True. In contrast, Approach #2 (session.execute(select(...))) goes to the database each time, as expected.
My Set Up / Environment
Versions: Flask 2.2.2, Flask-SQLAlchemy 3.0.3, and SQLAlchemy 2.0.1 in a virtual environment with Python 3.11.
I'm using the project structure defined in the Flask Mega-Tutorial, specifically Part IV Database.

Related

Create sqlalchemy engine from django.db connection

With DJANGO app and postgresql db, I use panda read_sql quite a bit for rendering complex queries into dataframe for manipulation and ultimate rendering to JSON. Historically have used django.db dbconnections to map from multi db environment and pass that connection directly into read_sql function. As panda evolves, and becomes less tolerant of non sqlalchemy connections as an argument, I am looking for a simple method to take my existing connection and use it to create_engine.
I've seen some related past comments that suggest
engine = create_engine('postgresql+psycopg2://', creator=con)
but for me that generates an error: TypeError: 'ConnectionProxy' object is not callable
I've played with various attributes of the ConnectionProxy...no success. Would like to avoid writing a separate connection manager or learning too much about sqlalchemy. Django is using psycopg2 to create its connections and I am long time user of same. Some of the add-ins like aldjemy are too intrusive since I neither need or want models mapped. Some have suggested ignoring warning message since dbconnection still works...seems like risk longterm...

Django test -- Model object created but cannot be found

I'm calling a Model which is called People and do
People.objects.create(first='foo', last='bar', bio='test')
This Model uses db_table='"people"."background"'
When I run the test, doing People.objects.first() finds something, but doing raw query like SELECT * from people.background gives me nothing. Why is that?
Apparently Django doesn't officially support schema.
I have come up with a workaround which connects to the db and makes a raw query directly. Essentially,
with connection().cursor as cursor:
cursor.execute("""INSERT INTO bleh bleh bleh""") # assuming there's autocommit
EDIT:
Django's response: Django doesn't officially support schemas. See #6148 for that. As far as I know, the . syntax only works on Oracle.

django json field: which one?

I am looking for a JSON field for Django.
I have found mainly 2 jsonfield app and I am not sure which one I should use.
The main difference I see is that the first one does not have the native JSON datatype support for PostgreSQL anymore.
It has been removed recently (https://github.com/bradjasper/django-jsonfield/commit/15957c9dab18c546ae5c119f8a6057e5db6b2135). It was related to this issue https://github.com/bradjasper/django-jsonfield/issues/57
but I am not sure if it's the right approach since JSONB is also coming soon with PostgreSQL 9.4. I think it's better to use the native datatype when using PostgreSQL. What do you think?
1) https://github.com/bradjasper/django-jsonfield
2) https://bitbucket.org/schinckel/django-jsonfield/
Since Django 1.9 JSON support is back again with JSONField:
https://docs.djangoproject.com/en/1.9/ref/contrib/postgres/fields/

Django Dajax vs Dajaxice

This may be a very silly question but I'm looking at implementing ajax in my django project and the big plugin seems to be dajax/dajaxice however I can't for the life of me distinguish between the two. Could someone clear this up a little for me? Thanks.
ATTENTION:
Should I use django-dajax or django-dajaxice?
In a word, No. I created these projects 4 years ago as a cool tool in
order to solve one specific problems I had at that time.
These days using these projects is a bad idea.
https://github.com/jorgebastida/django-dajax
Dajaxice is the core of the project, to quote the website:
'Its main goal is to trivialize the asynchronous communication between the django server side code and your js code.'
This means that a django / python method on the server like:
from django.utils import simplejson
from dajaxice.decorators import dajaxice_register
#dajaxice_register
def multiply(request, a, b):
result = int(a) * int(b)
return simplejson.dumps({'result' : result})
Can be called on the client using javascript:
var result = Dajaxice.calcualator.multiply(1, 2);
console.log("Dajax says 1 * 2 = "+result);
Dajax provides a series of tools that incorporate dajaxice but requires less Javascript to be used, instead relying on more Python. The multiple example is here.
I have used dajaxice on a few projects without using dajax. Also worth mentioning is Tasty Pie this creates a similar interface on the server, and using JQuery ajax helper functions like .post(), client side, little additional code is required in javascript compared to dajaxice.

How to use Django 1.4 with Xeround?

According to Xeround's Release Notes they don't support save points and I can't figure out how to turn off support for this in Django 1.4. Does anyone know how to accomplish this?
I had the same problem. Django seems to only check the version of the MySql when it decides whether to use savepoints or not. Xeround probably uses some non-standard database-engine that doesn't support savepoints even if the MySql version is high enough.
Quick fix (just for testing) is to just edit the django/db/backends/mysql/base.py to override the logic:
Before:
self.features.uses_savepoints = self.get_server_version() >= (5, 0, 3)
After:
self.features.uses_savepoints = False
I tested this and it didn't seem to cause problems.
Note: Editing django sources directly like this is not recommended, you probably should just create your own db backend module by subclassing or copying the mysql module and placing it inside your project. Remember to update settings.py database configuration to point to your module.