I'm trying to return an object using Jsonresponse, Sorry im newb
This is my script:
setInterval(function()
{
$.ajax({
url: '/check_notification/',
type: "POST",
dataType: 'json',
success: function (data) {}
});
}, 2000);
in my django views.py:
def check_notification(request):
user = request.user
profile = Person.objects.get(profile=user)
notification = NotificationRecipient.objects.filter(profile=profile)
return JsonResponse(model_to_dict(notification))
You can make a model Serializers for models you want to pass as response. for more information read django rest framework tutorial about serializers an learn how to make json response. Or if you have a simple dictionary you can make json response with this code snippet at the end of your check_notification function. return HttpResponse(json.dumps(your dictionary))
I would recommend you use Django Rest Framework for returning Responses in JSON format as the Serialization of models can be don easily. You can start from here. There you will find something known as a ModelSerializer. Basically you create a serializer.py in your app folder with the following content:
from rest_framework import serializers
from .models import Person, NotificationRecipient
class PersonSerializers(serializers.ModelSerializer):
class Meta:
model = Person
fields = '__all__'
class NotificationRecipientSerializers(serializers.ModelSerializer):
class Meta:
model = NotificationRecipient
fields = '__all__'
The above code will serialize your models which means will be converted to json format.
Than in a file named as views_api.py, you can create a class that will be called using by the URL and will have your queryset defined. In your case the class will be defined as:
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Person, NotificationRecipient
from .serializers import NotificationRecipientSerializers
class NotificationAPIView(APIView):
def get(self,request):
user = request.user
profile = Person.objects.get(profile=user)
notification = NotificationRecipient.objects.filter(profile=profile)
return Response(notification)
This will return the response in JSON format. In your urls.py file call the NotificationAPIView as follows:
from django.urls import path
from .import views_api
urlpatterns = [
path('check/notification/', views_api.NotificationAPIView.as_view(), name='notification'),
]
Hope you get a basic understanding of what is going on there. For better understanding go through Django Rest Framework docs.
Related
The context
I want to save json data from an external public kraken API in my Django database
Do you have any suggestion of (i) how can i get the json response working accordingly, and (ii) how can i afterwards save it in my django database?
If you have any ideas or tips I would be very grateful.
Thank you!
My view.py
from rest_framework import generics
from .serializers import KrakenSerializer
from kraken.models import Kraken
import requests
class KrakenList(generics.RetrieveAPIView):
serializer_class = KrakenSerializer
queryset = Kraken.objects.all()
def get_object(self):
url = 'https://api.kraken.com/0/public/Time'
r = requests.get(url, headers={'Content-Type':
'application/json'})
kraken = r.json()
return kraken
def seed_kraken():
for i in kraken:
krakenss = Kraken(
unixtime=i["unixtime"],
)
krakenss.save()
My urls.py
from .views import KrakenList
from django.urls import path
app_name = 'kraken'
urlpatterns = [
path('', KrakenList.as_view(), name='listkraken'),
]
My serializers.py
from rest_framework import serializers
from kraken.models import Kraken
class KrakenSerializer(serializers.ModelSerializer):
class Meta:
model = Kraken
fields = ('unixtime',)
My models.py
from django.db import models
class Kraken(models.Model):
unixtime = models.IntegerField(default=0)
This the Django REST framework with wrong empty json answer:
This is how the json unixtime answer should look like in my Django REST framework
The issue
Do you have any suggestion of (i) how can i get the json info working accordingly, and (ii) how can i afterwards save it in my django database?
I am working on a custom schema and got an error saying Object of type Boolean is not JSON serializable on the Swagger documentation page.
import coreapi
import coreschema
from rest_framework.schemas import AutoSchema
class CustomSchema(AutoSchema):
def get_manual_fields(self, path, method):
manual_fields = []
if method == "POST":
manual_fields.extend(
[
coreapi.Field(
"custom_field",
required=False,
location="form",
description="custom field",
type=coreschema.Boolean()
)
]
)
return manual_fields
I noticed that using location="query" would not yield the error above, but I need it in the form for Swagger. Is there any workaround? Thanks in advance!
Not necessarily solving the error above, but here's a workaround that worked for the same purpose:
from rest_framework import serializers
from . import CustomModel
class CustomSerializer(serializers.ModelSerializer):
custom_field = serializers.BooleanField(write_only=True)
class Meta:
model = CustomModel
fields = "__all__"
Rather than calling schema = CustomSchema() from the views, Call this CustomSerializer and specify a write_only field in the serializer automatically populates the Swagger schema for the POST method.
I am trying to understand Django RESTFramework. I am already familiar with Django. I want to create an endpoint that accepts some text data and processes it and returns it to the user along with the results of the processing (in text). I have completed a couple of tutorials on the topic but I still don't understand how it works. Here is an example from a working tutorial project. How can I edit it to achieve my goal? It all looks automagical.
# views.py
from rest_framework import generics
from .models import Snippet
from .serializers import SnippetSerializer
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
# Here I would like to accept form data and process it before returning it along with the
# results of the processing.
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
Okay, I think you are a newbie in Django rest and try to understand its flow so I can explain it with an example of a subscription plan.
First, create a model in models.py file
from django.db import models
class SubscriptionPlan(models.Model):
plan_name = models.CharField(max_length=255)
monthly_price = models.IntegerField()
yearly_price = models.IntegerField()
Then create views in a view.py file like
from rest_framework.views import APIView
class SubscriptionCreateAPIView(APIView):
serializer_class = SubscriptionSerializer
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(
{'message': 'Subscription plan created successfully.',
'data': serializer.data},
status=status.HTTP_201_CREATED
)
and then define a serializer for validation and fields in which we can verify which fields will be included in the request and response object.
serializers.py
from rest_framework import serializers
from .models import SubscriptionPlan
class SubscriptionSerializer(serializers.ModelSerializer):
plan_name = serializers.CharField(max_length=255)
monthly_price = serializers.IntegerField(required=True)
yearly_price = serializers.IntegerField(required=True)
class Meta:
model = SubscriptionPlan
fields = (
'plan_name', 'monthly_price', 'yearly_price',
)
def create(self, validated_data):
return SubscriptionPlan.objects.create(**validated_data)
Now add urls in src/subsciption_module/urls.py
from django.urls import path
from .views import SubscriptionCreateAPIView
app_name = 'subscription_plan'
urlpatterns = [
path('subscription_plan/', SubscriptionCreateAPIView.as_view()),
]
At the end include module url in root urls.py file where your main urls will be located. It will be the same directory which contains settings.py and wsgi.py files.
src/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('src.subscription_plan.urls', namespace='subscription_plan')),
]
That's it. This is how flow works in django rest and you can process data and display data in this way. For more details you can refer django rest docs.
But this is not in any way different from what you do with plain Django. Your SnippetDetail view is just a class-based view, and like any class-based view if you want to do anything specific you override the relevant method. In your case, you probably want to override update() to do your custom logic when receiving a PUT request to update data.
I have a very basic Django Rest API.
I don't know how to have some HTML views, in the same django project, which uses API (finally keeping API returning JSON only).
I followed this, but it seems to change the API View (in this case, curl will retrieve HTML and not JSON) :
https://www.django-rest-framework.org/api-guide/renderers/#templatehtmlrenderer
Do I need another Django App ? Another Django project ? Some JS ?
EDIT :
Ok, I've seen it's possible, thanks to rrebase.
But I can't retrieve the JSON with Curl, here my views.py
from rest_framework import generics
from rest_framework.renderers import TemplateHTMLRenderer, JSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAdminUser
from . import models
from . import serializers
class UserListView(generics.ListAPIView):
renderer_classes = [JSONRenderer, TemplateHTMLRenderer]
template_name = 'profile_list.html'
def get(self, request):
queryset = models.CustomUser.objects.all()
serializer_class = serializers.UserSerializer
return Response({'profiles': queryset})
My models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
def __str__(self):
return self.email
I get an error "Object of type 'CustomUser' is not JSON serializable" when I request the API (http://127.0.0.1:8000/api/v1/users/)
Sorry, it's some different that initial question...
Yes, you can have both. The link you provided to docs has the following:
You can use TemplateHTMLRenderer either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint.
When making an API request, set the ACCEPT request-header accordingly to html or json.
Finally I made some conditions in my view, and it's working
class UserListView(generics.ListAPIView):
renderer_classes = [JSONRenderer, TemplateHTMLRenderer]
permission_classes = (IsAdminUser,)
def get(self, request):
queryset = CustomUser.objects.all()
if request.accepted_renderer.format == 'html':
data = {'profiles': queryset}
return Response(data, template_name='profile_list.html')
else:
serializer = UserSerializer(queryset, many=True)
data = serializer.data
return Response(data)
My django-rest-auth on authentication sends the following response
{"key":"XXXXXXXXXXXXXX"}
Now i am using ember-simple-auth specifically oauth2-password-grant for authentication which expects access_token in response body. After looking at source code of ember js here, i found out that the value access_token is defined as string and cannot be changed. My question is how can i implement authentication using the two stack. Is there any way that i can rename key to access_token in django ?
You can create your own MyLoginView which subclasses the original LoginView from django-rest-auth and create custom Serializer that returns the access_token field.
Something like this:
my_app/serializers.py
from rest_auth.models import TokenModel
from rest_framework import serializers
class MyTokenSerializer(serializers.ModelSerializer):
"""
Serializer for Token model.
"""
access_token = serializers.SerializerMethodField()
class Meta:
model = TokenModel
fields = ('access_token',)
def get_access_token(self, obj):
return object.key
my_app/views.py
from rest_auth.views import LoginView
from my_app.serializers import MyTokenSerializer
class MyLoginView(LoginView):
def get_response_serializer(self):
return MyTokenSerializer
urls.py
from my_app.views import MyLoginView
url(r'^login/$', MyLoginView.as_view(), name='my_login'),