Does PeeWee support interaction with MySQL Views? - python

I am trying to access pre-created MySQL View in the database via. peewee treating it as a table [peewee.model], however I am still prompted with Operational Error 1054 unknown column.
Does PeeWee Supports interactions with database view ?

Peewee has been able to query against views when I've tried it, but while typing up a simple proof-of-concept I ran into two potential gotcha's.
First, the code:
from peewee import *
db = SqliteDatabase(':memory:')
class Foo(Model):
name = TextField()
class Meta: database = db
db.create_tables([Foo])
for name in ('huey', 'mickey', 'zaizee'):
Foo.create(name=name)
OK -- nothing exciting, just loaded three names into a table. Then I made a view that corresponds to the upper-case conversion of the name:
db.execute_sql('CREATE VIEW foo_view AS SELECT UPPER(name) FROM foo')
I then tried the following, which failed:
class FooView(Foo):
class Meta:
db_table = 'foo_view'
print [fv.name for fv in FooView.select()]
Then I ran into the first issue.
When I subclassed "Foo", I brought along a primary key column named "id". Since I used a bare select() (FooView.select()), peewee assumed i wasnted both the "id" and the "name". Since the view has no "id", I got an error.
I tried again, specifying only the name:
print [fv.name for fv in FooView.select(FooView.name)]
This also failed.
The reason this second query fails can be found by looking at the cursor description on a bare select:
curs = db.execute_sql('select * from foo_view')
print curs.description[0][0] # Print the first column's name.
# prints UPPER(name)
SQLite named the view's column "UPPER(name)". To fix this, I redefined the view:
db.execute_sql('CREATE VIEW foo_view AS SELECT UPPER(name) AS name FROM foo')
Now, when I query the view it works just fine:
print [x.name for x in FooView.select(FooView.name)]
# prints ['HUEY', 'MICKEY', 'ZAIZEE']
Hope that helps.

Related

Django Bug with long name in db_column?

When i use a long name in db_columns at a field in Models.py, django does not work correct. It truncates the name, and add random letters/numbers at the end.
Like this: db_column='my_loooooooooooooooooong_column_name'
And when i try queryset, django returns:
'table name'.'my_looooooooooooooo6E4': invalid identifier.
My scenario in detail:
I have a legacy database in Oracle.
The table name in database: PALAVRA_CHAVE_ENTREGA_VALOR
With 3 Fields: PCEV_CD_PALAVRA_CHAVE_ENTREGA_VALOR (Primary Key), PACH_CD_PALAVRA_CHAVE, ENVA_CD_ENTREGA_VALOR
In my models.py:
class PalavraChaveEntregaValor(models.Model):
pcev_cd_palavra_chave_entrega_valor = models.BigIntegerField(primary_key=True, db_column='pcev_cd_palavra_chave_entrega_valor')
pach_cd_palavra_chave = models.BigIntegerField()
enva_cd_entrega_valor = models.BigIntegerField()
class Meta:
managed = False
db_table = 'palavra_chave_entrega_valor'
When i run in shell (python manage.py shell) this command:
PalavraChaveEntregaValor.objects.all()
I got output: DatabaseError: ORA-00904: "PALAVRA_CHAVE_ENTREGA_VALOR"."PCEV_CD_PALAVRA_CHAVE_ENTRA6E4": invalid identifier
I made a test, changed the long name PCEV_CD_PALAVRA_CHAVE_ENTREGA_VALOR to PCEV_CD, and everthing works fine..
Is there a limitation of characters in db_columns at django? Is there a workaround for this? If not, i will have to create a lot of Views in Oracle Database with shorter names of columns only for django work.. Change the current table column names is not an option.

Do i need to call create tables every time in peewee?

I working in a project in which i have different projects with the same database architecture,
so i used peewee Model in which:
dynamic_db = SqliteDatabase(None)
class BaseModel(Model):
class Meta:
database = dynamic_db
class KV (BaseModel):
key = TextField()
value = IntegerField()
And whenever i new project is created i will call a function
dynamic_db.init(r'{}\database.db'.format(ProjectName.upper()))
dynamic_db.connect()
dynamic_db.create_tables([KV])
dynamic_db.close()
The problem is that once this database is created, i can't access with peewee.
When i try to create a record:
KV.create(key = 'Saul', value = 123)
I get this error:
peewee.InterfaceError: Error, database must be initialized before opening a connection.
I would appreciate any help or cookbook for peewee.
I believe something is incorrect, either in your question description, or in the error you are receiving. The call you are making to .init() is what initializes the database. After that, you should have no problems using it.
Full example which works fine:
from peewee import *
db = SqliteDatabase(None)
class Base(Model):
class Meta:
database = db
class KV(Base):
key = TextField()
value = IntegerField()
db.init('foo.db') # database is now initialized
db.connect()
db.create_tables([KV]) # no problems.
db.close()
I was finally able to create a record.
I didn't mention that i was trying to create them in another file, but the procedure is the same as the one coleifer posted on the answer.
The file in which i create the peewee models is databases.py, so in the other file i do the following:
import databases
databases.db.init('foo.db')
databases.KV.create(name = 'Saul', value= 123)
Thanks!

