8

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?

1
  • 1
    Instead of creating like this, You can always use serializers for the same. Commented Jul 20, 2017 at 4:14

4 Answers 4

17

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)
Sign up to request clarification or add additional context in comments.

Comments

4

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.

2 Comments

Thanks for your help. And what is (?p<pk>\d+) matching in the urls.py?
(?P<pk>\d+) is a regex placeholder to capture the Todo objects Primary Key in the url and lookup the object, which in this case should be an integer. You can customize what field the view expects from the url and which field on the model it uses to lookup. django-rest-framework.org/api-guide/generic-views/…
3

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()

1 Comment

Thanks this works well, can you please also show me how this can work with PUT and DELETE request?
2

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()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.