partial_update only if not exist (PATCH Django Rest Framework) - django

I am currently using partial_update to update info but I want to update it only if that specific field is empty.
views.py
class TitleViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
queryset = Title.objects.all()
serializer_class = TitleSerializer
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
serializers.py
class TitleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Title
fields = ['pk', 'name', 'steam_appid', 'website', 'twitter']
So instead of updating for example 'twitter' field. I ONLY want to update if its empty. Also I dont want to specify 'twitter' as a field since I have many more.

Found a solution, it basically checks of the attribute is empty, if its not it does nothing. If it is empty, it will update it.
class TitleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Title
fields = ['pk', 'name', 'steam_appid', 'website', 'twitter']
def update(self, instance, validated_data):
for attr, value in validated_data.items():
if not getattr(instance, attr):
setattr(instance, attr, value)
instance.save()
return instance

Related

Django rest_framework perform_update

I trying to move my def update from my serializer.py to my views.py, What it does is well after updating an Item it also saves a log to transaction_log
class ClearanceItemSerialize(serializers.ModelSerializer):
class Meta:
model = ClearanceItem
fields = '__all__'
def update(self, instance, validated_data):
instance.resolve = 'True'
instance.resolve_date = timezone.now()
instance.save()
TransactionLog.objects.create(cl_itemid=ClearanceItem.objects.get(cl_itemid=instance.cl_itemid),
trans_desc="Resolve Clearance Item",
trans_recorded=timezone.now())
return instance
views.py
class APIClerkUpdate(generics.RetrieveUpdateAPIView):
permission_classes = [IsAuthenticated]
queryset = ClearanceItem.objects.all()
serializer_class = ClearanceItemSerialize
def perform_update(self, serializer):
"""
What to put here
"""
hope someone help thank you.
Just like in your serializer:
class APIClerkUpdate(generics.RetrieveUpdateAPIView):
def perform_update(self, serializer):
serializer.save()
instance = serializer.instance
TransactionLog.objects.create(
cl_item=instance,
trans_desc="Resolve Clearance Item",
trans_recorded=timezone.now()
)

Why Django's OneToOneField returns 500 if relation aready exists

In a Django REST Framework POST view, is there any way to avoid an HTTP 500 if the OneToOneField relation already exists?
Instead, it would be great to get an HTTP 400.
models.py
class Club(TimeStampModel):
owner = models.OneToOneField(User, on_delete=models.PROTECT)
name = models.CharField(max_length=255, unique=True)
serializers.py
class ClubSerializer(serializers.ModelSerializer):
class Meta:
model = Club
fields = '__all__'
read_only_fields = ['owner', 'active']
views.py
class ClubRegistrationView(generics.CreateAPIView):
queryset = Club.objects.all()
serializer_class = ClubSerializer
permission_classes = [IsAuthenticated]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
Thanks.
When you passed owner like this serializer.save(owner=self.request.user) serializer doesn't perform validation. You should rewrite create instead of perform_create method for this
class ClubRegistrationView(generics.CreateAPIView):
queryset = Club.objects.all()
serializer_class = ClubSerializer
permission_classes = [IsAuthenticated]
def create(self, request, *args, **kwargs):
request.data["owner"] = request.user.pk
return super().create(request, *args, **kwargs)
Here a validation error:
{'user': ['This field must be unique.']}

Allow partial update in serializer_class in Django REST

I am trying to partially update my ProfileSerializer when i am making PATCH request. However i am not able to make it beacuse by default Serializer doesn't allow partial changes to be made. I am using Django Rest Framwork UpdateModelMixin to handle my patch request. Where can i set partial=True in my case?
View:
class ProfileViewPartialUpdate(GenericAPIView, UpdateModelMixin):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
lookup_field = 'token'
lookup_url_kwarg = 'pk'
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
Serializer:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('token', 'bio', 'name', 'email', 'sport', 'location', 'image')
View:
from rest_framework import generics
class ProfileViewPartialUpdate(generics.RetrieveUpdateAPIView):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
lookup_field = 'pk'
Serializer:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('token', 'bio', 'name', 'email', 'sport', 'location', 'image')
Look at this snippet code from one of my projects. You can modify accordingly. Add this to ProfileViewPartialUpdate class instead of patch.
def partial_update(self, request, slug):
user = self.request.user
get_blog = Blog.objects.get(slug=slug)
instance = self.get_object()
serializer = BlogSerializer(instance, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(data=serializer.data, status=HTTP_201_CREATED)
return Response(data="wrong parameters", status=HTTP_400_BAD_REQUEST)
Hope this might help

Bad request 400 while trying to do partial update with UpdateAPIView

I am using DRF UpdateAPIView to take in PATCH method and partially update my model. It should by default handel correctly partial update but i somehow get Bad request error. What could be issue here?
View:
class ProfileViewUpdate(generics.UpdateAPIView):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
lookup_field = 'token'
lookup_url_kwarg = 'pk'
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
Serializer:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('token', 'bio', 'name', 'email', 'sport', 'location', 'image')

How to update modified_by field with CurrentUserDefualt

i get this error when i am trying to update modified_by field
Tried to update field sales.CustomersTag.modified_by with a model instance, <SimpleLazyObject: <UserProfile: Admin>>. Use a value compatible with CharField.
this is my serializer.py:
class CustomersTagSerializer(serializers.ModelSerializer):
created_by = serializers.CharField(read_only=True, default=serializers.CurrentUserDefault())
modified_by = serializers.CharField(read_only=True, default=serializers.CurrentUserDefault())
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.modified_by = validated_data.get('modified_by', instance.modified_by)
instance.save()
return instance
class Meta:
model = models.CustomersTag
fields = (
'id',
'name',
'created_date',
'modified_date',
'created_by',
'modified_by',
)
and this my view.py:
class CustomerTagGetIdPutView(generics.RetrieveAPIView,
mixins.UpdateModelMixin):
permission_classes = (AllowAny,)
queryset = models.CustomersTag.objects.all()
serializer_class = CustomersTagSerializer
def get_object(self):
id = self.kwargs['id']
obj = generics.get_object_or_404(models.CustomersTag, id=id)
return obj
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
i tried alot to solve this problem but i can't .. any one can help me for this problem
If you're using Django REST Framework generic views and no overriding the behavior of methods like get_serializer or get_serializer_context, your serializer will receive a context object. This context object is a dictionary with the request and the view object.
That said, you can do this by overriding create() and update() in your serializer. For example:
class CustomersTagSerializer(serializers.ModelSerializer):
class Meta:
model = models.CustomersTag
fields = (
'id',
'name',
'created_date',
'modified_date',
'created_by',
'modified_by',
)
def create(self, validated_data):
user = self.context['request'].user
return models.CustomersTag.objects.create(
created_by=user, **validated_data)
def update(self, instance, validated_data):
user = self.context['request'].user
instance.name = validated_data.get('name', instance.name)
instance.modified_by = user
instance.save()
return instance
But maybe if you want to maintain a log history of editions in your models you could use a package like django-auditlog.
You can do this while calling save() in your model.
For example:
class CustomersTagSerializer(serializers.ModelSerializer):
created_by = models.ForeignKey(User, null=True, editable=False)
modified_by = models.ForeignKey(User, null=True, editable=False)
def save(self, *args, **kwargs):
user = get_current_user()
if user and user.is_authenticated():
self.modified_by = user
if not self.id:
self.created_by = user
super(CustomersTagSerializer, self).save(*args, **kwargs)