Given the below JSON result from tastypie, I would like to create a new value at check.payments_total which is equal to the total amount of the payments (in this case, 44.00). Any clue on how to do this? I'm completely stumped. payments is a joined foreign key to the check table.
{
"objects": [
{
"check": {
"id": "58a81b36-1ea6-403b-9902-a50cbd13cf2e",
"number": 2,
"payments": [
{
"amount": "5.00",
},
{
"amount": "39.00",
}
]
}
}
]
}
If for the response, then you could override the following method in your resource (the snippet is from tastypie.resources.Resource):
def alter_list_data_to_serialize(self, request, data):
"""
A hook to alter list data just before it gets serialized & sent to the user.
Useful for restructuring/renaming aspects of the what's going to be
sent.
Should accommodate for a list of objects, generally also including
meta data.
"""
return data
just include something like (not tested, consider to be pseudo-code):
total_amount = 0.0
for object in data[ 'objects' ]:
total_amount += object[ 'amount' ]
return { 'objects' : data[ 'objects' ], 'total_amount' : total_amount }
and you should be done.
Related
Using pymongo, I only want to update certain fields of a document if a specific field is greater.
for example, the original document could look something like this for an auction application
{
"_id": ".....",
"highestbid": 100,
"highestbidder": "joe",
"someotherinfo": "...."
}
suppose now a bidder named john outbid joe at 200. How could I use collection.update() to update both the highestbid field and highestbidder field only if the new bid is higher than highestbid, while leaving someotherinfo alone?
I know I can use $max to insert the higher of the two bid values, but I'm not sure how to update highestbidder depending on the result of highestbid all in a single .update(), if it is even possible.
You need to use the operator $lt to verify that old bid is less then the new one to update your document, this should solve your problem:
db.collection.update({
"highestbid": {
"$lt": 200
}
}, {
"$set": {
"highestbid": 200,
"highestbidder": "jhon"
}
}, {
"multi": false
})
Using pymongo:
db.collection.update_one({
"highestbid": {
"$lt": 200
}
}, {
"$set": {
"highestbid": 200,
"highestbidder": "jhon"
}
})
So I have a flattened tree in JSON like this, as array of objects:
[{
aid: "id3",
data: ["id1", "id2"]
},
{
aid: "id1",
data: ["id3", "id2"]
},
{
aid: "id2",
nested_data: {aid: "id4", atype: "nested", data: ["id1", "id3"]},
data: []
}]
I want to gather that tree and resolve ids into data with recursion loops into something like this (say we start from "id3"):
{
"aid":"id3",
"payload":"1",
"data":[
{
"id1":{
"aid":"id1",
"data":[
{
"id3":null
},
{
"id2":null
}
]
}
},
{
"id2":{
"aid":"id2",
"nested_data":{
"aid":"id4",
"atype":"nested",
"data":[
{
"id1":null
},
{
"id3":null
}
]
},
"data":[
]
}
}
]
}
So that we would get breadth-first search and resolve some field into "value": "object with that field" on first entrance and "value": Null
How to do such a thing in python 3?
Apart from all the problems that your structure has in terms of syntax (identifiers must be within quotes, etc.), the code below will provide you with the requested answer.
But you should carefully think about what you are doing, and have the following into account:
Using the relations expressed in the flat structure that you provide will mean that you will have an endless recursion since you have items that include other items that in turn include the first ones (like id3 including id1, which in turn include id3. So, you have to define stop criteria, or be sure that this does not occur in your flat structure.
Your initial flat structure is better to be in the form of a dictionary, instead of a list of pairs {id, data}. That is why the first thing the code below does is to transform this.
Your final, desired structure contains a lot of redundancies in terms of information contained. Consider simplifying it.
Finally, you mentioned nothing about the "nested_data" nodes, and how they should be treated. I simply assumed that in case that exist, further expansion is required.
Please, consider trying to provide a bit of context in your questions, some real data examples (I believe the data provided is not real data, therefore the inconsistencies and redundancies), and try yourself and provide your efforts; that's the only way to learn.
from pprint import pprint
def reformat_flat_info(flat):
reformatted = {}
for o in flat:
key = o["aid"]
del o["aid"]
reformatted[key] = o
return reformatted
def expand_data(aid, flat, lvl=0):
obj = flat[aid]
if obj is None: return {aid: obj}
obj.update({"aid": aid})
if lvl > 1:
return {aid: None}
for nid,id in enumerate(obj["data"]):
obj["data"][nid] = expand_data(id, flat, lvl=lvl+1)
if "nested_data" in obj:
for nid,id in enumerate(obj["nested_data"]["data"]):
obj["nested_data"]["data"][nid] = expand_data(id, flat, lvl=lvl+1)
return {aid: obj}
# Provide the flat information structure
flat_info = [
{
"aid": "id3",
"data": ["id1", "id2"]
}, {
"aid": "id1",
"data": ["id3", "id2"]
}, {
"aid": "id2",
"nested_data": {"aid": "id4", "atype": "nested", "data": ["id1", "id3"]},
"data": []
}
]
pprint(flat_info)
print('-'*80)
# Reformat the flat information structure
new_flat_info = reformat_flat_info(flat=flat_info)
pprint(new_flat_info)
print('-'*80)
# Generate the result
starting_id = "id3"
result = expand_data(aid=starting_id, flat=new_flat_info)
pprint(result)
I am using a third-party API to get data and add it into my database via objects.update_or_create() method. This data has many records and some of the fields in the response only exists for certain records.
Below the a snippet of the JSON that is returned from the API. However this data is only present for some of the records in the JSON response. When I try to add this data into my model, I am getting the following error:
'f_name': i.get('card_faces')[0].get('name'),
TypeError: 'NoneType' object is not subscriptable
I am trying to have it so that if the card_faces field exists, True is added to the card_face column in the database, and then the card_faces name to the database. If card_faces doesn't exist, then False is added to the card_face column in the database, and subsequent fields are null.
JSON:
{
"data": [
{
"name": "Emeria Captain"
},
{
"name": "Emeria's Call // Emeria, Shattered Skyclave",
"card_faces": [
{
"object": "card_face",
"name": "Emeria's Call"
},
{
"object": "card_face",
"name": "Emeria, Shattered Skyclave"
}
]
}
]
}
views.py:
for i in card_data:
Card.objects.update_or_create(
id=i.get('id'),
defaults={
'name': i.get('name'),
'card_faces': i.get('card_faces'),
'f_name': i.get('card_faces')[0].get('name'),
'b_name': i.get('card_faces')[1].get('name'),
}
)
If the card_faces field doesn't exist, then the result of .get('card_faces') will be None, which you can't then call index 0 on
Break apart your line and do a logic check instead - this solution assumes that if card_faces does exist, there will be an index 0 and 1; you haven't provided enough information to assume otherwise
card_faces = i.get('card_faces')
f_name = None
b_name = None
if card_faces:
f_name = card_faces[0].get('name')
b_name = card_faces[1].get('name')
defaults = {
'name': i.get('name'),
'card_faces': True if card_faces else False,
'f_name': f_name,
'b_name': b_name,
}
I am getting data from one collection using python and I will be processing it and storing it in another collection. In the processed collection some of the date fields looks different like Date(-61833715200000).
I use below code to get data and processing it and then I bulk insert the values to new collection.
fleet_managers = taximongo.users.aggregate([{ "$match": { "role" : "fleet_manager"}}])
fleet_managers = pd.DataFrame(list(fleet_managers))
fleet_managers['city_id'] = fleet_managers['region_id'].map({'57ff2e84f39e0f0444000004':'Chennai','57ff2e08f39e0f0444000003':'Hyderabad'})
pros_fleet_managers.insert_many(fleet_managers.to_dict('records'))
The collection looks like this:
{
"_id" : ObjectId("58006678ee5e0e29c5000009"),
"deleted_at" : NaN,
"region_id" : "57ff2e84f39e0f0444000004",
"reset_password_sent_at" : Date(-61833715200000),
"current_sign_in_at" : ISODate("2016-10-14T06:07:55.568Z"),
"last_sign_in_at" : ISODate("2016-10-14T06:07:45.574Z"),
"remember_created_at" : Date(-61833715200000)
}
What did do wrong here. Thanks already.
I have found the solution by using the $ifNull while projecting the fields.
fleet_managers = taximongo.users.aggregate([{ "$match": { "role" : "fleet_manager"}},{"$project":{'_id':1,'deleted_at':{ "$ifNull": [ "$deleted_at", "null" ] },
'reset_password_sent_at':{ "$ifNull": [ "$reset_password_sent_at", "null" ] }, 'region_id':1,'current_sign_in_at':1,'last_sign_in_at':1,'remember_created_at':{ "$ifNull": [ "$remember_created_at", "null" ] }}}])
fleet_managers = pd.DataFrame(list(fleet_managers))
fleet_managers['city_id'] = fleet_managers['region_id'].map({'57ff2e84f39e0f0444000004':'Chennai','57ff2e08f39e0f0444000003':'Hyderabad'})
pros_fleet_managers.insert_many(fleet_managers.to_dict('records'))
The above code gives the solution but I need to handle the null or non existence dynamically i.e., when fetching it from the source collection.
Help me out on this.
Curently I have a viewset of an example Warehouse and I want to pass additional 'filter' list to each dictionary that is returned.
My WarehouseViewSet:
class WarehouseViewSet(viewsets.ReadOnlyModelViewSet):
filters = [{'date': 'Date/Time'}]
queryset = Warehouse.objects.all()
serializer_class = WarehouseSerializer
WarehouseSerializer:
class WarehouseSerializer(serializers.ModelSerializer):
class Meta:
model = Warehouse
field = ('name', 'address', 'action_list')
Currently I get an json list response like:
[
{
"id": 1,
"name": "Brameda Warehouse",
"address": "Bergijk"
},
{
"id": 2,
"name": "Amazon",
"address": "UK"
}
]
I would like to get:
[
{
"id": 1,
"name": "Brameda Warehouse",
"address": "Bergijk"
"filters": [
{'date': 'dateTime'}, {'actove': 'ActiveObject'}
]
},
{
"id": 2,
"name": "Amazon",
"address": "UK",
"filters": [
{'date': 'dateTime'}, {'actove': 'ActiveObject'}
]
}
]
I understand that having one filter is enough outside the objects dictionary, but I would like to know how to pass lists inside objects.
Any ideas how I can pass additional lists that would be returned as json object would be appreaciated.
I feel a bit unclear as to what you want, but if you just want to add some read-only computed field to the output, you can use SerializerMethodField:
class WarehouseSerializer(serializers.ModelSerializer):
# your other declared fields here
filters = serializers.SerializerMethodField()
# your Meta options here
def get_filters(self, obj):
return ['some', 'stuff', 'here', {'and': 'more'}]
The method has to be named get_field_name (there is an option to change it but I don't really see any point using it).
You get the instance being serialized as obj.
You may return anything that is made of regular types (numbers, strings, dicts, lists, tuples, booleans, None).
If the data has to come from outside, you should have the caller add it to the context, and it will be available on self.context['foobar'].