retrieving 1000s of rows performace

No?

Terminology and possibly conceptual issue here - there is no “original class”. You don’t “call” classes. You inherit methods and attributes from parent classes. You call methods within a class.

If you’re not familiar or comfortable with the concept of “Objects” in general, or Python classes in particular, I suggest you start with Chapter 9 of the official Python tutorial.

Your view, TestModelListJson, is a subclass of BaseDatatableView. That means that any functions you write for that class have all functions defined within BaseDatatable view available to it.
When you’re calling those methods, you’re not referencing a different class. You’re calling those methods in your class.

1 Like

Sorry Ken, do you mean I should add a function to the TestModelListJson class. Or write a new class using the subclass TestModelListJson

Or is it more defining a new method GET within the existing class?

Sorry for the rubbish questions.

You add the methods you need to add (in this case, prepare_results) to your TestModelListJson class.

Understood. Thank you

Sorry Ken, Im struggling with this. I know i should be able to work this out, but whilst i going through objects and class based views, which i think is going to take me a few days to get my head round any chance you can give me a pointer/part example? :slight_smile:

Hi Ken,

Am I on the right track here?

class TestModelListJson(BaseDatatableView):
    model = Product
    
    def prepare_results(self,data):
        super().prepare_results(data)
        pt = productAPI()
        results=[]
        for item in data:
            p_data = pt.get_product_by_id(item.product_slug)
            price = (p_data['market_data']['current_price']['gbp'])
            results.append({'price':price})
        results.append({results})

I’m a little confused on the args i need to pass into the function. Within the source code the prepare_results function is taking qs in as an arguement and returning data so im assuming i can pass data as an arg and do something.

I think the syntax is correct for super().functionName(args) within parent class (inherited).

This isn’t working, as it seems that there isn’t any data in data being past to def prepare_results(self, data)

That’s a good start, but let’s clear up a couple things:

The prepare_results method takes a queryset as input and returns a list.

So, when you call super, you want to capture the return value so that you can work with it.
e.g. data = super().prepare_results(qs) (Note that I’ve changed the parameter to match the original code - this implies that your method definition should also be def prepare_results(self, qs):)

Now when you iterate over data, you’re working with the output from prepare_results - which either is a list of lists or a list of dicts. You’ll need to figure out what the format is of each row for your specific query, or else use the same type of logic that prepare_results uses to determine how to add data to each row.

For example, if your query results in a list of dicts, then you need to do something like this:

for item in data:
    ...
    item['price'] = price
    results.append(item)

However, if the generated query returns a list of lists, then you would need to do:

for item in data:
    ...
    item.append(price)
    results.append(item)

In either case, at the end of the method, you need to return results.

Thank you, Ken.

I see where I went wrong with this data = super().prepare_results(qs) but can you just confirm the qs is the query set being created from the original code.

...
                if col['search.value']:
                    qs = qs.filter(**{
                        '{0}__{1}'.format(column, filter_method): col['search.value']})
            qs = qs.filter(q)
        return qs

But the orignal prepare_results returns data

    def prepare_results(self, qs):
        data = []
        for item in qs:
            if self.is_data_list:
                data.append([self.render_column(item, column) for column in self._columns])
            else:
                row = {col_data['data']: self.render_column(item, col_data['data']) for col_data in self.columns_data}
                data.append(row)

        return data

But for mine, I should be using qs and not data?

Hope that makes sense?

Yes, the original prepare_data accepts a queryset and returns data.

The very first thing you’re doing in your version of prepare_data is to call the original prepare_data.

So you are going to be passed a queryset as the first parameter - hence you want to call it qs in your definition. You are then going to call the original prepare_data, passing to it the queryset that you received as the first parameter - which would be the exact same qs as it would have received directly had you not overridden that method.

Also keep in mind that the naming here is to maintain consistency and uniformity with the original code. These are all local variables and so the specific names are of no real importance. You could define the method as def prepare_results(self, curling): and the list to be returned as ski_jumping=[]. The names here have no intrinsic significance.

This is really confusing me. (i know that’s not hard) :wink:

The prepare_data function is throwing an error 'dict' object has no attribute 'product_slug', when i loop through:

        for item in data:
            p_data = pt.get_product_by_id(item.product_slug)
            price = (p_data['market_data']['current_price']['gbp'])
            results.append({'price':price})

So I decided to print out the value of item

        for item in data:
            print(item)
...

it returns {'product_name': 'xps', 'product_slug': 'xps'}

Which is a dict ? with 2 keyValue pairs, why is it saying there isn’t attribute product_slug

In previous functions, I can reference the keyValue from item.whatever

You retrieve an attribute from a class using the “dot” notation. You retrieve the value from a dict using the “bracket” notation. e.g. item[‘product_slug’]

Thanks Ken. That’s looking much better.

I’m still not getting data being displayed within the template - It just sits at the processing when rendering the table. Not sure why, but will try to work it out.

Thanks

Tom

It’s working :slight_smile:

Thanks again for all your help, Ken. Learned a lot again from you.

Really appreciate your help

Tom

1 Like