SQL Query logic to Django ORM Query logic - sql

I have tried to think about how the following SQL query would be structured as a Django ORM query but I have had no luck in my multiple attempts. Can anyone help?
SELECT targets_genetarget.gene, count(targets_targetprediction.gene) as total
FROM targets_genetarget
LEFT OUTER JOIN targets_targetprediction on targets_targetprediction.gene =
targets_genetarget.gene
WHERE list_name LIKE %s
GROUP BY targets_genetarget.gene
class GeneTarget(models.Model):
list_name = models.CharField(max_length=100)
gene = models.CharField(max_length=50)
date_added = models.DateField(auto_now=True)
class Meta:
unique_together = (('list_name', 'gene'),)
def __str__(self):
return self.list_name
class TargetPrediction(models.Model):
specimen_id = models.CharField(max_length=100)
patient_peptide = models.ForeignKey(Peptide, on_delete=models.CASCADE, verbose_name="Peptide", related_name="predictions")
allele = models.ForeignKey(Allele, on_delete=models.CASCADE, verbose_name="Allele", related_name="predictions")
gene = models.CharField(max_length=50)
class Meta:
unique_together = (('specimen_id', 'patient_peptide', 'allele', 'gene'),)
def get_absolute_url(self):
return f'/samples/specid-{self.specimen_id}'
def __str__(self):
return (f'Specimen: {self.specimen_id} Peptide: {self.patient_peptide} Allele: {self.allele} Gene: {self.gene} ')

There's nothing stopping you declaring the TargetPrediction.gene field as a foreign key using the to_field attribute, so you wouldn't need to change the data at all:
class TargetPrediction(models.Model):
...
gene = models.ForeignKey("GeneTarget", to_field="gene")
Now your query simply becomes:
GeneTarget.objects.filter(list_name="whatever").values("gene").annotate(total=Count("targetprediction"))

Related

Django restframework SerializerMethodField background work

I am writing a project in Django with rest framework by using SerializerMethodField. This method makes queries for every row to get data, or View collects all queries and send it to DB? Django can make it as one joint query?
class SubjectSerializer(serializers.ModelSerializer):
edu_plan = serializers.SerializerMethodField(read_only=True)
academic_year_semestr = serializers.SerializerMethodField(read_only=True)
edu_form = serializers.SerializerMethodField(read_only=True)
def get_edu_plan(self, cse):
return cse.curriculum_subject.curriculum.edu_plan.name
def get_academic_year_semestr(self, cse):
semester = cse.curriculum_subject.curriculum.semester
return {'academic_year': semester.academic_year, 'semester': semester}
def get_edu_form(self, cse):
return cse.curriculum_subject.curriculum.edu_form.name
class Meta:
model = CurriculumSubjectEmployee
fields = [
'id',
'name',
'edu_plan',
'academic_year_semestr',
'edu_form'
]
class SubjectViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = SubjectSerializer
def get_queryset(self):
contract = self.request.user.employee.contract
if contract is None:
raise NotFound(detail="Contract not found", code=404)
department = contract.department
cses = CurriculumSubjectEmployee\
.objects\
.filter(curriculum_subject__department=department)
return cses

Django Nested Annotate

I have 3 models
class QuestionsModel(models.Model):
created = models.DateTimeField(auto_now_add=True)
Question = models.CharField(max_length=200)
class AnswersModel(models.Model):
Question = models.ForeignKey(QuestionsModel, related_name='QuestionAnswer')
Answer = models.CharField(max_length=200)
class UsersAnswerModel(models.Model):
Answer = models.ForeignKey(AnswersModel, related_name='UsersAnswer')
RegistrationID = models.CharField(max_length=200)
I am trying to Count How many UsersAnswer the Question
what I tried :
class DashboardAdmin(admin.ModelAdmin):
class Meta:
model = QuestionsModel
change_list_template = 'admin/Dashboard_change_list.html'
date_hierarchy = 'created'
def has_add_permission(self, request):
return False
def changelist_view(self, request, extra_context=None):
response = super().changelist_view(
request,
extra_context=extra_context,
)
try:
qs = response.context_data['cl'].queryset
except (AttributeError, KeyError):
return response
metrics = {
'totalAnswers' : models.Count('QuestionAnswer'),
'totalUsersAnswer' : models.Count(UsersAnswer=OuterRef('QuestionAnswer'))
}
response.context_data['summary'] = list(
qs
.values('Question')
.annotate(**metrics)
.order_by('-totalUsersAnswer')
)
return response
admin.site.register(DashboardModel, DashboardAdmin)
I could not solve
'totalUsersAnswer' : models.Count(UsersAnswer=OuterRef('QuestionAnswer'))
how to count nested foreign key
any help please
class AnswersModel(models.Model):
Question = models.ForeignKey(QuestionsModel, related_name='QuestionAnswer')
Answer = models.CharField(max_length=200)
class UsersAnswerModel(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.PROTECT)
Answer = models.ForeignKey(AnswersModel, related_name='UsersAnswer')
RegistrationID = models.CharField(max_length=200)
Q- How many users answer a Question?
e.g
user_answer = UsersAnswerModel.objects.filter(Answer__question__id=2).count()
You can now annotate based on your need.
Your models need to be renamed
AnswersModel to simply Answer
UsersAnswerModel to UserAnswer and there should be a user entity as a field as I have done above.
3.Fieldnames in model is better lowercased.
I have Solve it by add QuestionAnswer__UsersAnswer
metrics = {
'totalAnswers' : models.Count('QuestionAnswer', distinct=True),
'totalUsersAnswer' : models.Count('QuestionAnswer__UsersAnswer'),
}

