Trying to convert Left Join of SQL into Django query-set? - python

here is my models.py file
class Customer(models.Model):
"""All Customers details goes here"""
name = models.CharField(max_length=255, null=False)
firm_name = models.CharField(max_length=255, null=False)
email = models.EmailField(null=False)
phone_number = models.CharField(max_length=255, null=False)
location = models.CharField(max_length=255,null=True)
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
"""Meta definition for Customer."""
verbose_name = 'Customer'
verbose_name_plural = 'Customers'
def __str__(self):
"""Unicode representation of Customer."""
return self.name
class Order(models.Model):
"""All order details goes here.It has OneToMany relationship with Customer"""
STATUS = (
('CR', 'CR'),
('DR', 'DR'),
)
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
bill_name = models.CharField(max_length=255, null=False)
payment_date=models.DateField(auto_now=False)
status = models.CharField(max_length=255, choices=STATUS, null=False)
amount = models.FloatField(max_length=255, null=False)
date_created = models.DateTimeField(auto_now_add=True)
description = models.TextField(null=True)
class Meta:
"""Meta definition for Order."""
verbose_name = 'Order'
verbose_name_plural = 'Orders'
def __str__(self):
"""Unicode representation of Order."""
return self.bill_name
i want to access only Customer's name and all fields of Order,in short i want to convert the following SQL in Django Query-set
select name ,bill_name ,status from accounts_customer left join
accounts_order on accounts_customer.id = accounts_order.customer_id
where accounts_order.status="DR";

To attach the customer's name on the order object, you can use annotate with an F expression. https://docs.djangoproject.com/en/3.0/ref/models/expressions/#using-f-with-annotations
orders = Order.objects.annotate(
customer_name=F('customer__name')
).filter(status='DR')
for order in orders:
print(order.customer_name)
If you suspect you will want to access more customer attributes, you may want to select_related (slightly more memory, larger query). What's the difference between select_related and prefetch_related in Django ORM?
orders = Order.objects.select_related('customer').filter(status='DR')
for order in orders:
print(order.customer.name)

You can perform join operation using two ways:
1st: via using select_related
I.e. Order.objects.select_related('customer')
And
2nd: via using filter:
I.e. Order.objects.filter(status__iexact="DR")

Related

django getting all objects from select

I also need the field (commentGroupDesc) from the foreign keys objects.
models.py
class commentGroup (models.Model):
commentGroup = models.CharField(_("commentGroup"), primary_key=True, max_length=255)
commentGroupDesc = models.CharField(_("commentGroupDesc"),null=True, blank=True, max_length=255)
def __str__(self):
return str(self.commentGroup)
class Meta:
ordering = ['commentGroup']
class Comment (models.Model):
commentID = models.AutoField(_("commentID"),primary_key=True)
commentUser = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
commentGroup = models.ForeignKey(commentGroup, on_delete=models.CASCADE, null=True)
commentCI = models.ForeignKey(Servicenow, on_delete=models.CASCADE, null=True)
commentText = RichTextField(_("commentText"), null=True, blank=True)
commentTableUpdated = models.CharField(_("commentTableUpdated"), null=True, blank=True, max_length=25)
def __str__(self):
return str(self.commentGroup)
class Meta:
ordering = ['commentGroup']
views.py
comment = Comment.objects.get(pk=commentID)
Here I get the commentGroup fine but I also need commentGroupDesc to put into my form.
At first, it's not a good thing to name same your model field as model name which is commentGroup kindly change field name, and run migration commands.
You can simply use chaining to get commentGroupDesc, also it's better to use get_object_or_404() so:
comment = get_object_or_404(Comment,pk=commentID)
group_desc = comment.commentGroup.commentGroupDesc
Remember to change field and model name first.

Django complex filter with two tables

