Django Model is not JSON serializable - python

Im trying to return a dictionary of Django models in JSON format.
I have tried serializers, model_to_dict, json.dump and can't seem to get it working.
a small snippet of the code:
def get_queryset(self):
queryset = (Venue.objects.all())
location = self.request.query_params.get('location', None)
latitude = location.split('S')[0]
longitude = location.split('S')[1]
venue_gaps = {}
for venue in queryset.iterator():
locationArray = [y.strip() for y in venue.postcode.split(',')]
distance = gmaps.distance_matrix([str(latitude) + " " + str(longitude)], [str(locationArray[0]) + " " + str(locationArray[1])], mode='driving')['rows'][0]['elements'][0]
m = distance["distance"]["value"]
venue_gaps[m] = venue
sorted_venues = dict(sorted(venue_gaps.items()))
return JsonResponse(json.dumps(sorted_venues))
the dictionary I create is a {int:object, int:object, int:object, ....}
I want this to be returned as the response. I keep getting issues such as "TypeError: Object of type object is not JSON serializable"

Use django.core.serializers:
from django.core import serializers
qs = YourModel.objects.filter(foo='bar')
serialized_qs = serializers.serialize('json', qs)
print(serialized_qs)
Docs: https://docs.djangoproject.com/en/2.2/topics/serialization/

Simpler issue I believe:
return JsonResponse(json.dumps(sorted_venues))
is redundant, this should work:
return JsonResponse(sorted_venues)

Related

django-import-export append column to imported .xlsx [duplicate]

Im trying to import some data from a csv file to a django database using django-import-export, with a foreign key (location). What I want to achieve is, that the location_id is passed by the request url.
value,datetime,location
4.46,2020-01-01,1
4.46,2020-01-02,1
My urls look like this, so I want "location_id" to be passed into the uploaded csv file:
urlpatterns = [
...
...
path('..../<int:location_id>/upload', views.simple_upload, name='upload'),
]
My view looks like this:
def simple_upload(request, location_id):
if request.method == 'POST':
rainfall_resource = RainfallResource()
dataset = Dataset()
new_rainfall = request.FILES['myfile']
imported_data = dataset.load(new_rainfall.read().decode("utf-8"), format="csv")
try:
result = rainfall_resource.import_data(dataset, dry_run=True) # Test the data import
except Exception as e:
return HttpResponse(e, status=status.HTTP_400_BAD_REQUEST)
if not result.has_errors():
rainfall_resource.import_data(dataset, dry_run=False) # Actually import now
return render(request, '/import.html')
My ModelResource looks like this:
class RainfallResource(resources.ModelResource):
location_id = fields.Field(
column_name='location_id',
attribute='location_id',
widget=ForeignKeyWidget(Location, 'Location'))
class Meta:
model = Rainfall
def before_import_row(self, row, **kwargs):
row['location'] = location_id
The manipulation works when I hardcode "location_id" like:
def before_import_row(self, row, **kwargs):
row['location'] = 123
However, I do not understand how to pass the location_id argument from the "url" to the "before_import_row" function. Help would be highly appreciated:-)
I think you will have to modify your imported_data in memory, before importing.
You can use the tablib API to update the dataset:
# import the data as per your existing code
imported_data = dataset.load(new_rainfall.read().decode("utf-8"), format="csv")
# create an array containing the location_id
location_arr = [location_id] * len(imported_data)
# use the tablib API to add a new column, and insert the location array values
imported_data.append_col(location_arr, header="location")
By using this approach, you won't need to override before_import_row()

Q: Simple-Salesforce make a dynamic soql query

