is creating serializer mandatory for each View in django rest frame work - django-rest-framework

I am working on app where I didnt use serializer in one view I just want to ask am I doing something wrong.
I am getting a committee id in the url and in the body I am getting the usr_id whos status I want to change if someone sends a post request to this end point.
This is my url
path('committee/<int:id>/accept-request/', RequestAcceptView.as_view(), name="accept-request"),
this is my view.py
class RequestAcceptView(APIView):
def post(self, request, id):
user_id = request.data['user']
print("iddddd",user_id )
try :
approve_request = Member.objects.filter(
Q (com=Committee.objects.get(id=id))
).update(mem_status="fully_approved")
return Response(SuccessResponse(msg="Request accepted"))
except:
return Response(ErrorResponse(msg="invalid))
I want to know I am not using serializer here for any purpose, is it fine? should I remove serializer file?

No, it is not when you are using ApiView. Generic and ModelView requires them. You should also think about if you want to have auto generated documentation you need the serializer and it will also perform validation (because you are not using the id field, but request.data.
If request.data and I'd are the same, then you might want to delete the serializer

Related

Pagination on Django Rest Framework when the data does not come from a model from the database

I'm trying to create an endpoint who returns the values from an Enum, but I need to make it with pagination because the UI library we use was designed to received exactly the same format that Django Rest Framework return when we read from a database.
The problem is that I cannot make the pagination to work. No matter which base class I use (ApiView, ListView, etc), the Response return doesn't has the count, next, previous and results fields (in results is where the real json should be).
I tried to overwrite pagination with pagination_class on the view class, and also creating a custom pagination class based on PageNumberPagination, but nothing.
Also, I tried to create a custom get_paginated_response method on my custom pagination class, but when I debug it looks like the method is not called.
What I'm doing wrong? I imagine it should be a way to tell DRF "take this data, even if is not from a model, and return that as a paginated list of fields"
When this happened to me in the past, I just called paginate_queryset with the enum and the request. Then, you need to return the response of get_paginated_response(page). So, something like this:
class SampleViewSet(views.ViewSet):
def list(self, request):
values = [e.value for e in MyEnum]
paginator = YourPaginationClass()
page = paginator.paginate_queryset(values, request)
if page is not None:
return paginator.get_paginated_response(page)
return Response(data)

how to get validated data from serializers to views in django rest framework

I am returning some data from def create method in seriaizers.py file I want to acccess that data in views.py I dont know how to get it.
serilizers.py
def create(self, validated_data):
//returning something
return validated_data
views.py
if serializer.is_valid():
serializer.save()
//I want to return that validated_data here so how to get it here here
Response(validated_data)
To get the validated data, use serializer.validated_data. See the Deserializing Objects section of the manual.
Also, I want to point out a potential footgun here: you're supposed to return a model instance, from the create() method, rather than the validated data.

Update Foreign-key Related Instance on Post Request

I am trying to implement a system where a user can subscribe to a company. For that I have to implement the following flow:
User registers
User klicks on a button to subscribe to a company
User has to enter a code (every company has a secret code. By possession the user proves that he is somewhat related to the company)
User is subscribed
For this, I have to implement an API endpoint that receives the code by the user (the user is authenticated at this point).
It is shameful, but I am lost: I am thinking of implementing a view like this.
class RegisterUserToCustomer(APIView):
permission_classes = (permissions.IsAuthenticated,)
def post(self, request, format=None):
serializer = CustomerSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=self.request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
Obviously, I have to:
Receive the code from the user via POST method
Search the database and figure out, if the code corresponds to any company
Edit the ForeignKey field on the user and link it to the company
But where would I implement this logic. With my limited experience I see three possibilities:
Call serializer.save() and write a custom create() method (but I don't want to create anything so this seems like bad practice
Implement this logic in the view, but I want to access the code from the validated_data (this seems like a problem?)
Can I write a custom save() method for the serializer? Are there any examples for a custom save() method since the original drf save() method contains a lot of validation logic.
Obviously I don't expect you guys to write the whole code for me, but maybe someone has somewhat of a blueprint of how and where to implement this?
Steps to do this:
Create a field company_code in Customer table and make that
field as Foreign key.
Create a Serializer with that foreign key field.
Create a viewset or generic views to expect that field from Post method as Id of the Company. Use save() method to store foreign key.
This scenarios is only for Subscribe one organisation, if you're able to subscribe multiple organisation make that field as ManytoMany field.
Refer the code sample,
Models.py
class Customer(models.Model):
# customer related field
name = models.CharField(max_length=20)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
Serializer.py
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('name', 'organization', )
Views.py
class CustomerViewSet(viewsets.ModelViewSet):
serializer_class = CustomerSerializer
queryset = Customer.objects.all()
Request data(POST Json)
{
"name": "test",
"organization": "id-of company"
}

DRF clear m2m field via patch with SlugRelatedField

Currently i'm using a SlugRelatedField in my ModelSerializer to represent a m2m-Field.
manager = serializers.SlugRelatedField(
many=True,
queryset=get_user_model().objects.all(),
slug_field='username',
required=False,
allow_null=True)
if i send now a patch request with e.g.
'manager': 'user1' or 'manager: ['user1', 'user2'] it works as expected.
but how can i achieve, that the m2m field gets cleared, when i send an empty array 'manager': []
at the moment nothing happens, when i do so.
If i try to clear it with 'manager': '' i get an "object with username= does not exist" error.
maybe the SlugRelatedField isn't the right choice for me? i just wanted to achieve handling users with their username instead of their pk.
Edit:
I can do a PUT Request with not sending 'manager' at all to clear it.
Is there maybe no way to clear a m2m field with a PATCH Request?
r = requests.patch('http://localhost:8000/api/projects/dfo2/',
auth = ('lala','lilu'),
data = {'developer': []}
)
result:
{'manager': ['peter', 'fllow'], 'description': '','name_short': 'dfo2', 'developer': ['peter'], 'name': 'asdf'}
what works is:
r = requests.patch('http://localhost:8000/api/projects/dfo2/',
auth = ('lala','lilu'),
data = '{"developer": []}',
headers = {'Content-type': 'application/json'}
)
but why does this not work:
r = requests.patch('http://localhost:8000/api/projects/dfo2/',
auth = ('lala','lilu'),
data = {"developer": []},
headers = {'Content-type': 'application/x-www-form-urlencoded'}
)
Without seeing your full code it is hard to know, but generally it seems like you are not dealing with the data properly. One piece of advice I always give people with DRF is to think about serializers as a tool for giving and validating data, but not necessarily describing what to do with it.
With that in mind, I suggest you try something like the following, although again it is hard without seeing the models and full serializer code:
class Projects(models.Model):
managers = models.ManyToManyField('auth.Users')
class ProjectSerializer(serializers.Serializer):
managers = serializers.SlugRelatedField(
many=True,
source='managers.all',
queryset=get_user_model().objects.all(),
slug_field='username',
required=False,
allow_null=True)
def update(self, instance, validated_data):
[instance.managers.add(manager) for manager in validated_data['managers']
return instance

How to get the id attribute when I'm inside the perform_validation method of the serializer

When I'm inside the perform_validation method of a given serializer I need access to the "id" of the model I've requested (at my RetrieveUpdateDestroy endpoint)
def perform_validation(self, attrs):
name = attrs['name']
guid = attrs['id'] #broken :(
What is the best way to get this when I'm inside the validation method?
Use the serializer context, that's provided by the generic view.
See here for what context is populated by default: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/generics.py#L83
You should be able to do something like this: self.context['view'].kwargs['pk']

Resources