Sending JSON data from view in Django - python

I have to store some data in the window object to use it un the frontend rendering. I have a model:
from django.db import models
from tools.various.db import Base
from tools.files.fields import CustomImgField, IMAGES_DIRECTORY_ORIGINAL
from django.conf import settings
class myModel(Base):
myName = models.CharField(max_length=100, verbose_name='myName')
mySurname = models.CharField(max_length=100, verbose_name='mySurname')
I have a view:
from django.http import Http404
from django.views.generic import TemplateView
from django.http import JsonResponse
from json import dumps
from front.models import Language
from front.models import myModel
class BaseView(TemplateView):
def get_context_data(self, **kwargs):
context = super(BaseView, self).get_context_data(**kwargs)
context['myData'] = myModel.objects.value()
return context
And I want to retrieve myData as a JSON object and store it in window object:
window.app = {
data: {},
settings: {
staticUrl: '{{ STATIC_URL }}',
urls: {},
storedData: {{ myData|jsonify|safe }}
}
};
But I get this response:
[{'myName': u'foo', 'mySurname': u'bar', u'id': 1L, 'order': 0L}] is not JSON serializable
Does anyone knows what I'm doing wrong?
Thanks!
EDIT:
I just tried return list(context) as André Laszlo proposes: it returns
Exception Value: list indices must be integers, not str
But if I use:
context['myData'] = list(myModel.objects.values())
return context
It seems to work. I'm going to read the documentation about 'list()'.

You are returning a python dictionary, you need to serialize it to JSON using json.dumps()
You are already importing json but not making use of it.
from django.http import Http404
from django.views.generic import TemplateView
from django.http import JsonResponse
from json import dumps
from front.models import Language
from front.models import myModel
class BaseView(TemplateView):
def get_context_data(self, **kwargs):
context = super(BaseView, self).get_context_data(**kwargs)
context['myData'] = myModel.objects.value()
return dumps(context)
Additionally, you might want to read up on ujson - Faster than the builtin json library.
Preferably, if you are using Django 1.7+ you can do:
from django.http import Http404
from django.views.generic import TemplateView
from django.http import JsonResponse
from json import dumps
from front.models import Language
from front.models import myModel
from django.http import JsonResponse
class BaseView(TemplateView):
def get_context_data(self, **kwargs):
context = super(BaseView, self).get_context_data(**kwargs)
context['myData'] = myModel.objects.value()
return JsonResponse(context)

I think that the problem is that your list is actually not a list, it's a QuerySet that just looks like a list when printed.
Have you tried:
context['myData'] = list(myModel.objects.values())
return context
I think it should return a list with dictionaries, which should be JSON serializeable. Please update your question with your results if it doesn't work.

Related

What is the best, cleanest and shortest way to check if a given value is valid URL when working with models?

I rather want to use Django's built-in functionalities as much as possible and avoid implementing stuff myself as much as possible!
Why doesn't the following code issue exceptions when given a non-URL value?
models.py:
from django.core.validators import URLValidator
from django.db import models
class Snapshot(models.Model):
url = models.URLField(validators=[URLValidator])
views.py:
from django.http import HttpResponse
from .models import Snapshot
def index(request):
a = Snapshot(url='gott ist tot')
a.save()
Because this validator is run when you use a django form.
More information about validators on the doc : https://docs.djangoproject.com/en/4.1/ref/validators/
if you do a form :
from django import forms
from .models import Snapshot
class SnshotForm(forms.ModelForm):
class Meta:
model = Snapshot
fields = ('url', )
and your views.py :
from django.http import HttpResponse
from .forms import SnapshotForm
def index(request):
a = SnapshotForm(data={'url': 'gott ist tot'})
if a .is_valid()
a.save()
else:
print(a.errors)
Your validator will be run and you will see the errors form message
Without using form, you can call manually validator in your view or in the save method:
# in views
from django.core.validators import URLValidator
from django.core.exceptions import ValidationError
def index(request):
url_validator = URLValidator()
url = 'gott ist tot'
is_valid_url = False
try:
url_validator(url)
except ValidationError:
pass
if is_valid_url:
a = Snapshot(url=url)
a.save()
else:
print(a.errors)
Be careful ! I do not recommanded to bypass the validator with forms, i think it is the better way for maximizing usage of django builtins funtions

NameError: name doohickey is not defined

