Django UnicodeEncodeError when importing from db - python

I have a custom management command to import data from one db and create model instances from it. Basically it is:
class Command(BaseCommand):
def handle(self, **kwargs):
cursor = connections['db2'].cursor()
sql = 'SELECT * FROM table'
cursor.execute(sql)
for row in cursor.fetchall():
my_model = MyModel(*row)
my_model.save()
First I was importing from sqlite to sqlite and all went well. But when I switched to MySQL as my main db, I started getting UnicodeEncodeError, when calling my_model.save(). The caveat is that I have non-ascii symbols in db (namely Russian), but as I get, Django converts all strings to unicode. And yes, both dbs use utf-8.

It seems that bug is due to mezzanine app, I'm using
https://github.com/stephenmcd/mezzanine/issues/1132

Related

how to use SQL connection string class in python

i want to create a class which maintain sql connection instead of creating sql connection everytime.
models.py
in models.py i declare sql connection in sqlconn method whenever i call this i want to establish sql connection in views.py
from django.db import models
import pyodbc
def sqlconn(request):
constr = "DRIVER={SQL Server};SERVER=localhose;DATABASE=testdb;UID=user;PWD=password"
conn = pyodbc.connect(constr)
return conn
Views.py
in this views.py i'm retrieving employee data from database instead of writing sqlconnection string in every views.py method. I want to call sqlconn method from models and i want to do further process like
getdata, insertdata, deletedata, updatedate
from django.shortcuts import render
from .models import sqlconn
import pyodbc
def getEmpData(request):
conn = sqlconn
cursor = conn.cursor()
#cursor.execute("select * from Employee")
cursor.execute("exec sp_demotable")
result = cursor.fetchall()
return render(request, 'getempdata.html', {'result':result})
i tried above code but its not working its showing error, any help thanks in advance
Note:
what is the best practices for python any articles are videos tutorials provide its great help for me, because i'm new to python but i've good knowledge in .NET Programming
I would suggest you to use SQLAchemy library as ORM for project.
https://docs.sqlalchemy.org/en/14/orm/tutorial.html

Read entire database with sqlalchemy and dump as JSON

Django has the convenience manage.py command dumpdata which can be configured to dump an entire database as JSON.
At present I am confined to using sqlalchemy and I'd like to do the same thing:
Take as input a connection string like 'mysql+pymysql://user:pwd#localhost:3306/' and get the contents of the database as JSON (I don't require all the meta info that Django provides, but I won't mind).
I found this question elaborating how to dump SQLAlchemy objects to JSON and this from the sqlalchemy documentation outlining how to get all tablenames from a database:
meta = MetaData()
input_db = f'sqlite:///tmpsqlite'
engine = create_engine(input_db)
meta.reflect(bind=engine)
print(meta.tables)
How do I retrieve all of the content of these tables and then convert them to JSON? Is there a built-in command in sqlalchemy similar to django's dumpdata functionality?
Leaving my solution here for posterity:
import json
def dump_sqlalchemy(output_connection_string,output_schema):
""" Returns the entire content of a database as lists of dicts"""
engine = create_engine(f'{output_connection_string}{output_schema}')
meta = MetaData()
meta.reflect(bind=engine) # http://docs.sqlalchemy.org/en/rel_0_9/core/reflection.html
result = {}
for table in meta.sorted_tables:
result[table.name] = [dict(row) for row in engine.execute(table.select())]
return json.dumps(result)

SQL query using current_user doesn't filter results

The following query retrieves every reservation in the database, but I only want to get the reservations that the current user made. When I run the query in the mysql command line, it works. Why isn't this working in my app?
from flaskext.mysql import MySQL
from flask.ext.login import LoginManager
from flask_login import current_user
...
db = MySQL()
db.init_app(app)
...
cur = db.connect().cursor()
cur.execute("SELECT ReservationID FROM Reservation WHERE user_name=" + "'" + current_user + "';")
reservation_instance = cur.fetchall()
current_user is a User instance. You can't just add it to a string, you need to use it's username (assuming you called the attribute "username").
You are currently open to SQL injection attacks. Never try to insert parameters into a query string yourself. Always use parameterized queries, which lets the driver do the work of building, quote, and escape the query properly.
cur.execute('SELECT ReservationID FROM Reservation WHERE user_name=?', [current_user.username])
The placeholder character (I used ? in the example) depends on the driver. Consider using SQLAlchemy, which normalizes this sort of thing and is much more powerful. There is the Flask-SQLAlchemy to make integration with Flask easier as well.

How to retrieve data from sqlite3 database filled up using Python?

