Queryset - How find a word in foreign key in django? - django

How find a word in a foreign key?
There are classes:
class Customers(models.Model):
customer = models.CharField(max_length=255, unique=True)
order = models.ForeignKey('Order')
class Orders(models.Model):
orderName = models.CharField(max_length=255)
There are these records in Customer and order tables:
Order:
+-----+------------------+
| id | orderName |
+-----+------------------+
| 1 | Apple juice |
+-----+------------------+
| 2 | Apple pie |
+-----+------------------+
| 3 | Banana juice |
+-----+------------------+
| 4 | Banana pie |
+-----+------------------+
| 5 | Apple ice cream |
+-----+------------------+
| ... | ... |
+-----+------------------+
Customer:
+-----+----------+-------+
| id | Customer | Order |
+-----+----------+-------+
| 1 | A | 2 |
+-----+----------+-------+
| 2 | B | 3 |
+-----+----------+-------+
| 3 | C | 2 |
+-----+----------+-------+
| 4 | G | 1 |
+-----+----------+-------+
| 5 | H | 1 |
+-----+----------+-------+
| ... | ... | ... |
+-----+----------+-------+
I want to get all the records in the customer table that their orders consist of "Apple".
I wrote these codes:
all_apple_orders = Customer.objects.filter(order='Apple')
I got an error message:
Field expected a number but got 'Apple'.
How should change the code?

You can check if the orderName of the related Orders objects contains that name, for example with:
all_apple_orders = Customer.objects.filter(order__orderName__icontains='Apple')
or for a case sensitive match:
all_apple_orders = Customer.objects.filter(order__orderName__contains='Apple')
or you can make use of a regex with word boundaries:
all_apple_orders = Customer.objects.filter(order__orderName__iregex=r'\bApple\b')
or if you want to only match orders that have 'Apple':
all_apple_orders = Customer.objects.filter(order__orderName='Apple')
or for case insenstive matching:
all_apple_orders = Customer.objects.filter(order__orderName__iexact='Apple')

Span your relationship lookup by using __ (double underscore)
all_apple_orders = Customer.objects.filter(order__orderName__icontains='Apple')
Reference: Lookups that span relationships

Related

Django Query "not in" M2M

I got these three models:
class Crcheck(models.Model):
crlist = models.ForeignKey("crlists.Crlist", on_delete=models.CASCADE)
persons = models.ForeignKey("persons.Person", on_delete=models.CASCADE)
...
| id | crlist_id | persons_id |
| 41 | 2 | 64 |
| 42 | 3 | 64 |
class Cuslistprofile(models.Model):
customer= models.ForeignKey("customers.Customer",on_delete=models.CASCADE)
crlist = models.ManyToManyField("crlists.Crlist")
...
class Crlist(models.Model):
dbname=models.CharField(max_length=200)
...
As a result of the M2M Django generates this table "cuslistprofiles_cuslistprofile_crlist":
| id | cuslistprofile_id | crlist_id |
| 9 | 4 | 2 |
| 13 | 4 | 3 |
| 14 | 4 | 5 |
| 19 | 4 | 7 |
I want to get all the crlist values that are in "cuslistprofiles_cuslistprofile_crlist" but missing in "crcheck". In this particular example I want to retrieve 5 and 7.
How can I achieve that in Django ORM?
You can .filter(…) [Django-doc] with:
Crlist.objects.filter(cuslistprofile__isnull=False, crcheck=None).distinct()
One can use double underscores (__) to look "through" relations.

Aggregate Sum on Django2