I am having issues importing a function from a module I created into my code. I am getting an error stating that the function is not defined, despite importing the module into my file.
The error message:
something = doohickey()
NameError: name 'doohickey' is not defined
get_random_tweet.py
import twitter
api = twitter.Api(consumer_key='',
consumer_secret='',
access_token_secret='')
timeline = api.GetUserTimeline(screen_name='realDonaldTrump',
include_rts=False,
trim_user=True,
exclude_replies=True,
count=6)
def doohickey():
pprint(timeline)
return {'index': "<i> something </i>"}
My views.py
from django.shortcuts import render
from django.http import HttpResponse
from hello.sampled_stream import okdood
import hello.get_random_tweet
from .models import Greeting
# Create your views here.
def index(request):
# return HttpResponse('Hello from Python!')
# okdood()
something = doohickey()
return render(request, "index.html")
I have also attempted the following:
from django.shortcuts import render
from django.http import HttpResponse
from hello.sampled_stream import okdood
from hello.get_random_tweet import doohickey
from .models import Greeting
# Create your views here.
def index(request):
# return HttpResponse('Hello from Python!')
# okdood()
something = doohickey()
return render(request, "index.html")
Error message:
something = doohickey()
NameError: name 'doohickey' is not defined
and
from django.shortcuts import render
from django.http import HttpResponse
from hello.sampled_stream import okdood
import hello.get_random_tweet
from .models import Greeting
# Create your views here.
def index(request):
# return HttpResponse('Hello from Python!')
# okdood()
something = hello.get_random_tweet.doohickey()
return render(request, "index.html")
Error message:
something = hello.get_random_tweet.doohickey()
NameError: name 'doohickey' is not defined
It looks like the issue is that you are not referring to the doohickey function as part of the hello.get_random_tweet namespace. You can do this in several ways:
from django.shortcuts import render
from django.http import HttpResponse
from hello.sampled_stream import okdood
from hello.get_random_tweet import doohickey
from .models import Greeting
# Create your views here.
def index(request):
# return HttpResponse('Hello from Python!')
# okdood()
something = doohickey()
return render(request, "index.html")
or
from django.shortcuts import render
from django.http import HttpResponse
from hello.sampled_stream import okdood
import hello.get_random_tweet
from .models import Greeting
# Create your views here.
def index(request):
# return HttpResponse('Hello from Python!')
# okdood()
something = hello.get_random_tweet.doohickey()
return render(request, "index.html")
As your code is currently structured, you import the hello.get_random_tweet module, but when you refer to doohickey Python is looking for it in the local namespace. However, it should be looking for it in the hello.get_random_tweet namespace. You can either import the function and add it to the local namespace, as shown in the first snippet, or refer to the function in the imported module's namespace as shown in the second snippet.
Might be a copy/paste error, but you're missing endquotes on a few lines here, and the closing bracket:
api = twitter.Api(consumer_key='',
consumer_secret='',
access_token_secret=''
Should be:
api = twitter.Api(consumer_key='',
consumer_secret=''
access_token_key=''
access_token_secret='')

How to pass a query set to the context class in Django?

I am trying to pass a queryset object to django context class, but doing so results in the following error: TypeError('context must be a dict rather than %s.' % context.__class__.__name__)
Now i understand that the context accepts only a dictionary but i am following an example from a book called django_unleashed which uses Django version 1.8 and i am using django 2.0. and i guess it was done like that in previous versions.
So my question is how should i do this step correctly using django 2.0
from django.shortcuts import render
from django.http import HttpResponse
from .models import Tag
from django.template import Context, loader
def homepage(request):
tag_list = Tag.objects.all()
template = loader.get_template('organizer/tag_list.html')
context = Context({'tag_list': tag_list})
output = template.render(context)
return HttpResponse(output)
As the error suggests, you should use a regular dictionary for the context:
def homepage(request):
tag_list = Tag.objects.all()
template = loader.get_template('organizer/tag_list.html')
context = {'tag_list': tag_list}
output = template.render(context)
return HttpResponse(output)
In practice, you would usually use the render shortcut rather than manually rendering the template:
from django.shortcuts import render
def homepage(request):
tag_list = Tag.objects.all()
context = {'tag_list': tag_list}
return render(request, 'organizer/tag_list.html', context)
'''you have a model class named 'Tag',
wish your template is on ' Project directory/ app directory/ template/ same name of app directory'
example: let your project name is 'Website' and app name is 'organizer' then the template will be on: 'Website/ organizer/ templates/ organizer/ tag_list.html' Confirm your TEMPLATES setting is default on setting.py file."'
from django.shortcuts import render
from .models import Tag
def homepage(request):
tag_list = Tag.objects.all()
context = { 'tag_list' : tag_list}
return render ( request, 'organizer/tag_list.html', context)

Django rest framework and python3.5 OrderedDict mutated during iteration

I use Django rest framework and python3.5. Earlier I had another version of python and everything was going right. When I want to get some information from server with URL for example like:
"http://127.0.0.1:8000/api/companies"
I'm getting error:
"OrderedDict mutated during iteration"
.
In views.py I have:
from django.shortcuts import render
from companies.models import Companies
from companies.serializers import CompaniesSerializer
from rest_framework import generics
from rest_framework.response import Response
from rest_framework.renderers import JSONRenderer
from rest_framework import status
class CompaniesList(generics.ListCreateAPIView):
queryset = Companies.objects.all()
serializer_class = CompaniesSerializer
class CompaniesDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Companies.objects.all()
serializer_class = CompaniesSerializer
What should I do to make it working? Where is something mutating the dict?
I don't know why using ListCreateApiView is mutating dict, but I changed class into function like :
#api_view(['GET'])
def CompaniesList(request):
if request.method == 'GET':
companies = Companies.objects.all()
serializer = CompaniesSerializer(companies, many=True)
return Response(serializer.data)
and now it's working...

DRF - Method 'GET' not allowed

I'm trying to setup a class based view in Django Rest Framework.
This is my urls.py -
from django.conf.urls import patterns, include, url
from rest_framework.urlpatterns import format_suffix_patterns
from django.contrib import admin
from TidalDEV import views
admin.autodiscover()
urlpatterns = patterns('',
url(r'^test/(?P<pk>[0-9]+)/$', views.TESTXMLDetail.as_view()),
)
And this is my view -
import os, tempfile, zipfile
from django.shortcuts import render
from django.core import serializers
from django.core.serializers import serialize
from django.core.servers.basehttp import FileWrapper
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer, XMLRenderer
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny
from itertools import chain
from TAPI.renderers import *
from TAPI.models import *
from TAPI.serializers import JobdtlSerializer, JobmstSerializer, TrgjobSerializer, JobdepSerializer
class TESTXMLDetail(APIView):
permission_classes = (AllowAny,)
"""
Retrieve, update or delete a snippet instance.
"""
def get_object(self, pk):
try:
mst = Jobmst.objects.db_manager('AdmiralDEV').raw("""
query1""", [pk])
dtl = Jobdtl.objects.db_manager('AdmiralDEV').raw("""
query2""", [pk])
dep = Jobdep.objects.db_manager('AdmiralDEV').raw("""
query3""", [pk])
trg = Trgjob.objects.db_manager('AdmiralDEV').raw("""
query4""", [pk])
except Jobmst.DoesNotExist:
return HttpResponse(status=404)
def get(self, request, pk, format=None):
jobmststring = JobmstSerializer(mst)
jobdtlstring = JobdtlSerializer(dtl)
jobdepstring = JobdepSerializer(dep, many=True)
trgjobstring = TrgjobSerializer(trg, many=True)
jobmst_serialized = {'jobmst': jobmststring.data}
jobdtl_serialized = {'jobdtl': jobdtlstring.data}
jobdep_serialized = [{'jobdep':item} for item in jobdepstring.data]
trgjob_serialized = [{'trgjob':item} for item in trgjobstring.data]
jobgroup = jobmst_serialized, jobdtl_serialized, jobdep_serialized, trgjob_serialized
jobgroupresponse = TESXMLResponse(jobgroup)
return jobgroupresponse
When I run the URL all I get is the XML format but then it says -
<detail>Method 'GET' not allowed.</detail>
I've tried setting the permission class in the view as above and I've also put the following lines in my settings.py what gives?
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
You're getting this error because the DRF APIView doesn't have a get method (or a method for any HTTP request type actually).To get your code working you can either rename your get_object method to get (making sure you add the expected parameters request and format), or you can write a get method to return your response:
class TESTXMLDetail(APIView):
def get(self, request, pk, format=None):
return self.get_object(pk)
def get_object(self, pk):
...
...

Categories