I am using peewee along with flask to populate my database with user's inputs and various other stats. How can I retrieve the data in sqlite3 database?
Here is the skeleton:
from peewee import *
database = SqliteDatabase('app4.db', autocommit=True)
class BaseModel(Model):
class Meta:
database = database
class Model1(BaseModel):
class Model2(BaseModel):
class Model3(BaseModel):
app = Flask(__name__)
#app.before_request
def func1():
database.connect()
#app.after_request
def func2(response):
database.close()
return response
#app.route('/', method= ['GET'])
def some_func():
#update pluto and create instances of Model2 and Model3 here
if __name__ == "__main__":
database.connect()
database.create_tables([Model1, Model2, Model3], True)
pluto, created = Model1.get_or_create(key = 2, key2 = 0)
My app is running and showing the updated instances of Model1 and Model2 which means that it has created the models and is continually updating the database.
But I don't know how to retrieve this data offline.
When I enter my sqllite database by sqlite3 app4.db and type .tables it shows me all the tables i.e. Model1, Model2, Model3 but typing in the query : select * from model1; gives nothing. I tried retrieving the data in Ipython shell too making a connection to database as above and querying list(Model1.select()) but it gives an empty list.
It looks like your database filename is being set to app.py:
database = SqliteDatabase('app.py', autocommit=True)
It should probably be app4.db if that's what you want to use:
database = SqliteDatabase('app4.db', autocommit=True)
The commands you are using look like the correct ones for doing it at the command line. Sounds to me like either 1 of 2 things are happening:
You are not actually putting data into the databases
You are not viewing the same database that you are populating.
Try renaming the app4.db file, and re-running your app and see if it creates a new one. This way you can make sure you are using sqlite3 on the correct one. If you are still not seeing any data using the commands you listed, I would assume that your app is not actually putting the data into the tables.

Why Doesn't Django Reset Sequences in SQLite3?

Why does Django allow you to reset the sequences (AutoID) fields on postgres and other DBMS's but not SQLite3?
Looking at the source code for the sql_flush method in django/db/backends/sqlite3/base.py, there is a comment that says:
Note: No requirement for reset of auto-incremented indices (cf. other sql_flush() implementations). Just return SQL at this point
I have a few tests where I load in fixture files that depend on absolute primary key ids. Because Django doesn't reset the auto id field for SQLite, these fixtures do not load correctly.
It appears that it is somewhat trivial to reset the auto id columns in sqlite: How can I reset a autoincrement sequence number in sqlite
You can monkey-patch sql_flush as follows to reset SQLite sequences:
from django.db.backends.sqlite3.operations import DatabaseOperations
from django.db import connection
def _monkey_patch_sqlite_sql_flush_with_sequence_reset():
original_sql_flush = DatabaseOperations.sql_flush
def sql_flush_with_sequence_reset(self, style, tables, sequences, allow_cascade=False):
sql_statement_list = original_sql_flush(self, style, tables, sequences, allow_cascade)
if tables:
# DELETE FROM sqlite_sequence WHERE name IN ($tables)
sql = '%s %s %s %s %s %s (%s);' % (
style.SQL_KEYWORD('DELETE'),
style.SQL_KEYWORD('FROM'),
style.SQL_TABLE(self.quote_name('sqlite_sequence')),
style.SQL_KEYWORD('WHERE'),
style.SQL_FIELD(self.quote_name('name')),
style.SQL_KEYWORD('IN'),
', '.join(style.SQL_FIELD(f"'{table}'") for table in tables)
)
sql_statement_list.append(sql)
return sql_statement_list
DatabaseOperations.sql_flush = sql_flush_with_sequence_reset
You would use it as follows for example in a TransactionTestCase:
from django.test import TransactionTestCase
class TransactionTestCaseWithSQLiteSequenceReset(TransactionTestCase):
reset_sequences = True
#classmethod
def setUpClass(cls):
super().setUpClass()
if connection.vendor == 'sqlite':
_monkey_patch_sqlite_sql_flush_with_sequence_reset()
This assures that tests that depend on fixed primary keys work with both SQLite and other database backends like PostgreSQL. However, see Django documentation for caveats regarding reset_sequences. For one thing, it makes tests slow.
Maybe this snippet will help:
import os
from django.core.management import call_command
from django.db import connection
from django.utils.six import StringIO
def reset_sequences(app_name):
os.environ['DJANGO_COLORS'] = 'nocolor'
buf = StringIO()
call_command('sqlsequencereset', app_name, stdout=buf)
buf.seek(0)
sql = "".join(buf.readlines())
with connection.cursor() as cursor:
cursor.execute(sql)
print("Sequences for app '{}' reset".format(app_name))

Categories

Resources