I am in need of some help. I am struggling to figure this out.
I have two models
class Orders(models.Model):
order_id = models.CharField(primary_key=True, max_length=255)
channel = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return str(self.order_id)
class Meta:
managed = False
db_table = 'orders'
class OrderPaymentMethods(models.Model):
id = models.CharField(primary_key=True, max_length=255)
payment_type = models.CharField(max_length=75, blank=True, null=True)
fk_order = models.ForeignKey('Orders', models.DO_NOTHING, blank=True, null=True)
class Meta:
managed = False
db_table = 'order_payment_methods'
My goal is to count the number of orders that have a OrderPaymentMethods specific payment_type
Example:
orders = Orders.object.filter(Q(channel="Green_House"))
method_money = orders.filter(payment_methods = "credit").count()
How can I get the count based on the orders that were filtered?
Thank You
You don't need Q nor separating such query. You need to use relation lookup:
Orders.object.filter(channel="Green_House", orderpaymentmethods_set__payment_type="credit").count()

Django Rest Framework: How to get instance of related foreign key

Note: IF INFORMATION BELOW IS NOT CLEAR TO UNDERSTAND - PLEASE ASK ME, I WILL UPDATE AND POST INFORMATION YOU NEED | It is important for me
In Warehouse(models.Model) I have amount attribute and
in ChosenProduct(models.Model) - quantity
I'm trying to get amount in Warehouse through chosen_products instance in App_formSerializer to add the quantity of chosen_product
But I can not get the chosen_products objects from instance
--> below Out:
class WarehouseSerializer(serializers.ModelSerializer):
category_name = serializers.ReadOnlyField(
source='category_product.category_name')
posted_user = serializers.ReadOnlyField(
source='posted_user.username')
class Meta:
model = Warehouse
fields = ['id', 'category_product', 'category_name', 'condition',
'product_name', 'amount', 'barcode', 'f_price', 'created_at', 'updated_at', 'posted_user']
class ChosenProductSerializer(serializers.ModelSerializer):
product_info = WarehouseSerializer(source='product', read_only=True)
period_info = Product_periodSerializer(source='period', read_only=True)
class Meta:
model = ChosenProduct
exclude = ('app_form',)
class App_formSerializer(serializers.ModelSerializer):
chosen_products = ChosenProductSerializer(many=True)
def update(self, instance, validated_data):
instance.terminated = validated_data.get('terminated', instance.terminated)
if instance.terminated == True :
print('-----------TRUE--------------------')
print(instance.chosen_products)
print('-----------PRINT--------------------')
instance.save()
return instance
class Meta:
model = App_form
fields = '__all__'
Out
-----------TRUE--------------------
creditapi.ChosenProduct.None
-----------PRINT--------------------
QUESTION UPDATED
models.py
class Warehouse(models.Model):
category_product = models.ForeignKey(
Category_product, on_delete=models.CASCADE)
product_name = models.CharField(max_length=200, unique=True)
condition = models.BooleanField(default=False)
amount = models.IntegerField()
barcode = models.BigIntegerField()
f_price = models.CharField(max_length=255, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
posted_user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
def __str__(self):
return self.product_name
class App_form(models.Model):
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,12}$', message="Phone number must be entered in the format: '998981234567'. Up to 12 digits allowed.")
terminated = models.BooleanField(default=False)
name = models.CharField(max_length=150)
phone_number = models.CharField(validators=[phone_regex], max_length=13)
def __str__(self):
return self.surname
class ChosenProduct(models.Model):
product = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
quantity = models.IntegerField()
app_form = models.ForeignKey(App_form, on_delete=models.CASCADE, related_name='chosen_products')
def __str__(self):
return self.product.product_name
If you write instance.chose_products you access the manager, not the QuerySet that contains the items. You can use .all() to obtain the QuerySet with all the objects:
print(instance.chosen_products.all())
If you access a ForeignKey in reverse, you have a manager, since zero, one, or more elements can refer to the instance.
You can for example aggregate over the chose_products, for example if you want to retrieve the number of related chose_products, you can use:
print(instance.chosen_products.count())
I would however advise not store (aggregated) data in the App_form, but aggregate data when you need it. Data duplication is an anti-pattern, and it turns out it is hard to keep data in sync.

