I have the following filter query which is doing an SQL OR statement:
results = Stores.objects.filter(Q(title__icontains=prefs.address1) | Q(title__icontains=prefs.address2))
This works fine but if the prefs.address1 and prefs.address2 values (which come from another model) are blank in mySQL, Django complains with the following error:
Cannot use None as a query value
Is there an elegant way to check to see if my filter values are not blank before constructing the OR filter query?
Many thanks.
You could do this which is easily generalisable to more queries
query = Q()
for search in (prefs.address1, prefs.address2):
if search:
query |= Q(title__icontains=search)
results = Stores.objects.filter(query)
This?
thefilter = Q(title__icontains=prefs.address1)
if prefs.address2 is not None:
thefilter = thefilter | Q(title__icontains=prefs.address2)
results = Stores.objects.filter( thefilter)
Related
I am trying to limit the number of rows displayed in a table filtered using django-filter and build by django-tables2. I did not find anything here or in the docs (I don't want to use pagination).
I know I can slice the queryset but I also want to have the table sortable and can't figure out how to do both.
This is my views.py:
def filtered_table(request):
f = itemFilter(request.GET, queryset=ItemModel.objects.all())
has_filter = any(field in request.GET for field in set(f.get_fields()))
table = None
if has_filter:
if not request.GET.get('sort'):
table = ItemTable(f.qs, order_by='-timestamp')
else:
table = ItemTable(f.qs, order_by=request.GET.get('sort'))
return render(request, 'itemlist/filteredlist.html', {
'itemtable': table,
'filter': f,
})
I tried to slice the queryset before passing it to the table:
table = ItemTable(f.qs.order_by('-timestamp')[:20])
table = ItemTable(f.qs.order_by(request.GET.get('sort'))[:20])
Resulting in:
AssertionError: Cannot reorder a query once a slice has been taken.
Because django-tables2 calls .order_by() again.
Is there a way to configure django-tables2 or manipulate the queryset to limit the displayed rows?
Update:
I tried as suggested, which does not work with my database:
This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
With a slight change this works for me:
f_qs = ItemModel.objects.filter(id__in=list(f_qs_ids))
I think this will now do two queries on the database but that is not a problem for me.
Thank you for answering and pointing me in the right direction. Much appriciated!
This is a bit of a round about way to get there, but you could use your original QuerySet (f.qs), and then take a slice of the obj ids, and then re-filter the original QuerySet with those ids.
# get the 20 ids for the objects you want
f_qs_ids = f.qs.order_by(request.GET.get('sort')).values_list("id", flat=True)[:20]
# create a new queryset by also filtering on the set of 20 ids
f_qs = f.qs.filter(id__in=f_qs_ids)
# pass a legitimate queryset to the table
table = PassTable(f_qs)
I'm new to Django and SQL. I have this following SQL query. How to implement the same in the Django query?
"SELECT DISTINCT C1.CLASSDESC AS CLASS,C2.CLASSCODE AS CODE, C1.CARDCATEGORY AS CATEGORY, C2.CLASSBENEFITS BENEFITS FROM CARDCLASSMAPPING C1,CARDCLASSMASTER C2 WHERE C1.ISACTIVE = 1 AND C2.ISACTIVE = 1 AND C1.CLASSDESC = C2.CLASSDESC AND C1.SCHEMETYPE = ? AND C1.SCHEMECODE = ? AND C1.GLCODE = ? AND C1.ACCOUNTCATEGORY = ? ORDER BY CLASS";
You can go through this link to understand how queries can be constructed in Django. Django provides ORM API to fetch data from your database easily using queries like this:
CardClassMapping.objects.get(id=1)
In order to use the above line of code, you should have a model named CardClassMapping to get the objects from.
Also, you can use raw SQL like this:
CardClassMapping.objects.raw('SELECT DISTINCT C1.CLASSDESC AS CLASS,C2.CLASSCODE AS CODE, C1.CARDCATEGORY AS CATEGORY, C2.CLASSBENEFITS BENEFITS FROM CARDCLASSMAPPING C1')
For more on raw SQL: https://docs.djangoproject.com/en/3.1/topics/db/sql/
I am learning to use SQL alchemy to connect to a mysql database. I want to pull records from the DB that start with a given string. I know that for simple equality all I need to do is this
queryRes = ses.query(Table).filter(Table.fullFilePath == filePath).all()
result = []
How do I do something like this?
queryRes = ses.query(Table).filter(Table.fullFilePath.startsWith(filePath)).all()
result = []
Maybe the query would look like this?
q = ses.query(Table).filter(Table.fullFilePath.like('path%')).all()
SQLAlchemy has a startswith column property, so it works exactly as you'd think:
queryRes = ses.query(Table).filter(Table.fullFilePath.startswith(filePath)).all()
This is the pure SQL:
SELECT * FROM table WHERE field LIKE "string%"
The SQL alchemy is:
q = ses.query(Table).filter(Table.fullFilePath.like('path%')).all()
If you need a case insensitive comparison, use ilike:
session.query(SomeTable).filter(SomeTable.some_column.ilike('bla%')).all()
I am trying to filter a query in mysql alchemy by doing something like this:
query_train = DBSession.query(TokenizedLabel).filter_by(which_disaster!=opts.disaster).all()
But it does not seem to work. Is there a way to filter a query where you are looking for somehting that is not equal to something else -> filter where which_disaster != "irene"
Thanks!
filter_by() cannot handle not equal (!=), use filter() instead:
query_train = DBSession.query(TokenizedLabel).filter(TokenizedLabel.which_disaster!=opts.disaster).all()
I need to perform a raw sql on multiple tables. I then render the result set. For one table I would do:
sql = "select * from my_table"
results = my_table.objects.raw(sql)
For multiple tables I am doing:
sql = "select * from my_table, my_other_table where ...."
results = big_model.objects.raw(sql)
But, do I really need to create a table/model/class big_model, which contains all fields that I may need? I will never actually store any data in this "table".
ADDED:
I have a table my_users. I have a table my_listings. These are defined in Models.py. The table my_listings has a foreign key to my_users, indicating who created the listing.
The SQL is
"select user_name, listing_text from my_listings, my_users where my_users.id = my_listings.my_user_id".
I want this SQL to generate a result set that I can use to render my page in django.
The question is: Do I have to create a model that contains the fields user_name and listing_text? Or is there some better way that still uses raw SQL (select, from, where)? Of course, my actual queries are more complicated than this example. (The models that I define in models.py become actual tables in the database hence the use of the model/table term. Not sure how else to refer to them, sorry.) I use raw sql because I found that python table references only work with simple data models.
This works. Don't know why it didn't before :( From Dennis Baker's comment:
You do NOT need to have a model with all the fields in it, you just need the first model and fields from that. You do need to have the fields with unique names and as far as I know you should use "tablename.field as fieldname" to make sure you have all unique fields. I've done some fairly complex queries with 5+ tables this way and always tie them back to a single model. –
2 . Another solution is to use a cursor. However, a cursor has to be changed from a list of tuples to a list of dictionaries. I'm sure there are cleaner ways using iterators, but this function works. It takes a string, which is the raw sql query, and returns a list which can be rendered and used in a template.
from django.db import connection, transaction
def sql_select(sql):
cursor = connection.cursor()
cursor.execute(sql)
results = cursor.fetchall()
list = []
i = 0
for row in results:
dict = {}
field = 0
while True:
try:
dict[cursor.description[field][0]] = str(results[i][field])
field = field +1
except IndexError as e:
break
i = i + 1
list.append(dict)
return list
you do not need a model that includes the fields that you want to return from your raw sql. If you happen to have a model that actually has the fields that you want to return from your raw sql then you can map your raw sql output to this model, otherwise you can use cursors to go around models altogether.