I want to serialize the data
class Main(models.Model):
title = models.CharField()
class ForeignKey(models.Model):
main = models.ForeignKey(Main,on_related='foreign_key')
I want to get the result like
{'title':'hello', 'foreign_key':'['foreign_key1','foreign_key2','foreign_key3']'
I first thought I could make it work in the 'views.py', but some documents told me that there is a thing like 'listField' in serializer, which has too little examples..
What would be the way here?
Write your serializer as ,
#serializers.py
from rest_framework import serializers
class ForeignKeySerializer(serializers.ModelSerializer):
class Meta:
model = ForeignKey
fields = '__all__'
class MainSerializer(serializers.ModelSerializer):
foreign_key = ForeignKeySerializer(source='foreignkey_set', many=True)
class Meta:
model = Main
fields = ("title", "foreign_key")
then write your views as,
#views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
#api_view()
def sample_view(request):
queryset = Main.objects.all()
serializer = MainSerializer(queryset, many=True)
return Response(data=serializer.data)
References
DRF-Serializer
DRF-views
Related
I'm following an udemy tutorial, and all it's going nice until I try to do a POST to create an article on the database.
When I send a POST to /api/posts
with Multipart form:
title: What is Java?
description: Java
order: 1
I receive the error:
NOT NULL constraint failed: posts_post.order
I can't find the solution to this specific situation. So I let you the code of my:
models.py:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
order = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
serializers.py:
from rest_framework.serializers import ModelSerializer
from posts.models import Post
class PostSerializer(ModelSerializer):
class Meta:
model = Post
fields = ['title', 'description', 'created_at']
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from posts.models import Post
from posts.api.serializers import PostSerializer
class PostApiView(APIView):
def get(self, request):
serializer = PostSerializer(Post.objects.all(), many=True)
return Response(status=status.HTTP_200_OK, data=serializer.data)
def post(self, request):
print(request.POST)
serializer = PostSerializer(data=request.POST)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(status=status.HTTP_200_OK, data=serializer.data)
I can do a GET request to my api/posts properly. The real problem is the POST request where I should create a new article/post
The order field is not included in the serializer. You need to add order in the fields.
class PostSerializer(ModelSerializer):
class Meta:
model = Post
fields = ['title', 'description', 'order, 'created_at']
You are using input as title, description and order but in your serializer you didn't mention order field so you need to mention order filed in your serializer
class PostSerializer(ModelSerializer):
class Meta:
model = Post
fields = ['title', 'description', 'order, 'created_at']
class SalonCarDetailsSerializer(serializers.ModelSerializer):
salon = PrimaryKeyRelatedField(queryset=Salon.objects.filter(owner=?))
class Meta:
model = SalonCarDetails
fields = ["salon", "car", "price", "number_of_cars"]
CurrentUserDefault() doesn't works
Well, you could write your own PrimaryKeyRelated field like that:
class SalonKeyRelatedField(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
qs = super().get_queryset()
request = self.context.get('request')
return qs
then you can filter qs by request.user, this will be called only on POST and PUT requests. You can then include it in your serializer
salon = SalonKeyRelatedField()
don't forget to include salon in your fields
I wish I could see your views.py, but anyway I make some assumptions about it and put it in the class implementation scenario.
#
### views.py
#
# Django native libraries
from rest_framework.serializers import Serializer
from rest_framework import viewsets, mixins, status
from django.db.models import Q
# your serializer and model
from .serializers import YourSalonCarSerializer
from .models import SalonCarDetails
class YourCustomViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
queryset = SalonCarDetails.objects.all()
serializer_class = YourSalonCarSerializer
def get_queryset(self):
if self.request.user.is_anonymous:
return []
lookups = Q(user=self.request.user)
queryset = self.queryset.filter(lookups)
So basically I have a django model that has a ManyToManyField of friends and two methods that run on it. Here are my files:
Models.py:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
first_name = models.CharField(max_length=50, blank=True)
last_name = models.CharField(max_length=50, blank=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
friends = models.ManyToManyField(User, blank=True, related_name='friends')
def friends_list(self):
return self.friends.all()
def number_of_friends(self):
return self.friends.all().count()
Serialzers.py:
from rest_framework import serializers
from .models import Profile
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = '__all__'
Views.py:
from rest_framework import viewsets, permissions
from .models import Profile
from .serializers import ProfileSerializer
class ProfileViewSet(viewsets.ModelViewSet):
queryset = Profile.objects.all()
permission_classes = [
permissions.AllowAny
]
serializer_class = ProfileSerializer
The issue is that in the Api, the return values of the method aren't there. The friends_list method for example is supposed to return a list of friends you have and even though this does work in a traditional django project, the Django Rest Framework is not showing any value for this method. How can I fix this and get the return values for both methods to show up in the api?
Since the model serializer picks up only model fields for the serializer fields, you won't automatically get any methods copied over.
You can still send this read only data over the API by explicitly adding the two fields with reference to the model methods
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = [
# need to explicitly define all fields I believe
'friends_list',
'number_of_friends',
]
Now that the two fields (matching the method name are declared, DRF should create SerializerMethodField or ReadOnly field (not sure which one, but they are similar) for each of them.
It works coz it sets the source for those fields to be the same name, and if finds some attribute (in this case the methods) on the model.
If that doesn't work, you can
class ProfileSerializer(serializers.ModelSerializer):
friends_list = serializers.SerializerMethodField()
number_of_friends = serializers.SerializerMethodField()
class Meta:
model = Profile
fields = [
# need to explicitly define all fields I believe
'friends_list',
'number_of_friends',
]
def get_friends_list(self, instance):
return instance.friends_list()
def get_number_of_friends(self, instance):
return instance.number_of_friends()
when you use __all__ it call fields only you have to call fields with methods using list like that
`fileds = ["first_name","last_name","user",
"friends","friends_list","number_of_friends"
]`
I'm following this tutorial (Django Rest Framework) and I'm facing a problem when I try to use serializers. It returns a empty result, instead the 49086 records that it should to return. My query it's ok because when I try to show the data without serializers it's shows these data. Please, what I'm doing wrong?
models.py
# coding=utf-8
from __future__ import unicode_literals
from django.db import models
class Workers(models.Model):
chapa = models.IntegerField(primary_key=True)
emp_cod = models.IntegerField(primary_key=False)
class Meta:
managed = False
db_table = 'WORKERS'
serializers.py
from rest_framework import serializers
from .models import Workers
class WorkersSerializer(serializers.ModelSerializer):
class Meta:
model = Workers
fields = '__all__'
views.py
...
#api_view(['GET'])
#permission_classes((permissions.AllowAny,))
def get_all_workers(request):
data = Workers.objects.using('rh').all().order_by('emp_cod')
print(data.count()) # Returns 49086
serializer = WorkersSerializer(data)
print(serializer.data) # Returns {}
json = JSONRenderer().render(serializer.data)
return Response(json) # Returns Django Rest standard page with "{}" data
You should use many=True serializer's argument to serialize multiple objects. Also you can pass serializer.data directly as Response argument:
#api_view(['GET'])
#permission_classes((permissions.AllowAny,))
def get_all_workers(request):
data = Workers.objects.using('rh').all().order_by('emp_cod')
serializer = WorkersSerializer(data, many=True)
return Response(serializer.data)
Since your view return so many objects at once, I suggest you to add pagination:
from rest_framework.pagination import PageNumberPagination
#api_view(['GET'])
#permission_classes((permissions.AllowAny,))
def get_all_workers(request):
data = Workers.objects.using('rh').all().order_by('emp_cod')
paginator = PageNumberPagination()
paginator.page_size = 10
result_page = paginator.paginate_queryset(data, request)
serializer = WorkersSerializer(result_page, many=True)
return Response(serializer.data)
I have a model, and I just want to show the data of the model in my /api/
from django.db import models
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
class Book(models.Model):
order_id = models.IntegerField()
isbn = models.IntegerField()
publisher = models.CharField(max_length=256)
school = models.CharField(max_length=256)
price = models.IntegerField()
duration = models.CharField(max_length=10)
order_datetime = models.DateTimeField(auto_now=False, auto_now_add=False)
def __str__(self):
return str(self.order_id)
This is my urls.py:
from django.contrib import admin
from django.urls import path
from filter import views
urlpatterns = [
path('', views.index, name='index'),
path('api/', views.BookApiView.as_view(), name='book_api'),
path('admin/', admin.site.urls),
]
This is my views.py:
from django.shortcuts import render
from rest_framework.views import APIView
from .models import Book
from django.http import JsonResponse
class BookApiView(APIView):
def get(self, request, format=None):
books = Book.objects.all()
return JsonResponse({'model': list(books)})
I get the following error: 'Object of type 'Book' is not JSON serializable'
Regards,
Anthony
Django models can't be JSON serialized implicitly.
You need a serializer to convert the model into a representation that is JSON serializable (primitive dicts, lists, numbers, strings, etc)
Django rest framework serializer docs: http://www.django-rest-framework.org/api-guide/serializers/
class BookSerializer(serializers.Serializer):
order_id = serializers.IntegerField()
isbn = serializers.CharField()
...
class BookApiView(APIView):
def get(self, request, format=None):
books = Book.objects.all()
serializer = BookSerializer(books, many=True)
return JsonResponse({'model': serializer.data})
Man... You need a 'Serializer' before send the data to the view!
The Serializez class get the abstract data from the django ORM and parse the data easily to JSON.
Create a file serializers.py at the same level of view.py
and:
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
After you create the SerializerBook class, import this on your view and pass the book queryset as the first parameter of the BookSerializer.
...
class BookApiView(APIView):
def get(self, request, format=None):
books = Book.objects.all()
serializer = BookSerializer(books, many=True)
return Response(serializer.data)
You should define serializer to convert the model instance data to respective JSON data, So define a serializer.py as below
class BookSerializer(serializers.ModelSerializer):
class Meta:
fields = '__all__'
model = Book
then in your view, change as below,<br>
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Book
class BookApiView(APIView):
def get(self, request, format=None):
booksqueryset = Book.objects.all()
serializer = BookSerializer(booksqueryset, many=True)
return Response(data=serializer.data)
Read this DRF ModelSerializer Official Doc for more details