django db_table not changing

Hi i have created a dynamic table model and it is not changing whenever i select another table from the list i ve created in the template...
if i select the first table to see the data of it and then go back to the list and select the second table i get this error
InternalError: (1054, u"Unknown column 'table_name1.id' in 'field list'")
So, when I change from http://127.0.0.1:8000/tables/id=1 to http://127.0.0.1:8000/tables/id=2 it gives me the error.
But if I restart the server and go straight to
http://127.0.0.1:8000/tables/id=2 it works.
But now http://127.0.0.1:8000/tables/id=1 it doesn't work.
this is the party of views.py
def addview(request, pk):
table_name = Crawledtables.objects.get(id=pk)
print table_name
AllTables._meta.db_table = table_name.name
print AllTables._meta.db_table
tbl_detail = AllTables.objects.all()
print tbl_detail
return render(request, 'tables/table_list.html', {'details': tbl_detail})
The prints are just for testing and they work.
It prints out the correct table I select.
But the tbl_detail it doesn't print when i go to the 2nd table that i selected. only when I restart the server.
CrawledTables holds all the table names inside that DB with the date of creation of each table. I get the table name of the CrawledTables and put it in the AllTables._meta.db_table.
AllTables access all the tables in the DB ( same structure, different table names with different data inside of each table)
Do I need to clear the db_table everytime i go to the selected table?
I have done all the migrations correctly.
Please help me. Thank you in advance.

Updating specific row in SQLAlchemy

I'm using SQLAlchemy with python and i want to update specific row in a table which equal this query:
UPDATE User SET name = 'user' WHERE id = '3'
I made this code by sql alchemy but it's not working:
session.query(User).filter(User.id==3).update({'name': 'user'})
returned this error:
InvalidRequestError: Could not evaluate current criteria in Python. Specify 'fetch' or False for the synchronize_session parameter.
How can i do it?
ormically, you don't use update(), you set attributes:
a_user = session.query(User).filter(User.id == 3).one()
a_user.name = "user"
session.commit()
session.query(User).filter(User.id==3).update({'name':'user'},synchronize_session=False)
This would work. Read about syncrhonize_session in sqlalchemy documentation.

Django - Following a foreign key relationship (i.e JOIN in SQL)

Busy playing with django, but one thing seems to be tripping me up is following a foreign key relationship. Now, I have a ton of experience in writing SQL, so i could prob. return the result if the ORM was not there.
Basically this is the SQL query i want returned
Select
table1.id
table1.text
table1.user
table2.user_name
table2.url
from table1, table2
where table1.user_id = table2.id
My model classes have been defined as:
class Table1(models.Model):
#other fields
text = models.TextField()
user = models.ForeignKey('table2')
class Table2(models.Model):
# other fields
user_name = models.CharField(max_length=50)
url = models.URLField(blank=True, null=True)
I have been through the documentation and reference for querysets, models and views on the django website. But its still not clear on how to do this.
I have also setup the url with a generic list view, but would like to access the user_name field from the second table in the template. I tried select_related in urls.py and also via the shell but it does not seem to work. See examples below.
config in urls
url(r'^$','django.views.generic.list_detail.object_list', { 'queryset': Table1.objects.select_related() }),
At the shell
>>> a = Table1.objects.select_related().get(id=1)
>>> a.id
1
>>> a.user_name
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Table1' object has no attribute 'user_name'
So basically,
What am i doing wrong?
Am i missing something?
What's the best way to pass fields from two tables in the same queryset to your template (So fields from both tables can be accessed)
Can this be done with generic views?
Something like this should work:
u = Table1.objects.get(id=1)
print u.id
print u.user.user_name
If you want to follow a foreign key, you must do it explicitly. You don't get an automatic join, when you retrieve an object from Table1. You will only get an object from Table2, when you access a foreign key field, which is user in this example
select_related() do not add second table result directly to the query, it just "Loads" them, insead of giving to you lazily. You should only use it, when you are sure it can boost your site performance. To get second table you need to write
a.user.username
In Django to get related table you need to follow them through foreign-keys that you have designed. Query itself do not directly translate to SQL query, because it is "lazy". It will execute only SQL that you need and only when you need.
If you have select_related SQL would have been executed at the moment when you do original query for a. But if you didn't have select_related then it would load DB only when you actually execute a.user.username.

Categories