How does PostgreSQL structure an ArrayField like:
class House(models.Model):
people_ids = ArrayField(models.IntegerField(), default=list, blank=True)
in database? Does it generate an auxiliary table with the numbers as Ids and then another table with the Id pairs? Like:
House
Id
Name
1
MyHouse
People
Id
1
2
House_People
House_Id
Person_Id
1
1
1
2
So as to have, for example, people 1 and 2 in house "MyHouse"?
Related
The output could look like this, for example:
id
secondary_id
fk
1
1
1
2
2
1
3
3
1
4
1
2
5
2
2
For context:
(see models below)
I have a commission structure which will have brackets depending on how much a user is earning in a month.
Ideally, I need to know in my Commission Bracket model, the bracket index for a given structure.
Here are my models.
class CommissionStructure(APIBaseModel):
advisor = models.ManyToManyField(AdviserDetail)
name = models.CharField(max_length=20, blank=True, null=True, default='default')
company = models.ForeignKey(Company, on_delete=models.CASCADE)
start_dt = models.DateTimeField(auto_now_add=True)
end_dt = models.DateTimeField(default=timezone.datetime.max)
objects = CommissionStructureManager()
class CommissionBracket(APIBaseModel):
<secondary_id ???>
commission_structure = models.ForeignKey(CommissionStructure, on_delete=models.CASCADE, related_name="brackets")
lower_bound = models.DecimalField(decimal_places=2, default=0.00, max_digits=20, null=True, blank=True)
upper_bound = models.DecimalField(decimal_places=2, default=0.00, max_digits=20, null=True, blank=True)
Please note, I may not have to store it on my model if I can add an annotation to an aggregate set, but my preference is to follow DRY.
Thank you
My suggestion would be to execute custom SQL directly. You can add the secondary id as an integer field in CommissionBracket. Then, you can implement this:
from django.db import connection
def sample_view(request):
...
with connection.cursor() as cursor:
cursor.execute('''
INSERT INTO appname_commissionbracket (
secondary_id,
commission_structure_id
)
SELECT CASE
WHEN MAX(secondary_id)
THEN MAX(secondary_id) + 1
ELSE 1
END AS new_secid, %s
FROM appname_commissionbracket
WHERE commission_structure_id = %s''',
[1, 1] # Sample foreign key value
)
return render(...)
Here we're using INSERT INTO SELECT since we're basing the new record's secondary_id from the same table. We're also adding a CASE so that we can have a fallback value if no record with commission_structure_id value as 1 is returned.
In case you need to populate other columns during create, you can simply include them like so:
INSERT INTO (secondary_id, commission_structure_id, lower_bound, upper_bound)
SELECT CASE ... END AS new_secid, <fk_value>, <lower_bound_value>, <upper_bound_value>
I've found a way to annotate the queryset, but for interest, my original question still remains: how do I add another field partitioned by the foreign key?
brackets = CommissionBracket.objects.select_related("commission_structure")\
.prefetch_related(
'commission_structure__advisor',
'commission_structure__start_dt__gte',
'commission_structure__end_dt__lte',
'commission_structure__company',
'bracket_values'
).filter(
commission_structure__advisor=advisor,
commission_structure__start_dt__lte=date,
commission_structure__end_dt__gte=date,
commission_structure__company=advisor.user.company,
).annotate(index=Window(
expression=Count('id'),
partition_by="commission_structure",
order_by=F("lower_bound").asc()))
I am new to Django and came up with a problem. I have a table like
TABLE
Id Title Type Value
1 A 1 10
2 A 1 20
3 A 2 5
4 A 2 8
5 B 1 1000
Model
class Company(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
value = models.IntegerField()
type = models.SmallIntegerField(default='1')
date = models.DateTimeField(default=timezone.now)
user = models.ForeignKey(User, on_delete=models.CASCADE)
Now from the above table how can I get a value where I sum the value of a similar type and subtract the value from the different type ((A+A)-(A+A)) = 17). Also, I have a value of two types only.
How can I write the query to get the result.
You can aggregate over the model with:
from django.db.models import Q, Sum, Value
from django.db.models.functions import Coalesce
Company.objects.aggregate(
total=(Coalesce(Sum('value', filter=Q(type=1)), Value(0)) -
Coalesce(Sum('value', filter=Q(type=2)), Value(0)))
)['total']
I have a data like shown below, first column protein IDs second column peptide sequence and third column some value I have created a Django model to store this data.
Data table:
A0A075B6K4 YELTQPPSVSTAR 60,10
A0A075B6K4 SYELTQPPSVTAR 2
A0A075B6Q5 EVQLVESGEGSLR 7
A0A075B6S5 DIQMTQSPSGDR 10
A0A0A0MRZ8 EIVLTQSPGER 30,20
A0A0B4J1V0 EVQLVESGGSLR 10
A0A0B4J1X5 EVQLVESGGSLR 0
A0A0B4J2D9 AIQLTQSPSGDR 0
A0A0C4DH42 EVQLVESGGSLR 0
A0A0C4DH55 EIVMTQSPGER 10
A0A0C4DH42 YELTQPPSTAR 20
A0A0C4DH55 YELTQPPSTAR 4
A0A0B4J1X5 YELTQPPSTAR 12
Django models:
from django.db import models
# Create your models here.
class ProteinID(models.Model):
ProtID = models.CharField(max_length=30)
def __str__(self):
return "%s" % (self.ProtID)
class PeptideSeq(models.Model):
sequence = models.CharField(max_length=100)
feq = models.CharField(max_length=100)
protein = models.ForeignKey(ProteinID, on_delete=models.CASCADE)
def __str__(self):
return "%s %s" % (self.sequence, self.feq)
class Meta:
ordering = ['sequence']
Details:
As we can see in the table a single protein ID can hold more then one peptide sequence and single peptide can be associated with more then one protein ID.
I want to add two search option:
if a protein ID entered as a query it should return all the associated peptides and the values from the third column
Query A0A0C4DH55 should return
YELTQPPSTAR 4
EIVMTQSPGER 10
Or a peptide sequence entered as a query it should return all the associated protein id and values from the third column.
Query EVQLVESGGSLR should return
A0A0B4J1V0 10
A0A0B4J1X5 0
A0A0C4DH42 0
How to I implement this?
Thanks
Instead of making proteinID a foreign key in your peptide Model, establish a many to many relationship between Protein and Peptide Models. That way, a protein will have multiple peptides and a peptide can belong to many proteins.
You can get all peptides related to a protein like this
protein = ProteinID.objects.get(ProtID=1)
peptides = protein.peptide_set.all()
Same way you can get the protein of a sine peptide as well.
https://docs.djangoproject.com/en/3.0/topics/db/examples/many_to_many/
1.
ProteinID.objects.get(id='A0A0C4DH55').peptideseq_set.all()
2.
PeptideSeq.objects.filter(sequence='EVQLVESGGSLR').values('protein__ProtID', feq)
I have the following database structure:
Products
--------
id name
1 prodA
2 prodB
Products_Invoices
-----------------
product_id Invoice_id
1 1
2 1
Invoices
--------
id name
1 InvA
2 InvB
Which is most correct way to retrieve all the values of the Products_Invoices table but bring the names of their respective row in parent tables.
Since you stated that you have
products = models.ManyToManyField('Product', blank=True)
You can do the following:
invoices = Invoice.objects.all()
for invoice in invoices:
for product in invoice.products.all():
print(product.name)
For efficiency, you can also prefetch all the products for the invoice using prefetch_related
invoices = Invoice.objects.all().prefetch_related('products')
Model:
class Subjects (models.Model):
name = models.CharField(max_length=100)
places = models.CharField(max_length=100)
class Student (models.Model):
name = models.CharField(max_length=40)
lastname = models.CharField(max_length=80)
subjects = models.ManyToManyField(Subjects, blank=True)
Django creates appname_student_subjects when I use model above.
appname_student_subjects table looks for example, like this:
id | student_id | subjects_id
-----------------------------------------
1 | 1 | 10
2 | 4 | 11
3 | 4 | 19
4 | 5 | 10
...
~1000
How can I access subjects_id field and count how many times subjects_id exists in the table above (and then do something with it). For example: If subject with id 10 exists two times the template displays 2. I know that I should use "len" with result but i don't know how to access subject_id field.
With foreign keys I'm doing it like this in a for loop:
results_all = Students.objects.filter(subject_id='10')
result = len(results_all)
and I pass result to the template and display it within a for loop but it's not a foreign key so it's not working.
You can access the through table directly.
num = (Students.subjects # M2M Manager
.through # subjects_students through table
.objects # through table manager
.filter(student_id=10) # your query against through table
.count())