Boky
Boky

Reputation: 12084

Django Querying database

I'm trying to implement search in django.

My view is as follows :

    search_term = request.GET['search_term']

    customers = Customer.objects.filter(
        Q(chassis__icontains=search_term) | Q(registration__icontains=search_term) |
        Q(email__icontains=search_term) | Q(firstname__icontains=search_term) |
        Q(lastname__icontains=search_term))
    calculations_data = []
    if customers:
        for customer in customers:

            try:
                calculation = Calculations.objects.get(customer=customer, user=request.user)
                calculations_data.append({
                    'calculation': calculation,
                    'price': price_incl_vat(calculation.purchase_price),
                    'customer_fullname': '{} {} '.format(customer.firstname, customer.lastname),
                    'car_chassis': customer.chassis,
                    'car_registration': customer.registration,

                })
            except Calculations.DoesNotExist:
                pass

    context = {'search_term': search_term, 'total_result': len(calculations_data), 'calculation_data': calculations_data}
    return render(request, 'master/search.html', context)

I have two models, calculations and customer. Inside calculation I have customer as ForeignKey, but it can be empty. Thus, every calculation doesn't need to have a customer.

In my example, if I have search term the result is good, but If there is not search term, then I get only the calculations which have a customer.

But what I need is, if there is no search_term, I want to get all calculations.

Is there maybe a better way to write the query?

Thanks.

Upvotes: 1

Views: 111

Answers (2)

narendra-choudhary
narendra-choudhary

Reputation: 4826

Since the results depend on availability of search_term, why aren't you using if-else on search_term.

search_term = request.GET.get('search_term', None)
if search_term:
    # when search term is not None
    # get relevant calculations
else:
    calculations = Calculations.objects.all()
    # rest of code

You can further simplify your code when search_term is not None by putting the Q objects directly in a Calculations.objects.filter() itself (instead of getting relevant customers and then finding the relevant calculations). In Django, you can query on attributes of foreign key in Q objects. You are first fetching Customers and then using those results to find Calculations. That will increase number of queries to database.

You can do something like following:

calculations = Calculations.objects.filter(
                   Q(customer__email__icontains=search_term) | 
                   Q(customer__chassis_icontains=search_term)| 
                   Q(....)).select_related('customer')

Related links:
1. Lookups that span relationships
2. select_related

Upvotes: 1

amit_183
amit_183

Reputation: 981

try this:

if customers:
        try:
            calculations = Calculations.objects.filter(user=request.user)
            if customers:
                calculations=calculations.filter(customer__in=customers)

            for calculation in calculations:
                 calculations_data.append({
                    'calculation': calculation,
                    'price': price_incl_vat(calculation.purchase_price),
                    'customer_fullname': '{} {} '.format(customer.firstname, customer.lastname),
                    'car_chassis': customer.chassis,
                    'car_registration': customer.registration,
                 })
        except Calculations.DoesNotExist:
            pass

Upvotes: 0

Related Questions