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.
Related
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']
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
py which looks like below
class Scenes(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class Tech(models.Model):
tech = models.CharField(max_length=30)
scenario = models.ManyToManyField('Scenes')
def __str__(self):
return self.tech
class UserLog(models.Model):
tech_id = models.ForeignKey(Tech, on_delete=models.CASCADE)
....#other fields
It generates one extra table called pages_tech_scenario (pages is my app name)
My populated tables in database (postgres) looks like below
pages_tech_scenario
id | tech_id | scenes_id
----+---------+-----------
1 | 1 | 1
4 | 2 | 1
5 | 2 | 2
6 | 2 | 3
7 | 2 | 4
8 | 2 | 5
9 | 3 | 3
10 | 4 | 1
11 | 4 | 2
12 | 4 | 3
pages_scenes
id | name
----+----------
1 | poweron
2 | poweroff
3 | sleep
4 | wakeup
5 | switch
pages_tech
id | tech
----+------
2 | CDMA
3 | GSM
4 | 5G
1 | LTE
pages_userlog
id | data_location | pc | username | target | data_type | description | status | submission_time | upload_now | string_submission_time | tech_id_id
----+------------------------------------------------------+---------+----------+--------+-----------+-------------+-------------+-----------------------+------------+------------------------+------------
39 | C:\My Files\testFolder | lab0128 | ananagra | SDX55 | crash | | In Progress | 2020_02_12_T_17_45_04 | f | | 2
19 | C:\My Files\testFolder | lab0034 | sujaraj | SDX55 | crash | | In Progress | 2020_02_12_T_15_46_59 | f | 111 | 1
Here, for pages_userlog first entry id=39 has tech_id_id is 2 which is equivalent to CDMA. While entering the form, I had selected one of the scenario (say sleep) field of CDMA (as CDMA points to all 5 scenarios, can be seen from pages_tech_scenario table).
How can I retrieve only sleep scenario from CDMA instead of all the scenarios its pointing to?.
How to get the id from pages_tech_scenario by specifying tech_id and scenes_id?.
You can name the field from UserLog:
tech = models.ForeignKey(Tech, on_delete=models.CASCADE)
This way you can reference the id by tech_id instead of tech_id_id
How can I retrieve only sleep scenario from CDMA instead of all the
scenarios its pointing to?.
UserLog.objects.get(pk=1).tech.scenario.get(name="sleep")
How to get the id from pages_tech_scenario by specifying tech_id and
scenes_id?.
Tech.scenario.through.objects.get(tech_id=tech_id, scenes_id=scenes_id).id
I have two models :
class Actors(models.Model):
name = models.CharField(max_length=128)
...
class Movies(models.Model)
title = models.CharField(max_length=128)
casting = models.ManyToManyField("actors.Actors", related_name="casting")
...
I am looking for ordering actors by using the number of movies they played in.
Django autogenerated a table with actors_id and movies_id, named movies_movies_casting :
+-----+-----------+-----------+
| id | movies_id | actors_id |
+-----+-----------+-----------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 3 | 1 |
...
Here actor #1 played in movies #1, #2 and #3. And actor #2 played only in movie #1.
Here is the request used in MySQL to get what I want :
SELECT actors_id, COUNT(movies_id) as count FROM movies_movies_casting GROUP BY actors_id ORDER BY count;
The result is :
+-----------+-------+
| actors_id | count |
+-----------+-------+
| 15 | 29 | // actor #15 played in 29 movies
| 12 | 21 |
| 24 | 17 |
| 3 | 16 |
| 20 | 15 |
| 21 | 14 |
...
What is the request used in Django to get this result ?
Try this,
from django.db.models import Count
Movies.objects.values('casting'
).annotate(
count=Count('id')).order_by('-count')
I have given two tables and its models.
mysql> SELECT gid, sk, source from datagen_gidskmap limit 10;
+-----+------+----------+
| gid | sk | source |
+-----+------+----------+
| 1 | 3829 | smsarena |
| 2 | 623 | smsarena |
| 3 | 1308 | smsarena |
| 4 | 1747 | smsarena |
| 5 | 1827 | smsarena |
| 6 | 1218 | smsarena |
| 7 | 2957 | smsarena |
| 8 | 3468 | smsarena |
| 9 | 2580 | smsarena |
| 10 | 2579 | smsarena |
+-----+------+----------+
10 rows in set (0.00 sec)
class GidSkMap(models.Model):
gid = models.AutoField(primary_key=True)
sk = models.CharField(max_length=256)
source = models.CharField(max_length=64)
creation_date = models.DateTimeField(auto_now_add=True)
modification_date = models.DateTimeField(auto_now=True)
def __unicode__(self):
return u'%s' % self.gid
class Meta:
unique_together = ("sk", "source")
mysql> SELECT id, gid_id, nm from datagen_crawlmeta limit 10;
+----+--------+----------------------------+
| id | gid_id | nm |
+----+--------+----------------------------+
| 1 | 1 | votes |
| 2 | 1 | performance_rating |
| 3 | 1 | title |
| 4 | 1 | specs__Sound__Loudspeaker |
| 5 | 1 | specs__Sound__3.5mm jack |
| 6 | 1 | specs__Sound__Alert types |
| 7 | 1 | specs__Sound__unknown0 |
| 8 | 1 | specs__Features__Java |
| 9 | 1 | specs__Features__Messaging |
| 10 | 1 | specs__Features__Colors |
+----+--------+----------------------------+
10 rows in set (0.00 sec)
class CrawlMeta(models.Model):
gid = models.ForeignKey(GidSkMap)
nm = models.CharField(max_length=256)
val = models.TextField()
modification_date = models.DateTimeField(auto_now=True)
def __unicode__(self):
return u'%s' % self.gid
class Meta:
unique_together = ("gid", "nm")
While viewing the CrawlMeta model in the django admin interface,
I would like to have a filter based on "source"(Eg: smsarena) which can be accessed
via gid (which is a foriegn key in CrawlMeta and primary_key in GidSkMap).
Any help would be appreciated.
list_filter accepts queryset API style field lookups. in this case you would use:
class YourAdmin:
list_filter = ["gid__source", ... ]
list_display = ["gid_source", ... ]