TypeError: unhashable type: 'dict' Django - python

I have a very simple dictionary with some data on it:
some_data= {'totalsForAllResults': {'ga:sessions': '11'}, 'profileInfo': {'internalWebPropertyId': '104132673', 'accountId': '67836206', 'profileName': 'My New Cool Site', 'webPropertyId': 'UA-677293506-1', 'profileId': '108628346', 'tableId': 'ga:108372846'},
on my views I have:
sessions = some_data['totalsForAllResults']['ga:sessions']
account_id = some_data['profileInfo']['accountId']
property_id = some_data['profileInfo']['internalWebPropertyId']
property_name = some_data['profileInfo']['profileName']
print(sessions,account_id,property_id,property_name)
return render(request, 'ga_app/report.html', {'sessions':sessions},
{'account_id':account_id},
{'property_id':property_id},
{'property_name':property_name},)
The variables get printed perfectly on my shell, however django doesn't want to pass them to the templates, I keep getting TypeError: unhashable type: 'dict' but I'm sending variables to the template not a dictionary. Why this happens?

Change this:
return render(request, 'ga_app/report.html', {'sessions':sessions},
{'account_id':account_id},
{'property_id':property_id},
{'property_name':property_name},)
to this:
return render(request, 'ga_app/report.html', {'sessions': sessions,
'account_id': account_id,
'property_id':property_id,
'property_name':property_name}
)
You have to pass one dict as the context. You are passing 4 of them!

Related

Unable to get images in list in Django views.py context, Throws List AttributeError

I am using below code to get a list of all image and then display it:
def index(request):
data = cos.list_objects(Bucket='pixmedia')
di = data['Contents']
endpoint="https://s3.us.cloud-object-storage.XXXXX.cloud/XXX/"
#print(di)
image_list=[]
for key in di:
print("Key is--->",key['Key'])
res=key['Key']
res=endpoint + res
print("Res is ---->",res)
#context = {
# 'image': res,
#}
image_list=image_list.append(res)
print("Image List is",image_list)
context = {
{'image_list': image_list,}
}
return render(request, "index.html", context)
But, i am getting below error on launching 127.0.0.1:8000:
image_list=image_list.append(res)
AttributeError: 'NoneType' object has no attribute 'append'. Please Help.
Change image_list=image_list.append(res) to image_list.append(res). You are reassigning image_list but there is no return value for the append method, hence the NoneType error. Lists are mutable so it modifies the list in place.

how to serialize list of form object to JSON in django

I'm trying to serialize the form objects and return to the AJAX call so that I can display them in the template, but I'm not able to serialize them unlike serializing the model objects don't we have an option for form objects
if request.method == 'POST':
temp_data_form = TemplateDataForm(request.POST)
if request.POST.get('temp_id'):
# getting id of the current template
existing_template = Template.objects.filter(id=request.POST.get('temp_id'))[0]
if request.POST.get('item'):
item_query = existing_template.tempdata_set.filter(item=request.POST.get('item'))
if item_query:
item_query = item_query[0] and True
# we only edit the existing object of the template always as we create the object by default on GET request
if existing_template and existing_template.title != request.POST.get('title') and request.POST.get('title')!= None:
existing_template.title = request.POST.get('title')
existing_template.save()
if temp_data_form.is_valid() and item_query != True:
# Template items alias data
td_obj = temp_data_form.save(commit=False)
td_obj.template = existing_template
td_obj.save()
values_form = []
for item in existing_template.tempdata_set.all():
values_form.append(TemplateDataForm(instance=item))
return JsonResponse(values_form, safe=False)
I'm getting the below error.
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type TemplateDataForm is not JSON serializable
Assuming your TemplateDataForm is a Django form, it should have a "cleaned_data" attribute. You need to serialize that data and not the form itself. So for a single form, that would look like the below. Also, cleaned_data is a dictionary, so you can drop the "safe=False" argument.
return JsonResponse(values_form.cleaned_data, safe=False)
However, based on your code, it looks like you are trying to loop through a child object set or multiple forms. So, for that, you would probably want to pre-build the json dictionary response in the loop.
json_response_dict = {}
for item in existing_template.tempdata_set.all():
values_form.append(TemplateDataForm(instance=item))
# Add to your response dictionary here. Assuming you are using
# django forms and each one is a valid form. Your key will
# need to be unique for each loop, so replace 'key' with a
# loop counter such as 'form' + counter or maybe a form instance
# cleaned_data pk. If looping through child set objects, then
# reference the appropriate attribute such as values_form.title.
json_response_dict['key'] = values_form.cleaned_data
return JsonResponse(json_response_dict, safe=False)
Then in javascript, for your response, you would need to access each key.
$.ajax({
method: 'POST',
url: yourURL,
data: yourData
}).always(function (response) {
/* Test viewing the title for a single object in dictionary. Otherwise, loop
* through the response in each dictionary subset to get the keys/values.
*/
alert(response.title);
});

AttributeError: 'InstrumentedList'

I am pretty new to using both SQLALCHEMY and the PYRAMID web framework. I am struggling with what might be a simple fix to some, but I haven't been able to figure it out. I have looked at some posts here on Stacks, but they don't quite answer my issue.
I have a many-to-many relationship in my database table. I am trying to return an object (categories) from the parent table assessment. I am trying at the moment to: return {'name': assessment.name, 'text': assessment.text, 'user': assessment.user_id, 'video':assessment.video_id, 'categories': assessment.categories.assessment_category_link} but this doesn't work --> 'categories': assessment.categories.assessment_category_link
I am able to return all the objects except categories. Below is the relevant error and code.
TRACEBACK:
line 306, in get_assessment
return {'name': assessment.name, 'text': assessment.text, 'user': assessment.user_id, 'video':assessment.video_id, 'categories': assessment.categories.assessment_category_link}
AttributeError: 'InstrumentedList' object has no attribute 'assessment_category_link'
SQLALCHEMY TABLE/RELATIONSHIP:
# MANY-to-MANY
association_table = Table('assessment_category_link', Base.metadata,
Column('assessment_id', Integer, ForeignKey('assessments.assessment_id')),
Column('category_id', Integer, ForeignKey('categories.category_id')))
class Assessment(Base):
# column/entity code
categories = relationship('Category', secondary='assessment_category_link', backref='assessments')
def __init__(self, name, text, user, video, categories):
# CODE
self.categories = categories
The GET() method, specifically the return value that is throwing the error:
#view_config(route_name='assessment', request_method='GET', renderer='json')
def get_assessment(request):
with transaction.manager:
assessment_id = int(request.matchdict['id'])
assessment = api.retrieve_assessment(assessment_id)
if not assessment:
raise HTTPNotFound()
return {'name': assessment.name, 'text': assessment.text, 'user': assessment.user_id, 'video':assessment.video_id, 'categories': assessment.categories.assessment_category_link}
I am not sure what you are trying to achieve since assessment.categories would return a list of Category objects that you need to iterate over. It is logical for such a list not to have an attribute named assessment_category_link (as the exception tells you), and it is not clear to me why you would want to access the association object anyway!
The relationship with the secondary keyword argument is meant to hide this complexity away so that assessment.categories would transparently return the list that you're after.
you can represent the categories list as you like, a suggestion for your case:
{...., 'categories': ', '.join([str(i) for i in assessment.categories])}
The answer above was very close, but the working code is:
{...., 'categories': ','.join([str(i) for i in assessment.categories])}
As suggested by similar Stack question/answer to the same issue: TypeError: sequence item 0: expected string, int found

Python Sql Alchemy - How to jsonify a class object result from a database query

Basically, I just want to json encode the results of my sql query.
x = db.session.query(User).filter_by(username = request.form['username'], password = request.form['password']).first()
print vars(x)
return jsonify(x)
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: < User WashingtonGeorge> is not JSON serializable
Here is the result for the print vars(x)
{'_updated': None, 'username': u'WashingtonGeorge', 'password': u'Washington', '_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7fd12a50c8d0>, 'firstname': u'George', 'lastname': u'Washington', '_created': None, 'fullname': u'George Washington', '_id': 1, 'email': u'WashingtonGeorge#yahoo.com'}
You can use marshallow. Here is the example. define a serializer.py and put it beside your main.py file, and:
in serializer.py
from marshmallow import Serializer
###### USER SERIALIZER #####
class UserSerializer(Serializer):
class Meta:
# Fields to expose
fields = ('username')
# you can add any other member of class user in fields
#Return the user data in json format
def get_user_serialized(user):
return UserSerializer(user).data
in your main.py
from .serializers import get_user_serialized
...
...
...
x = db.session.query(User).filter_by(username = request.form['username'], password = request.form['password']).first()
serialized = [get_user_serialized(item) for item in x]
res = jsonify(res=serialized)
return res
With JSON serialize you can do that.
Look this: http://prschmid.blogspot.com/2012/12/json-serializing-sqlalchemy-objects.html
it work for me
I assume the variable '_updated' & '_created' in your class User are of type DateTime. Datetime is not serilzable in jsonify. You can just convert your datetime variable into str. i.e. str(some_date_in_datetimeformat) might work.
Also, '_sa_instance_state' which is of type sqlalchemy.orm.state.InstanceState should be serializable.
Update:
jsonify is not able to serialize your object. The best solution is to define a function serialize() inside your class and use it to make the data serializable. So your class becomes,
class User(object):
def serialize():
return {
'_id': 1,
'username': u'WashingtonGeorge'
'fullname': u'George Washington'
# other fields that you need in the json
}
then at the place where you want to jsonify the data, just call.
jsonify(x.serialize())

Serializing attributes that are not model fields with Django JSON serializer

Not sure what the difference is but I have two snippets of code that i assume should behave the same.
This works:
channels = RpChannels.objects.using('prod').all().filter(userid=id).order_by('-when')
for channel in channels:
date = channel.t.replace(",","-") if channel.t else "Default"
name = Playlists.objects.using('prod').get(id=channel.p).description if channel.p else "Default"
genres = ', '.join(StTag.objects.values_list('tag', flat = True).filter(id__in=channel.g.split(',')).order_by('tag')) if channel.g else "Default"
when = channel.when if channel.when else "N/A"
setattr(channel, 'channel', name)
setattr(channel, 'genres', genres)
setattr(channel, 'date', date)
setattr(channel, 'when', when)
setattr(channel, 'valence', channel.v if channel.v else "Default")
setattr(channel, 'arousal', channel.a if channel.a else "Default")
context = {'st_user': user,
'devices': devices,
'feedback': feedback,
'stations': stations,
'channels': channels}
return render(request, 'user.html', context)
This doesn't:
tracks = Songplays.objects.using('prod').all().filter(user=id, when__gt=start, when__lt=end).order_by('-when')
for item in tracks:
track = Track.objects.get(id=item.trackid)
artist = Artist.objects.get(id=track.artist_id).name
title = TrackTitle.objects.get(id=track.id).title
setattr(item, 'duration', str(datetime.timedelta(seconds=track.duration)) if track.duration else "N/A")
setattr(item, 'title', title)
setattr(item, 'artist', artist)
data = serializers.serialize('json', tracks)
return HttpResponse(data, mimetype="application/json")
What i mean by doesn't work is, for example in the first one none of the setattr values exist but they get added to each individual channel and i can access them in my template. However, in the second strip of code duration exists so that modified value gets outputted in my JSON but the other 2 attributes, title and artist, don't exist in the original queryset but unlike with channels they don't get added. Could i have anything to do with the way it's being rendered? If so, why?
Since serializer only uses models field i decided to return a ValuesQuerySet instead of a QuerySet since the former returns a dict. I did this by getting values() instead of all(). Thanks to #PeterDeGlopper for pointing me in the right direction!
# this
tracks = Songplays.objects.using('prod').values().filter(user=id, when__gt=start, when__lt=end).order_by('-when')
#instead of this
tracks = Songplays.objects.using('prod').all().filter(user=id, when__gt=start, when__lt=end).order_by('-when')
Once I had the dict i was able to convert to JSON like this.
import json
data = json.dumps(list(tracks))

Categories