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.
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? 
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) 
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 
Thanks again for all your help, Ken. Learned a lot again from you.
Really appreciate your help
Tom
1 Like