Avoiding multiple queries to display model data on Django admin - python

I am using Django amdin for one of my data models. I want to display customized values on admin UI for each model.
On db, the result of a single query runs as multiple queries on django admin, one for each row
I am trying to avoid that.
Here are my models:
class words(models.Model):
word_id=models.AutoField(primary_key=True)
word=models.CharField(max_length=200,unique=True)
def __unicode__(self):
return '%s - %s' % (self.word,self.word_id)
class meanings(models.Model):
id=models.AutoField(primary_key=True)
word_id=models.ForeignKey(words,on_delete=models.CASCADE,db_column='word_id')
meaning=models.CharField(max_length=200)
def __unicode__(self):
return '%s %s %d ' % ( self.spelling_id.spelling,self.meaning,self.id)
For the second model, while loading the page, for each row I saw there are 2 queries running one on words table and other on meanings table. (from debug toolbar)
I tried avoiding that by using the below option.
models.py:
class meanings(models.Model):
meaning_id=models.AutoField(primary_key=True)
word_id=models.ForeignKey(words,on_delete=models.CASCADE,db_column='word_id')
meaning=models.CharField(max_length=200)
admin.py:
def modified_output(self):
cursor = connection.cursor()
cursor.execute("select word,meaning,id from meanings a,words b where a.word_id=b.word_id and meaning_id= "+str(self.id))
row = dictfetchall(cursor)
a=unicode(row[0]['word'])
b=unicode(row[0]['meaning'])
d=(row[0]['id'])
return '%s %s %d ' % ( a,b,d)
meanings.add_to_class("__str__", modified_output)
Now for each row there is only 1 query running. But as the dependency on models have more than 2 tables in join of a query, it will still consume time. So my question is instead of running 1 query for each row, can we have the query result displayed directly for each page.
for example result of the following query on a page:
select * from table ;
instead of
select * from table when id=1;
select * from table when id=2;
.
.
.
Any help is greatly appreciated.Thanks

You should use the list_select_related option on the ModelAdmin to tell Django to do a JOIN query.
class MeaningAdmin(admin.ModelAdmin):
list_select_related = ('word_id',)
(Note, you really shouldn't call your FK fields things like word_id. The field gives access to an actual instance of Word, so it should just be called word; the underlying db column will automatically be called word_id.)

Related

How to insert data in to multiple table using django orm

i have created 2 table, ie table1 and table2 i want to insert data in to both tables using django ORM , how can i achieve it
models.py
class Table1(models.Model):
name = models.CharField(max_length=20,null=True)
class Table2(models.Model):
name = models.CharField(max_length=20,null=True)
views.py
class Test(ListAPIView):
def get(self,request):
obj1 = Table1(name="jasir")
obj2 = Table2(name="shibin")
obj1.save()
obj2.save()
return Response(True)
im saving like this but i want to save it using single save() instance is there any possiblity
the equivalent sql query i found is
BEGIN TRANSACTION
INSERT INTO Table1 (name) VALUES ('jasir')
INSERT INTO Table2 (name) VALUES ('shibin')
COMMIT TRANSACTION
how to do the same with django ORM
Try making the saves atomic like this:
with django.db.transaction.atomic():
obj1.save()
obj2.save()
you can use Django's transcation.atomic context-manager to do that
Refer to:
https://docs.djangoproject.com/en/2.2/topics/db/transactions/#django.db.transaction.atomic
with transaction.atomic():
# This code executes inside a transaction.
obj1 = Table1(name="jasir")
obj2 = Table2(name="shibin")
obj1.save()
obj2.save()

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.

Does PeeWee support interaction with MySQL Views?

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.

Querying a for table not defined in models Sqlalchemy

I have this table in my database (using Posgresql and Sqlalchemy) called "participants".
In my models.py I want to access the participant's records. Since participants is not in my models.py and resides as a table in my db, when I do query = db.session.query('participants').order_by('name').all() I get an error:
ProgrammingError: (ProgrammingError) column "participants" does not exist
LINE 1: SELECT participants ORDER BY name
^
What can I do to retrieve this information?
Like the comment on the original post, did something like:
query = db.engine.execute('select * from participants order by name')
This doesn't give it in the same format as the query so I could use it for what I needed (a dictionary output, and a format for web), so I did:
partner_list = []
for record in query:
record_dict = dict(record)
partner_list.append(record_dict)

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