get count from related table data in django rest framework

I have two tables
class student(models.Model):
frist_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
class subject(models.Model):
student = models.ForeignKey(student)
sub_name = models.CharField()
I want student list and subject count in serializer
my serializer
classs SubjectSerializers(serializers.ModelSerializer):
class Meta:
model = JobPosting
fields = ('id','sub_name')
class StudentSerializers(serializers.ModelSerializer):
sub = SubjectSerializers(source = 'student')
class Meta:
model = JobPosting
fields = ('id','first_name', 'last_name','sub')
How can i get subject count for every student in serializer, Now i am geting subject table data but i want count like this
"detail": [{
"id": 680,
"first_name": "riya",
"last_name": "tri",
"subject_count": 5
}],
You can achieve this by using a serializer method field
Then StudentSerializer becomes the following:
class StudentSerializers(serializers.ModelSerializer):
sub = SubjectSerializers(source = 'student')
subject_count = serializers.SerializerMethodField()
class Meta:
model = JobPosting
fields = ('id','first_name', 'last_name','sub')
def get_subject_count(self, student):
return Subject.objects.filter(student=student).count()

django left join with null

The model:
class Product(models.Model):
name = models.CharField(max_length = 128)
def __unicode__(self):
return self.name
class Receipt(models.Model):
name = models.CharField(max_length=128)
components = models.ManyToManyField(Product, through='ReceiptComponent')
class Admin:
pass
def __unicode__(self):
return self.name
class ReceiptComponent(models.Model):
product = models.ForeignKey(Product)
receipt = models.ForeignKey(Receipt)
quantity = models.FloatField(max_length=9)
unit = models.ForeignKey(Unit)
def __unicode__(self):
return unicode(self.quantity!=0 and self.quantity or '') + ' ' + unicode(self.unit) + ' ' + self.product.genitive
The idea:
there are a components on stock. I'd like to find out which recipes I can made with components which I have.
It's not easy - but possible - I made a SQL view, which gets the solution. But I'm learning python and Django so I'd like to make it Django-style ;D
The concept of solution:
get the set of recipes which has at last one component:
list_of_available_components = ReceiptComponent.objects.filter(product__in=list_of_available_products).distinct()
list_of_related_receipts = Receipt.objects.filter(receiptcomponent__in = list_of_available_components).distinct()
get recipes (from list_of_related_receipts) which has not at last one component
list_of_incomplete_recipes = (SELECT * FROM drinkbook_receiptcomponent LEFT JOIN drinkstore_stock_products USING(product_id) WHERE drinkstore_stock_products.stock_id IS NULL AND receipt_id IN (SELECT receipt_id FROM drinkbook_receiptcomponent JOIN drinkstore_stock_products USING(product_id)))
get recipes (from list_of_related_receipts) which are not in "list_of_incomplete_recipes"
Heh. How stupid am I. This could be solved much easier. I don't have to find receipes which have at least one component. I can (the same way!) find recipes which i can't do because there is at least one component which i DON'T have.
list_of_unavailable_components = ReceiptComponent.objects.exclude(product__in=list_of_available_products).distinct()
And now.
list_of_available_receipts = Receipt.objects.exclude(receiptcomponent__in = list_of_unavailable_components).distinct()
Simple and clean. Thank you for cooperation ;D

Django ORM equivalent

I have the following code in a view to get some of the information on the account to display. I tried for hours to get this to work via ORM but couldn't make it work. I ended up doing it in raw SQL but what I want isn't very complex. I'm certain it's possible to do with ORM.
In the end, I just want to populate the dictionary accountDetails from a couple of tables.
cursor.execute("SELECT a.hostname, a.distro, b.location FROM xenpanel_subscription a, xenpanel_hardwarenode b WHERE a.node_id = b.id AND customer_id = %s", [request.user.id])
accountDetails = {
'username': request.user.username,
'hostname': [],
'distro': [],
'location': [],
}
for row in cursor.fetchall():
accountDetails['hostname'].append(row[0])
accountDetails['distro'].append(row[1])
accountDetails['location'].append(row[2])
return render_to_response('account.html', accountDetails, context_instance=RequestContext(request))
It would be easier if you post models. But from SQL I'm assuming the models are like this:
class XenPanelSubscription(models.Model):
hostname = models.CharField()
distro = models.CharField()
node = models.ForeignKey(XenPanelHardwareNode)
customer_id = models.IntegerField()
class Meta:
db_table = u'xenpanel_subscription'
class XenPanelHardwareNode(models.Model):
location = models.CharField()
class Meta:
db_table = u'xenpanel_hardwarenode'
Based on these models:
accountDetails = XenPanelSubscription.objects.filter(customer_id = request.user.id)
for accountDetail in accountDetails:
print accountDetail.hostname, accountDetail.distro, accountDetail.node.location