django rest framework not showing response data - django

i have a problem with django rest framework and mySql the response data not showing:
i define serializer:
from rest_framework import serializers
from ..models import H010002
class H010002Serializer(serializers.Serializer):
class Meta:
model = H010002
# Note: any fild passed her will send to xhr request
fields = [
'id',
'module_name',
'module_description',
'module_type',
]
2- view.py
from .serializers import H010002Serializer
from ..models import H010002
from rest_framework.generics import (
ListAPIView,
RetrieveAPIView,
)
# Create your views here.
class H010002ListAPIView(ListAPIView):
queryset = H010002.objects.all()
serializer_class = H010002Serializer
3- data base included 1 record
4- django rest framework disply empty data with status 200 OK
Note: if i use normal class ListView the data come correctly

You should use serializers.ModelSerializer class to create the serializer.
class H010002Serializer(serializers.ModelSerializer):
class Meta:
model = H010002
fields = ['id', 'module_name', 'module_description', 'module_type', ]

Related

Combine two django models with shared ids into a single viewset

I have two django models in two independent apps, who use the same user ids from an external authentication service:
In app1/models.py:
class App1User(models.Model):
user_id = models.UUIDField(unique=True)
app1_field = models.BooleanField()
In app2/models.py:
class App2User(models.Model):
user_id = models.UUIDField(unique=True)
app2_field = models.BooleanField()
I would like to have a combined viewset that can make it seem like these two are a single model with a list response as follows:
[
{
'user_id': ...,
'app1_field': ...,
'app2_field': ...
},
...
]
If I create or update with this viewset, it should save the data to each of the two models.
To create a combined viewset for App1User and App2User models, you can
follow these steps:
Create a serializer for the combined model. In your main app, create a
serializers.py file and define the following serializer:
from rest_framework import serializers
from app1.models import App1User
from app2.models import App2User
class App1UserSerializer(serializers.ModelSerializer):
class Meta:
model = App1User
fields = ('user_id', 'app1_field')
class App2UserSerializer(serializers.ModelSerializer):
class Meta:
model = App2User
fields = ('user_id', 'app2_field')
class CombinedUserSerializer(serializers.Serializer):
user_id = serializers.UUIDField()
app1_field = serializers.BooleanField()
app2_field = serializers.BooleanField()
def create(self, validated_data):
app1_data = {'user_id': validated_data['user_id'], 'app1_field': validated_data['app1_field']}
app2_data = {'user_id': validated_data['user_id'], 'app2_field': validated_data['app2_field']}
app1_serializer = App1UserSerializer(data=app1_data)
app2_serializer = App2UserSerializer(data=app2_data)
if app1_serializer.is_valid() and app2_serializer.is_valid():
app1_serializer.save()
app2_serializer.save()
return validated_data
def update(self, instance, validated_data):
app1_instance = App1User.objects.get(user_id=validated_data['user_id'])
app2_instance = App2User.objects.get(user_id=validated_data['user_id'])
app1_serializer = App1UserSerializer(app1_instance, data={'app1_field': validated_data['app1_field']})
app2_serializer = App2UserSerializer(app2_instance, data={'app2_field': validated_data['app2_field']})
if app1_serializer.is_valid() and app2_serializer.is_valid():
app1_serializer.save()
app2_serializer.save()
return validated_data
This serializer defines the structure of the combined model and uses App1UserSerializer and App2UserSerializer to handle the fields of each model.
Create a viewset for the combined model. In your main app, create a viewsets.py file and define the following viewset:
from rest_framework import viewsets
from app1.models import App1User
from app2.models import App2User
from .serializers import CombinedUserSerializer
class CombinedUserViewSet(viewsets.ModelViewSet):
serializer_class = CombinedUserSerializer
def get_queryset(self):
app1_users = App1User.objects.all()
app2_users = App2User.objects.all()
combined_users = []
for app1_user in app1_users:
app2_user = app2_users.filter(user_id=app1_user.user_id).first()
if app2_user:
combined_user = {
'user_id': app1_user.user_id,
'app1_field': app1_user.app1_field,
'app2_field': app2_user.app2_field
}
combined_users.append(combined_user)
return combined_users
This viewset uses CombinedUserSerializer to handle the requests and retrieves the data from both App1User and App2User models. The get_queryset() method retrieves all the App1User and App2User instances, matches them based on their user_id, and creates a list of combined users.
Register the viewset in your main app's urls.py file:
# main_app/urls.py
from django.urls import include, path
from rest_framework import routers
from .views import CombinedUserViewSet
router = routers.DefaultRouter()
router.register(r'combined-users', CombinedUserViewSet)
urlpatterns = [
path('', include(router.urls)),
]
This code sets up a default router and registers the CombinedUserViewSet with the endpoint /combined-users/, which can be used to access the combined model data.
Above solution is the idea how it can be done, you can modify according to your needs. If this idea helps, plz mark this as accept solution.

