I'm using the DjangoRestFramework. I have a UserSerialzer in my serializers.py file:
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'password', 'email', )
This is my urls.py file:
urlpatterns = [
url(r'^$', views.HomePageView.as_view()),
url(r'^users$', views.user_list.as_view()),
url(r'^users/(?P<pk>[0-9]+)$', views.user_detail.as_view()),
]
and this is my views.py file:
class HomePageView(TemplateView):
template_name = "home.html"
def get_context_data(self, **kwargs):
context = super(HomePageView, self).get_context_data(**kwargs)
# context['users'] = User.objects.all()
return context
class user_list(APIView):
"""
List all users, or create a new user.
"""
serializer_class = UserSerializer
def get(self, request):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
def post(self, request):
serializer = UserSerializer(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)
class user_detail(APIView):
"""
Get, update or delete a specific user.
"""
serializer_class = UserSerializer
def get_object(self, pk):
try:
return User.objects.get(pk=pk)
except User.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
def get(self, request, pk):
user = self.get_object(pk)
serializer = UserSerializer(user)
return Response(serializer.data)
def put(self, request, pk):
user = self.get_object(pk)
serializer = UserSerializer(user, data=request.DATA)
if serialzier.is_valid():
serializier.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk):
user = self.get_object(pk)
user.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
When I go to 127.0.0.1:8000/users, DjangoRestFramework has the API page which shows a list of users (JSON objects) and it also has a form which has "username", "password" and "email". This form seems to be validating correctly (checks if the email is a real email, and checks if username is unique and less than 30 characters). Is there a way for me to pass this form to the frontend when a user goes to 127.0.0.1:8000 (calling HomePageView)?
I'm in the process of using AngularJS on the frontend (not sure if this information helps or not).
Well here are a few things I think we might need to point out. Django forms are normally what you would use to create a new user, with a post request just like you are trying to do through DRF. Now you can do this through DRF, but thats not really what it is for, django forms would be more appropriate for what you are doing. Unless of course you are building an API that you want API users to be able to use to create new users on your platform, in which case continue onward. I am linking a tutorial I used when I first started using DRF with Angular, maybe you will find it helpful.
http://blog.kevinastone.com/getting-started-with-django-rest-framework-and-angularjs.html
Related
I want to customize the user viewset i.e. when the user registers the user account was created as well.
im doing this :
class CustomUserCreate(APIView):
permission_classes = [AllowAny]
def post(self, request):
serializer = RegisterUserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
if user:
profile_serializer = ProfileShortSerializer(data = request.data)
profile = profile_serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)```
is this the right approch?
I am trying to make a REST API using Django REST Framework. In the section of Authentication and Authorization I created 2 groups namely Manager (which has permissions to perform CRUD on database) and Staff (which has only view permission). Using serializers I am displaying the data in json format. But I am still able to perform CRUD operation using Staff account. How can I fix that?
This is my models.py
from django.db import models
class Users(models.Model):
Aadhar_Number = models.IntegerField(unique=True, primary_key=True, default=0)
Is_Active = models.BooleanField()
street = models.CharField(max_length=100,null=True)
city = models.CharField(max_length=10,null=True)
state = models.CharField(max_length=10,null=True)
Postal_Code = models.IntegerField(null=True)
def __str__(self):
return f"{self.Aadhar_Number}-{self.Full_Name}"
This is my api.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializers import *
class UserList(APIView):
def get(self, request):
model = Users.objects.all()
serializer = UsersSerializer(model, many=True)
return Response(serializer.data)
def post(self, request):
serializer = UsersSerializer(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)
class UserDetail(APIView):
def get_user(self, employee_id):
try:
model = Users.objects.get(id=employee_id)
return model
except Users.DoesNotExist:
return
def get(self, request, employee_id):
if not self.get_user(employee_id):
return Response(f'User with {employee_id} is Not Found in database', status=status.HTTP_404_NOT_FOUND)
serializer = UsersSerializer(self.get_user(employee_id))
return Response(serializer.data)
def put(self, request, employee_id):
serializer = UsersSerializer(self.get_user(employee_id), 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)
def delete(self, request, employee_id):
if not self.get_user(employee_id):
return Response(f'User with {employee_id} is Not Found in database', status=status.HTTP_404_NOT_FOUND)
model = self.get_user(employee_id)
model.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
I have added 2 groups using a Superuser and assigned them different permissions.
Permissions using Superuser
REST API View
When using DRF, you should go for its own permissions system.
Create a permissions.py inside your app.
# permissions.py
from rest_framework import permissions
class IsManagerOrReadOnly(permissions.BasePermission):
def has_permission(self, request, view):
if request.method in permissions.SAFE_METHODS:
# GET, OPTIONS, HEAD are considered safe methods.
return True
# for other methods such as POST/PUT/DELETE,
# check if the user has access with group name
return request.user.groups.filter(name='manager').exists()
And in your views, since you're using APIView it's pretty straightforward.
# views.py
from .permissions import IsManagerOrReadOnly
class NameOfYourView(APIView):
permission_classes = [IsManagerOrReadOnly]
# rest of your code...
I'm new to django rest framework, and I'm trying to learn drf. I didn't know how to achieve this features. I want some things like(Extra Actions) as shown in screenshot to navigate all the endpoint.
Here is an example from official DRF documentation:
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset that provides the standard actions
"""
queryset = User.objects.all()
serializer_class = UserSerializer
#action(detail=True, methods=['post'])
def set_password(self, request, pk=None):
user = self.get_object()
serializer = PasswordSerializer(data=request.data)
if serializer.is_valid():
user.set_password(serializer.data['password'])
user.save()
return Response({'status': 'password set'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
#action(detail=False)
def recent_users(self, request):
recent_users = User.objects.all().order_by('-last_login')
page = self.paginate_queryset(recent_users)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(recent_users, many=True)
return Response(serializer.data)
For more, please visit: Viewset actions
I'm using Django version 3 and the Rest Framework, i have a model with a user foreignkey.
so every time a model is saved the user also need to be saved.
To be able to add or to edit a model via rest you need to be authenticated using token authentication.
I'm using ClassBasedViews, the problem is that i can't find a way to add a model because in my serializer the field user is excluded because i don't want it to be editable.
models.py:
class Chambre(models.Model):
local_id=models.PositiveIntegerField(unique=True)
nom=models.CharField(max_length=255)
user=models.ForeignKey(User,on_delete=models.CASCADE,blank='true')
class Meta:
unique_together = ('local_id', 'user',)
serializers.py:
class ChambreSerializer(serializers.ModelSerializer):
class Meta:
model = Chambre
exclude =['user',]
views.py:
class ChambreListApi(APIView):
"""
List all chambres, or create a new chambre.
"""
authentication_classes=(TokenAuthentication,)
permission_classes=(IsAuthenticated,)
def get(self, request, format=None):
chambres = Chambre.objects.filter(user=request.user)
serializer = ChambreSerializer(chambres, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = ChambreSerializer(data=request.data)
if serializer.is_valid():
serializer.save(commit=False)
serializer.user=request.user
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Try moving the logic that sets the user to the serializer. By default GenericAPIView will pass the request to the serializer via the context.
class ChambreSerializer(serializers.ModelSerializer):
class Meta:
model = Chambre
exclude =['user',]
def create(self, validated_data):
validated_data["user"] = self.context["request"].user
return super().create(validated_data)
When I followed the accepted solution posted by schillingt, I had to add context={'request': request} when I instantiated the serializer. The Django REST Framework docs mention adding context to a serializer here.
serializers.py
class NoteCreateSerializer(serializer.ModelSerializer):
class Meta:
model = Note
exclude = ['owner',]
def create(self, validated_data):
validated_data['owner'] = self.context['request'].user
return super().create(validated_data)
views.py
#api_view['POST']
def create_note(request):
note_serializer = NoteCreateSerializer(
data = request.data,
context = {'request': request} # this will populate 'self.context'
# in the serializer instance
)
# ...
Thanks so much for this solution, though! It ended an hours-long struggle.
thanks for the reply that was very useful, i've solved it by adding method to serializer.py like this :
class ChambreSerializer(serializers.ModelSerializer):
class Meta:
model = Chambre
exclude =['user',]
def set_the_user(self,request):
self.user=request.user
def create(self, validated_data):
validated_data["user"] = self.user
return super().create(validated_data)
and in the views.py :
def post(self, request, format=None):
serializer = ChambreSerializer(data=request.data)
serializer.set_the_user(request)
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)
I'm trying to build a REST API for books:
/api/book
/api/book/{book_id}
A user should have access to his books only. The way I'm doing this now is by filtering the result using username i.e Book.objects.all().filter(owner=request.user)
views.py
class Book_List(APIView):
permission_classes=(permissions.IsAuthenticated)
def get(self, request, format=None):
**books= Book.objects.all().filter(owner=request.user)**
serializer = BookSerializer(books, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = BookSerializer(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)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
#/book/{pk}
class Book_Detail(APIView):
permission_classes = (permissions.IsAuthenticated)
def get_object(self, pk, request):
try:
return Book.objects.get(pk=pk, owner=request.user)
except Playlist.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
book = self.get_object(pk, request)
serializer = BookSerializer(playlist, context={'request': request})
return Response(serializer.data)
def put(self, request, pk, format=None):
book= self.get_object(pk)
serializer = BookSerializer(playlist, data=request.data, context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
book= self.get_object(pk)
book.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
serializers.py
class BookSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Book
fields = ('url', 'owner','title', 'created_date', 'shared_with', 'tracks')
class UserSerializer(serializers.HyperlinkedModelSerializer):
books = serializers.HyperlinkedRelatedField(many=True,view_name='playlist-detail', read_only=True)
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = User
fields = ('url', 'username', 'owner', 'books')
But is this the correct way?
Does Django Rest Framework provide any in-built solution for this?
Does the solution lie in permissions? If yes, then how do we set it for all objects created by a user (I understand the for getting a particular object we can put a permission check like obj.user==request.user). Am I right?
You could use the ModelViewset, which contains all the logic for the typical CRUD:
class BooksViewSet(ModelViewset):
serializer_class = BookSerializer
permission_classes=[permissions.IsAuthenticated, ]
def get_queryset(self):
return Books.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.data.owner = self.request.user
super(BooksViewSet, self).perform_create(serializer)