class Customer(models.Model):
cust_id = models.CharField(max_length=255)
name = models.CharField(max_length=255, blank=True, null=True)
reg_no = models.CharField(max_length=255, blank=True, null=True)
address = models.CharField(max_length=1000, blank=True, null=True)
class ServiceOrder(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=255)
so_number = models.CharField(max_length=255, blank=True, null=True)
SOFs = ServiceOrder.objects.all().order_by('-id')
for sof in SOFs:
try:
customer = Customer.objects.get(id=sof.customer_id)
sof.cust_id = customer.cust_id
sof.reg_no = customer.reg_no
sof.cust_name = customer.name
sof.customer_url = reverse('customers_view', args=[customer.id])
except ObjectDoesNotExist:
sof.cust_id = "N/A"
sof.reg_no = "N/A"
sof.cust_name = "N/A"
sof.customer_url = "#"
How do I get the customer details of a service order in one go and not loop through each of the 2500 SOFs ?
This query is unnecessary.
Inside this loop, sof
is an instance of ServiceOrder
. Each ServiceOrder
has a ForeignKey to Customer
, so sof.custom
is a reference to the Customer
related to that ServiceOrder
. The query is redundant.
For some reason I was getting an error for sof.cust_id = customer.cust_id
Does this make any faster ?
SOFs = ServiceOrder.objects.all().order_by('-id').prefetch_related('customer')
Correct:
Wrong function. Since it’s ServiceOrder
that has the ForeignKey, you want to use select_related
.
Will this improve your original code? No.
Will it improve the performance using the predefined FK reference? Yes.
The issue here is that I have this for Customer model class
def __str__(self):
return self.name + " (" + self.cust_id + ")"
Which model is that __str__
method in?
Customer :
class Customer(models.Model):
cust_id = models.CharField(max_length=255) # Alpha-Numeric Generated ID for the purpose of Sales People
partner_id = models.CharField(max_length=255, blank=True, null=True)
name = models.CharField(max_length=255, blank=True, null=True)
pan = models.CharField(max_length=255, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name + " (" + self.cust_id + ")"
Before I did prefetch_related('customer')
it was this :
SOFs = ServiceOrder.objects.filter(sales_id=userid).order_by('-id')
And sof.customer.cust_id
was not accessible.
You’re going to have to show the full code that was throwing an error, along with the complete traceback. We cannot diagnose general descriptions of problems.
I lost track of where it was happening - I since then edited the code to prefetch_related
and was wondering if there’s a difference between select_related
and prefetch_related
- both seem to work.
Yes, there is a difference - see the docs for them.
However, neither of them are required. They are a purely optional performance enhancement. Their presence (or absence) does not affect the functionality of your code. Adding them does not make something “work”. Removing them doesn’t make anything “not work”.
1 Like