Django Swagger Schema: Object of type Boolean is not JSON serializable

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.

How to accept form data and return it along with the results of some processing in Django RESTFramework?

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.

Returning objects using JSONRESPONSE

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.

Can't create HyperlinkedRelatedField in Django Rest Framework

I'm struggling to get HyperlinkedRelated fields working, and I can't figure out where I'm going wrong. No matter what I do, I get an error like:
Could not resolve URL for hyperlinked relationship using view name "court-detail". You may have failed to include the related model in your API, or incorrectly configured the lookup_field attribute on this field.
I feel that I've tried everything and I don't know where my error could be, nor how to identify it. My reading of this error message is that I am looking for a URL that corresponds to the court-detail view, but that that view doesn't exist.
Some piece of magic isn't working and any help would be greatly appreciated.
URLs:
from cl.api import views
from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'courts', views.CourtViewSet)
router.register(r'dockets', views.DocketViewSet)
router.register(r'clusters', views.OpinionClusterViewSet)
router.register(r'opinions', views.OpinionViewSet)
router.register(r'cited-by', views.OpinionsCitedViewSet)
urlpatterns = [
# url(r'^api/rest/(?P<version>[v3]+)/', include(router.urls)),
url(r'^api-auth/',
include('rest_framework.urls', namespace='rest_framework')),
url(r'^', include(router.urls)),
]
Views:
class DocketViewSet(viewsets.ModelViewSet):
queryset = Docket.objects.all()
serializer_class = serializers.DocketSerializer
class CourtViewSet(viewsets.ModelViewSet):
queryset = Court.objects.all()
serializer_class = serializers.CourtSerializer
class OpinionClusterViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
"""
queryset = OpinionCluster.objects.all()
serializer_class = serializers.OpinionClusterSerializer
class OpinionViewSet(viewsets.ModelViewSet):
queryset = Opinion.objects.all()
serializer_class = serializers.OpinionSerializer
class OpinionsCitedViewSet(viewsets.ModelViewSet):
queryset = OpinionsCited.objects.all()
serializer_class = serializers.OpinionsCitedSerializer
Serializers:
from cl.audio import models as audio_models
from cl.search import models as search_models
from rest_framework import serializers
class DocketSerializer(serializers.HyperlinkedModelSerializer):
court = serializers.HyperlinkedRelatedField(
many=False,
view_name='court-detail',
read_only=True
)
class Meta:
model = search_models.Docket
fields = ('date_created', 'date_modified', 'date_argued',
'date_reargued', 'date_reargument_denied', 'court')
class CourtSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = search_models.Court
class AudioSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = audio_models.Audio
class OpinionClusterSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = search_models.OpinionCluster
fields = ('judges', 'per_curiam', )
class OpinionSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = search_models.Opinion
fields = ('pk',)
class OpinionsCitedSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = search_models.OpinionsCited
When I go to:
http://127.0.0.1:8000/dockets/
It tells gives me the error message above. Of course, if I remove the court reference from the serialization, it works fine...
I imagine this can be caused by a number of things, but in my case, I figured out that it was caused by having DEFAULT_VERSIONING_CLASS set without having it configured in the urls.py:
REST_FRAMEWORK = {
# Use URL-based versioning
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v3',
'ALLOWED_VERSIONS': {'v3'},
}
The solution, therefore, was either to disable it in the settings, or to set up a url in in urls.py that accepted the version parameter:
url(r'^api/rest/(?P<version>[v3]+)/', include(router.urls)),
Ugh. Took a long time to realize I had this setting in place. Bad error message.