Convert SQL query set into Django Model Query-set?

I want to convert the following query of SQL into Django Query-set:-
select sum(amount) from accounts_order where status='Pending' and
customer_id=1;
here is my models.py file
from django.db import models
Create your models here.
class Customer(models.Model):
"""All Customers details goes here"""
name = models.CharField(max_length=255, null=False)
email = models.EmailField(null=False)
phone_number = models.CharField(max_length=255, null=False)
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
"""Meta definition for Customer."""
verbose_name = 'Customer'
verbose_name_plural = 'Customers'
def __str__(self):
"""Unicode representation of Customer."""
return self.name
class Order(models.Model):
"""All order details goes here.It has OneToMany relationship with Customer"""
STATUS = (
('Pending', 'Pending'),
('Done', 'Done'),
)
customer = models.ForeignKey(
Customer, null=True, on_delete=models.SET_NULL)
bill_name = models.CharField(max_length=255, null=False)
status = models.CharField(max_length=255, choices=STATUS, null=False)
amount = models.FloatField(max_length=255, null=False)
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
"""Meta definition for Order."""
verbose_name = 'Order'
verbose_name_plural = 'Orders'
def __str__(self):
"""Unicode representation of Order."""
return self.bill_name
You can use a .aggregate(…) [Django-doc] here:
from django.db.models import Sum
Order.objects.filter(
status='Pending', customer_id=1
).aggregate(total_amount=Sum('amount'))['total_amount']

Pulling Data From Multiple Tables in Django

I'm kind of new to Django and am having some trouble pulling from existing tables. I'm trying to pull data from columns on multiple joined tables. I did find a solution, but it feels a bit like cheating and am wondering if my method below is considered proper or not.
class Sig(models.Model):
sig_id = models.IntegerField(primary_key=True)
parent = models.ForeignKey('self')
state = models.CharField(max_length=2, db_column='state')
release_id = models.SmallIntegerField(choices=releaseChoices)
name = models.CharField(max_length=255)
address = models.CharField(max_length=255, blank=True)
city = models.CharField(max_length=255, blank=True)
zip = models.CharField(max_length=10, blank=True)
phone1 = models.CharField(max_length=255, blank=True)
fax = models.CharField(max_length=255, blank=True)
email = models.EmailField(max_length=255, blank=True)
url = models.URLField(max_length=255, blank=True)
description = models.TextField(blank=True)
contactname = models.CharField(max_length=255, blank=True)
phone2 = models.CharField(max_length=255, blank=True)
ratinggroup = models.BooleanField()
state_id = models.ForeignKey(State, db_column='state_id')
usesigrating = models.BooleanField()
major = models.BooleanField()
class Meta:
db_table = u'sig'
class SigCategory(models.Model):
sig_category_id = models.IntegerField(primary_key=True)
sig = models.ForeignKey(Sig, related_name='sigcategory')
category = models.ForeignKey(Category)
class Meta:
db_table = u'sig_category'
class Category(models.Model):
category_id = models.SmallIntegerField(primary_key=True)
name = models.CharField(max_length=255)
release_id = models.SmallIntegerField()
class Meta:
db_table = u'category'
Then, this was my solution, which works, but doesn't quite feel right:
sigs = Sig.objects.only('sig_id', 'name').extra(
select = {
'category': 'category.name',
},
).filter(
sigcategory__category__category_id = categoryId,
state_id = stateId
).order_by('sigcategory__category__name', 'name')
Now since the items in filter() join the sigcategory and category models, I was able to pull category.name out by using extra(). Is this a proper way of doing this? What if I did not have the reference in filter() and the join did not take place?
SigCategory has a ForeignKey pointing at Category, so you can always get from the SigCategory to the Category simply by doing mysigcategory.category (where mysigcategory is your instance of SigCategory.
If you haven't previously accessed that relationship from that instance, doing it here will cause an extra database lookup - if you're concerned about db efficiency, look into select_related.

Categories