I have 2 tables. Table A is
+--+------------------+
| ID | Fastivalname |
+--+------------------+
| 1 | 2020Xmas |
+--+------------------+
| 2 | 2019Xmas |
+--+------------------+
| 3 | 2020Thanksgiving |
+--+------------------+
| 4 | 2019Thanksgiving |
+--+—————————+
Fastival isForeignKey for table B,and table B is
+--+------------------+ ------------------+------------------+
| ID | fastival_name_id | money | useofmoney |
+--+------------------+ ------------------+------------------+
| 1 | 1 | 100 | game
+--+------------------+ ------------------+------------------+
| 2 | 1 | 20 | clothes
+--+------------------+ ------------------+------------------+
| 3 | 3 | 50 | food
+--+------------------+ ------------------+------------------+
| 4 | 4 | 10 | game
+--+------------------+ ------------------+—————————+
| 1 | 2 | 30 | food
+--+------------------+ ------------------+------------------+
| 2 | 3 | 15 | game
+--+------------------+ ------------------+—————————+
and models.py is:
class TableA(models.Model):
Fastivalname = models.CharField(max_length=50)
class TableB(models.Model):
fastival_name = models.ForeignKey(to=TableA, related_name="TableA_Fastival_name", on_delete=models.CASCADE)
money = models.IntegerField(default=0)
useofmoney = models.CharField(max_length=200, null=True, blank=True)
Please someone tell me how to get the "sum of money in game of 2020xxx" in Django2?
I tried context["money"] = TableB.objects.filter(fastival_id=TableA.objects.filter(Fastivalname__startswith=2020.values('id')[0]['id']).filter(useofmoney="game").aggregate(Sum('money'))['money']. But that response "None"...
You can do this with a single query on TableB and use the double-underscore syntax to perform joins/filters on related models/tables
TableB.objects.filter(
fastival__Fastival__startswith='2020',
useofmoney='game'
).aggregate(total=Sum('money'))['total']

Counting the number of items in two mutually exclusive rows of categories

Here is the sheet for testing: https://docs.google.com/spreadsheets/d/11CoQ_PAtVNQBkbtnHH0xR4bhCQVU-pcz645h1akTQuA/edit?usp=sharing
I have a table like this:
| id | category | irrelevant |
|----|----------|------------|
| 1 | cat1 | FALSE |
| 2 | cat2 | FALSE |
| 3 | | TRUE |
| 4 | cat1 | FALSE |
Each item has an ID and a category or, if it is considered irrelevant, it has no category and the column "irrelevant" is marked as TRUE.
What I would like to do is to write a formula that will return the number of items in each category plus a row with the number of irrelevant items. So in the case above the result would be:
| category | number |
|------------|--------|
| cat1 | 2 |
| cat2 | 1 |
| irrelevant | 1 |
If I try something like:
=QUERY(A1:C5,"select B,count(A) group by B")
I get the correct numbers, but since "irrelevant" is not a category its cell is empty, so the result is:
| category | count id |
|----------|----------|
| | 1 |
| cat1 | 2 |
| cat2 | 1 |
Notice the empty "B2" cell. Is there a way to rename it to "irrelevant" without altering the first table? One thing I tried was just to count the irrelevant items.
=transpose(query(A1:C5, "select count(A) where C = TRUE label count(A) 'irrelevant'"))
which returns me simply
| irrelevant | 1 |
And then altering slightly the first formula so it doesn't count the "empty" categories and finally joining both of them in an array:
={
QUERY(A1:C5,"select B,count(A) where B <> '' group by B");
TRANSPOSE(QUERY(A1:C5, "select count(A) where C = TRUE label count(A) 'irrelevant'"))
}
This returns me what I want for the example above
| category | count id |
|------------|----------|
| cat1 | 2 |
| cat2 | 1 |
| irrelevant | 1 |
But this won't work if my original table doesn't have irrelevant items. Which can occur depending on the range I chose to query, so if I want to query a table like this:
| id | category | irrelevant |
|----|----------|------------|
| 5 | cat1 | FALSE |
| 6 | cat2 | FALSE |
| 7 | cat2 | FALSE |
| 8 | cat3 | FALSE |
The solution I found will not work. Any suggestions on how can I do that?
try:
=ARRAYFORMULA(QUERY(IF((B2:B="")*(C2:C<>""), "irrelevant", ),
"select Col1,count(Col21)
where Col1 is not null
group by Col1
label count(Col2)''"))

Find a string in the entire table (all fields, all columns, all rows) in Django

I have a module (table) in my Django app with 24 fields (columns), and I want to search a string in it. I want to see a list that show me which one of the rows has this string in its fields.
Please have a look at this example:
+-----+------+------+---------+------------+------------+------------+-----+-------------+
| id | name | year | country | attribute1 | attribute2 | attribute3 | ... | attribute20 |
+-----+------+------+---------+------------+------------+------------+-----+-------------+
| 1 | Tie | 1993 | USA | Bond | Busy | Busy | ... | Free |
+-----+------+------+---------+------------+------------+------------+-----+-------------+
| 2 | Ness | 1980 | Germany | Free | Busy | Both | ... | Busy |
+-----+------+------+---------+------------+------------+------------+-----+-------------+
| 3 | Both | 1992 | Sweden | Free | Free | Free | ... | Busy |
+-----+------+------+---------+------------+------------+------------+-----+-------------+
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
+-----+------+------+---------+------------+------------+------------+-----+-------------+
| 24 | Lex | 2001 | Russia | Busy | Free | Free | ... | Both |
+-----+------+------+---------+------------+------------+------------+-----+-------------+
What I am looking to get (by using filters, etc.) is something like this: (When I filter the records base on the word "Both" in the entire table and all of the records. Each row that contains "Both" is in the result below)
+----+------+------+---------+------------+------------+------------+-----+-------------+
| id | name | year | country | attribute1 | attribute2 | attribute3 | ... | attribute20 |
+----+------+------+---------+------------+------------+------------+-----+-------------+
| 1 | Ness | 1980 | Germany | Free | Busy | Both | ... | Busy |
+----+------+------+---------+------------+------------+------------+-----+-------------+
| 2 | Both | 1992 | Sweden | Free | Free | Free | ... | Busy |
+----+------+------+---------+------------+------------+------------+-----+-------------+
| 3 | Lex | 2001 | Russia | Busy | Free | Free | ... | Both |
+----+------+------+---------+------------+------------+------------+-----+-------------+
You can see that the string ("Both") appears in different rows in different columns. (one "Both" is under the column "attribute3", the other "Both" is under column "Name", and the last "Both" is under column "attribute20".
How you get this result in Django by queryset?
Thanks
Assuming you have modeled the above table as a Django model named Person
from django.db.models import Q
query_text = "your search string"
Person.objects.filter(
Q(name__contains=query_text) |
Q(year__contains=query_text) |
Q(attribute1__contains=query_text)
and so on for all your attributes
)
The above code will do a case sensitie search. if instead you want it to be case insenssitive search, use name__icontains instead of say name__contains in the above code.
As suggested by #rchurch4 in comment and based on this so answer, here's how one could search the entire table with fewer lines of code:
from functools import reduce
from operators import or_
all_fields = Person._meta.get_fields()
search_fields = [i.name for i in all_fields]
q = reduce(or_, [Q(**{'{}__contains'.format(f): search_text}) for f in search_fields], Q())
Person.objects.filter(q)

django Queryset exclude() multiple data

i have database scheme like this.
# periode
+------+--------------+--------------+
| id | from | to |
+------+--------------+--------------+
| 1 | 2018-04-12 | 2018-05-11 |
| 2 | 2018-05-12 | 2018-06-11 |
+------+--------------+--------------+
# foo
+------+---------+
| id | name |
+------+---------+
| 1 | John |
| 2 | Doe |
| 3 | Trodi |
| 4 | son |
| 5 | Alex |
+------+---------+
#bar
+------+---------------+--------------+
| id | employee_id | periode_id |
+------+---------------+--------------+
| 1 | 1 |1 |
| 2 | 2 |1 |
| 3 | 1 |2 |
| 4 | 3 |1 |
+------+---------------+--------------+
I need to show employee that not in salary.
for now I do like this
queryset=Bar.objects.all().filter(periode_id=1)
result=Foo.objects.exclude(id=queryset)
but its fail, how do filter employee list not in salary?...
Well here you basically want the foos such that there is no period_id=1 in the Bar table.
We can let this work with:
ex = Bar.objects.all().filter(periode_id=1).values_list('employee_id', flat=True)
result=Foo.objects.exclude(id__in=ex)