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']
Related
I am designing Basic Django rest framework based application, i need to compare external parameters passed through POST method in Postman with Coupon code in database and generate custom response like 'This code is redeemed/validate." or " This is invalid coupon/code."
Here is my Model.py file :
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
class Coupon(models.Model):
code = models.CharField(max_length=50, unique=True)
valid_from = models.DateTimeField()
valid_to = models.DateTimeField()
discount = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(100)])
active = models.BooleanField()
def __str__(self):
return self.code
here is my views.py file:
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Coupon
from .serializers import CouponSerializer
from rest_framework import viewsets
class CouponViewSet(viewsets.ModelViewSet):
queryset = Coupon.objects.all()
serializer_class = CouponSerializer
#api_view(['POST'])
def coupon_redeem(request):
if request.method =='POST':
serializer = CouponSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
here is my Serializer.py file
from rest_framework import serializers
from .models import Coupon
class CouponSerializer(serializers.ModelSerializer):
class Meta:
model = Coupon
fields = '__all__'
Please help if possible, Thank you.
IN Your post method u can filter the desired object like:
if serializer.is_valid():
coup=Coupon.objects.filter(code=serializer.data['code'],active=True).exists()
if(coup=="NULL"):
return Response("This is invalid coupon/code",status=status.HTTP_400_BAD_REQUEST)
else:
return Response("This is valid code",status=status.HTTP_200_OK)
I have the following :
I am working with DRF, based JWT token.
I want to associate an experiment with a USER, i.e when a post request is arriving I want to be able to save that post request with the Foreginkey it needed for the author by the user whom sent the request.
The POST request is always authenticated and never anonymous, i.e request.user is always exist ( I can see it when debugging)
I tried to add the following
def create(self, request, **kwargs):
request.data["author"] = request.user
serializer = ExperimentsSerializers(data=request.data)
if serializer.is_valid():
serializer.save()
return....
But is_valid return always False ( the only time ts was true, was when I took out the author from the ExperimentsSerializers fields....
will be happy for any leads....
my code attached below
Model.py:
class User(AbstractUser):
pass
def __str__(self):
return self.username
class Experiments(models.Model):
name = models.CharField(max_length=40)
time = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
View.py:
filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
serializer_class = ExperimentsSerializers
queryset = Experiments.objects.all()
filterset_fields = '__all__'
permission_classes = (permissions.IsAuthenticated,)
serializers.py
class ExperimentsSerializers(serializers.ModelSerializer):
class Meta:
model = models.Experiments
fields = '__all__'
You can just pass additional data with save arguments:
def create(self, request, **kwargs):
serializer = ExperimentsSerializers(data=request.data)
if serializer.is_valid():
serializer.save(author=request.user)
Note that you may need to specify author field as read_only so it would not be required in request body:
class ExperimentsSerializers(serializers.ModelSerializer):
class Meta:
model = models.Experiments
fields = '__all__'
read_only_fields = ['author']
One more approach can be to use
HiddenField with default value set to CurrentUserDefault
This way that field will not be exposed at the same time current user will be accessible and other operations can be done on that user context.
author = serializers.HiddenField(default=serializers.CurrentUserDefault())
Something like this:
class ExperimentsSerializers(serializers.ModelSerializer):
author = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = models.Experiments
fields = '__all__'
Reference :
HiddenField - https://www.django-rest-framework.org/api-guide/fields/#hiddenfield
CurrentUserDefault - https://www.django-rest-framework.org/api-guide/validators/#currentuserdefault
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
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
I am gettting this error although I am giving proper string in Text and Title fields.I don't know what are the reasons,However i am able to post the values of remaining three fields(author,Created_date,publish_date).
Serializer.py
from rest_framework import serializers
from blog.models import Post
from django.utils import timezone
from rest_framework.validators import UniqueValidator
class blogSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('author','title', 'text','created_date','published_date')
model.py
from django.db import models
from django.utils import timezone
class Post(models.Model):
author = models.ForeignKey('auth.User',null=True)
title = models.CharField(max_length=200)
text = models.CharField(max_length=200)
created_date = models.DateTimeField(
default=timezone.now)
published_date = models.DateTimeField(
blank=True,null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
views.py
from blog.models import Post
from .serializers import UserSerializer, GroupSerializer,blogSerializer
from rest_framework import viewsets,status
from rest_framework.decorators import api_view
class blogViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = blogSerializer
here i am posting the data.
#api_view(['GET', 'POST'])
def blog_list(request):
if request.method=='GET':
my_blog=Post.objects.all()
serializers=blogSerializer(my_blog,Many=True)
return JsoResponse(serializers.data,safe=False)
elif request.method=='POST':
data=JSONParser().parse(request)
serializers=blogSerializer(data=data)
if serializers.is_valid():
serializer.save()
return JsonResponse(serializers.data,status=201)
return JsonResponse(serializers.errors,status=400)
I would set up a unit test to test this functionality. It looks like none of your post data is getting to the serializer otherwise the valid fields would have been repopulated once you submit the form and the for is returned with errors. The title and text fields are also the only fields which are required/do not have a default value.
If you are using some form of decorator(or something similar) on the view which accesses request.data, this might be what is causing the issue. Since rest framework modifies request.POST when populating request.data