Was trying to figure out a way to get simple salesforce to just give me all the field names in a list. I want to create soql query that pretty much does the same thing as a Select * does in sql.
for obj in objects:
fields = [x["name"] for x in sf[obj].describe()["fields"]]
thanks
A list of field names in an object can be achieved as follow:
def getObjectFields(obj):
fields = getattr(sf,obj).describe()['fields']
flist = [i['name'] for i in fields]
return flist
getObjectFields('Contact')
Your query to get the effect of SELECT * would then look something like this:
sf.query_all('SELECT {} FROM Contact LIMIT 10'.format(','.join(getObjectFields('Contact'))))
On a related note:
In case it is helpful, a dictionary of label/name pairs can be achieved as follows:
def getObjectFieldsDict(obj):
fields = getattr(sf,obj).describe()['fields']
fdict = {}
for i in fields:
fdict[i['label']] = i['name']
return fdict
getObjectFieldsDict('Contact')
I find this can be useful for figuring out the names of fields with labels that do not follow the standard format (i.e. "My Favorite Website" field label for "Favorite_Website__c" field name)
This method will return a query string with all fields for the object passed in. Well all the fields the user has access to.
public static string getFullObjectQuery(String sObjectName){
Schema.SObjectType convertType = Schema.getGlobalDescribe().get(sObjectName);
Map<String,Schema.sObjectField> fieldMap = convertType.getDescribe().Fields.getMap();
Set<String> fields = fieldMap.keySet();
String Query = 'SELECT ';
for(String field: fields){
Schema.DescribeFieldResult dfr = fieldMap.get(field).getDescribe();
if(dfr.isAccessible()){
Query += field + ',';
}
}
Query = query.SubString(0,Query.length() - 1);
Query += ' FROM ' + sObjectName;
return Query;
}
#!/usr/bin/env python3
import argparse
import os
import simple_salesforce
parser = argparse.ArgumentParser()
parser.add_argument('--sandbox', action='store_true',
help='Use a sandbox')
parser.add_argument('sfobject', nargs='+', action='store',
help=('Salesforce object to query (e.g. Contact)'))
args = parser.parse_args()
sf = simple_salesforce.Salesforce(
username = os.getenv('USERNAME'),
password = os.getenv('PASSWORD'),
security_token = os.getenv('SECURITY_TOKEN'),
sandbox = args.sandbox)
for sfobject in args.sfobject:
print(sfobject)
fields = [x['name'] for x in getattr(sf, sfobject).describe()['fields']]
print(fields)

Creating new table while iterating through a queryset in django

This is a newbie question, but despite reading https://docs.djangoproject.com/en/dev/ref/models/instances/#saving-objects , I'm not quite sure how to do this. I have an existing table where I would like to iterate through all its records, and save certain info to a second table. I have the following model:
class myEmails(models.Model):
text = models.CharField(max_length=1200)
In my view I have:
def getMyMessages(request):
from django_mailbox.models import Message
from get_new_emails.models import myEmails
import re
qs = Message.objects.all()
count = 0
output = ""
for i in qs:
count += 1
output = output + str(count) + " TEXT: " + i.text + '<br>' + '<br>'
return HttpResponse(output)
How can I modify my view to save "i.text" to the text field of the 'myEmails' table
You can create new objects and save them to the database afterwards using save():
for i in qs:
obj = myEmails(text=i.text)
obj.save()

Serializing ReferenceProperty in Appengine Datastore to JSON

I am using the following code to serialize my appengine datastore to JSON
class DictModel(db.Model):
def to_dict(self):
return dict([(p, unicode(getattr(self, p))) for p in self.properties()])
class commonWordTweets(DictModel):
commonWords = db.StringListProperty(required=True)
venue = db.ReferenceProperty(Venue, required=True, collection_name='commonWords')
class Venue(db.Model):
id = db.StringProperty(required=True)
fourSqid = db.StringProperty(required=False)
name = db.StringProperty(required=True)
twitter_ID = db.StringProperty(required=True)
This returns the following JSON response
[
{
"commonWords": "[u'storehouse', u'guinness', u'badge', u'2011"', u'"new', u'mayor', u'dublin)']",
"venue": "<__main__.Venue object at 0x1028ad190>"
}
]
How can I return the actual venue name to appear?
Firstly, although it's not exactly your question, it's strongly recommended to use simplejson to produce json, rather than trying to turn structures into json strings yourself.
To answer your question, the ReferenceProperty just acts as a reference to your Venue object. So you just use its attributes as per normal.
Try something like:
cwt = commonWordTweets() # Replace with code to get the item from your datastore
d = {"commonWords":cwt.commonWords, "venue": cwt.venue.name}
jsonout = simplejson.dumps(d)

Django JSON serializable error

With the following code below, There is an error saying
File "/home/user/web_pro/info/views.py", line 184, in headerview,
raise TypeError("%r is not JSON serializable" % (o,))
TypeError: <lastname: jerry> is not JSON serializable
In the models code
header(models.Model):
firstname = models.ForeignKey(Firstname)
lastname = models.ForeignKey(Lastname)
In the views code
headerview(request):
header = header.objects.filter(created_by=my_id).order_by(order_by)[offset:limit]
l_array = []
l_array_obj = []
for obj in header:
l_array_obj = [obj.title, obj.lastname ,obj.firstname ]
l_array.append(l_array_obj)
dictionary_l.update({'Data': l_array}) ;
return HttpResponse(simplejson.dumps(dictionary_l), mimetype='application/javascript')
what is this error and how to resolve this?
thanks..
The quick read is that obj.lastname is a Lastname model not a String. You probably need to say something like:
l_array_obj = [..., obj.lastname.value, .... ]
to get the string value, rather than the Model object.
Have you considered using Django's own serialization functionality?

Categories