I'd like to post to my Django server using post
so I can add a todo
item. Here is the model:
class Todo(models.Model):
title = models.CharField(max_length=200);
text = models.TextField()
completed = models.BooleanField(default=False)
created_at = models.DateTimeField(default=datetime.now, blank = True )
def __str__(self):
return self.title
And serializers:
class TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ("id", 'title','text', 'completed', 'created_at')
And view:
class TodoList(APIView):
def get(self,request):
todo=Todo.objects.all()
serializer=TodoSerializer(todo,many=True)
return Response(serializer.data)
def post(self,request):
Todo.objects.create(
title=request.POST.get('title'),
text=request.POST.get('text'))
return HttpResponse(status=201)
My post request is
{ "title": "new title",
"text": "a test text"}
And it told me
IntegrityError at /todos/
(1048, "Column 'title' cannot be null")
As a newbie at Django, I don't understand this error. Any ideas?
You need to access request.data
instead of request.POST
,
def post(self,request):
serializer = TodoSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Since you've asked about other methods besides post in the comments, I'll show an example of a ModelViewSet that will allow you to post to add a Todo, as well as provide support for retrieving, updating, and deleting your Todo's.
Recommended reading:
http://www.django-rest-framework.org/api-guide/viewsets/#modelviewset
from rest_framework.viewsets import ModelViewSet
from todo.models import Todo
from todo.serializers import TodoSerializer
class TodoViewSet(ModelViewSet):
queryset = Todo.objects.all()
serializer_class = TodoSerializer
The ModelViewSet class will provide you with a default implementation of view methods to list, create, retrieve, update (whole or partial update), and delete Todo's. These actions are mapped to certain methods for different urls, get is mapped to list and retrieve, post is mapped to create, put and patch are mapped to update and partial_update, and delete is mapped to destroy.
Then in your urls.py, include the TodoViewSet using TodoViewSet.as_view(...)
:
from django.conf.urls import url
from todo.views import TodoViewSet
urlpatterns = [
url(
r'^todos/$',
TodoViewSet.as_view({'get': 'list', 'post': 'create'}),
name='todo-list',
),
url(
r'^todos/(?P<pk>\d+)/$',
TodoViewSet.as_view({'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'}),
name='todo-detail',
)
]
Here we are explicitly stating the mapping of request methods to view actions that I mentioned before.
Instead of creating like this, You can always use serializers for the same
data_serializer = TodoSerializer(data=request.data)
if data_Serializer.is_valid():
data_Serializer.save()
for put request :
todo_item = Todo.objects.get(id=id) // Need to get that element
data_serializer = TodoSerializer(instance=todo_item,data=request.data, partial=True)
if data_Serializer.is_valid():
data_Serializer.save()
else:
print data_Serializer.errors
for delete:
todo_item = Todo.objects.get(id=id) // Need to get that element
todo_item.delete()