How do I get the request.user.id in serializer method field? - python

Here is my serializer method field:
def get_is_user_to_user(self, obj):
return obj.to_user == self.context.get('request').user.id
I want the method to return a boolean value of True if obj.to_user which is a field in the corresponding model equals the request.user.id. The method field at the moment always returns False even when it should be returning True.
How do I check if obj.to_user is equal to the request.user.id from the serializer method field?

def get_is_user_to_user(self, obj):
return obj.to_user == self.context.get('request').user.id
I think your FK obj.to_user is a User instance, you can not compare with self.context.get('request').user.id.
Your code should:
def get_is_user_to_user(self, obj):
return obj.to_user.id == self.context.get('request').user.id
Or:
def get_is_user_to_user(self, obj):
return obj.to_user == self.context.get('request').user # Make sure you did not override request.user before.

I used below Sample View
class CurrentUserView(APIView):
def get(self, request):
serializer = UserSerializer(request.user)
return Response({"user": serializer.data})

You can define a method i user model then use at as a field
E.g.:
class User(AbstractUser):
def chechsomething(self):
if something :
return True
return False

Related

Different serializers based on user object rights

I'm looking for a way to use different serializers within a ModelViewSet depending on the request.user properties making the call.
Case 1:
The request.user is the owner of the profile and must use the serializer called 'UserProfileOwnerSerializer' which allows a partial edit of their properties.
Case 2:
request.user has full control rights over profiles properties and must therefore use 'UserProfileViewEditSerializer'
Case 3:
request.user has only read rights on user profiles and must use 'UserProfileViewOnlySerializer' which sets all fields to readonly.
I created 3 permission checkers also used to check permissions within 'permissions.BasePermission':
def haveProfileOwnerRights(request, obj):
if (request.user.userprofile.id == obj.id):
return True
else:
return False
def haveProfileViewRights(request):
roleRightsProfileView = [
'MA',
'AM',
'ME',
'VI',
]
role = request.user.userprofile.role
if (role in roleRightsProfileView):
return True
else:
return False
def haveProfileViewEditRights(request):
roleRightsProfileViewEdit = [
'MA',
'AM',
'ME',
]
role = request.user.userprofile.role
if (role in roleRightsProfileViewEdit):
return True
else:
return False
class IsOwnerOrHaveProfileViewEditOrViewRight(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if (request.user.is_anonymous):
return False
if (haveProfileOwnerRights(request, obj)):
return True
if (haveProfileViewEditRights(request)):
return True
return False
class UserProfileViewSet(viewsets.ModelViewSet):
permission_classes = [
permissions.IsAuthenticated, IsOwnerOrHaveProfileViewEditOrViewRight
]
queryset = UserProfile.objects.all()
def get_serializer_class(self):
if haveProfileViewEditRights(self.request):
return UserProfileViewEditSerializer
if haveProfileViewRights(self.request):
return UserProfileViewOnlySerializer
#
# MISSING SERIALIZERS FOR 'UserProfileOwnerSerializer'
# I need to know here the content of the object to be serialized
#
To check if the serializer that I have to use for users who have 'haveProfileOwnerRights' I must be able to know the content of the object in order to pass it as a parameter to the 'haveProfileOwnerRights' function.
How can I get the object to be serialized inside 'get_serializer_class'?
Or is there a different approach that allows me to achieve the same result but in a different way?
Please save my brain :-)
You can override get_serializer(). It should receive the instance as the first argument.
class UserProfileViewSet(viewsets.ModelViewSet):
def get_serializer(self, instance=None, *args, **kwargs):
if instance.type == "xxx":
serializer_class = # set it depending on your conditions
else:
serializer_class = self.get_serializer_class()
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(instance, *args, **kwargs)

Set initial value in a form in Django

I have a model in my application:
models.py:
class bdAccesorios(models.Model):
fdClienteAcc=models.CharField(max_length=35)
fdProveedorAcc=models.CharField(max_length=60)
fdSkuAcc=models.CharField(max_length=30)
fdNombreAcc=models.CharField(max_length=60)
fdCostoAcc=models.DecimalField(max_digits=8, decimal_places=2)
fdUnidadAcc=models.CharField(max_length=30)
fdExistenciaAcc=models.IntegerField()
fdAuxAcc=models.CharField(max_length=60, default="0")
Then, I have a form to add new entries to the model
class fmAccesorios(ModelForm):
class Meta:
model=bdAccesorios
fields='__all__'
What I can't accomplish is that the form starts with an initial value, so far what I have done in my views is this, but the field shows blank
views.py
def vwCrearAccesorio(request):
vrCrearAcc=fmAccesorios(initial={'fdClienteAcc':"foo"}) ###Here is the problem ###
if request.method == "POST":
vrCrearAcc=fmAccesorios(request.POST)
if vrCrearAcc.is_valid():
vrCrearAcc.save()
return redirect('/')
else:
vrCrearAcc=fmAccesorios()
return render(request,"MyApp/CrearAccesorio.html",{
"dtCrearAcc":vrCrearAcc
})
MORE INFO:
I know that I can use the following code in my form to set initial values
def __init__(self, *args, **kwargs):
super(fmAccesorios, self).__init__(*args, **kwargs)
self.fields['fdClienteAcc'].disabled = True
self.fields['fdClienteAcc'].initial = "foo"
But I can't use that, because I need the variable "foo" to change dynamically, my ultimate goal is to use
the request.user.username variable and then use that variable to get another value from another model
In your view you have to pass the current instance you need to the form like this:
def vwCrearAccesorio(request):
vrCrearAcc=fmAccesorios(initial={'fdClienteAcc':"foo"}) # this will not be used because you reassign `vrCrearAcc` later
if request.method == "POST":
vrCrearAcc=fmAccesorios(request.POST, initial={'fdClienteAcc':"foo"}) # pass it here
if vrCrearAcc.is_valid():
vrCrearAcc.save()
return redirect('/')
else:
vrCrearAcc=fmAccesorios(initial={'fdClienteAcc':"foo"}) # and here
return render(request,"MyApp/CrearAccesorio.html",{
"dtCrearAcc":vrCrearAcc
})

How do you modify form data before saving it while using Django's CreateView?

I'm using the CreateView of Django and I'm trying to find out how I can modify any text which gets sent before it gets saved. For example, right now I'm only looking to lowercase all the text before saving.
I know I need to use form_valid() but I can't seem to get it right.
forms.py
class ConfigForm(forms.ModelForm):
class Meta:
model = Config
fields = ["heading", "name", "data", "rating"]
views.py
def form_valid(self, form):
super().form_valid(form)
form.fields["heading"].lower()
form.fields["name"].lower()
form.fields["data"].lower()
That shouldn't be done in form_valid. You should do that in the form itself. Instead of letting CreateView automatically create a form for you, do it explicitly and overwrite the clean method.
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ('list', 'of', 'fields')
def clean(self):
for field, value in self.cleaned_data.items():
self.cleaned_data['field'] = value.lower()
...
class MyCreateView(views.CreateView):
form_class = MyForm
Override get_form_kwargs method to update the kwargs which instantiates the form.
Solution:
def get_form_kwargs(self):
# update super call if python < 3
form_kwargs = super().get_form_kwargs()
form_kwargs['data']['str_field_name'] = form_kwargs['data']['str_field_name'].lower()
return form_kwargs
Ref:
get_form_kwargs docs
While it may not be the nicest solution, it can be done like this:
def form_valid(self, form):
self.object = form.save(commit=False)
# ...
self.object.save()
return http.HttpResponseRedirect(self.get_success_url())
Just for the record
In the first case
def get_form_kwargs(self):
# update super call if python < 3
form_kwargs = super().get_form_kwargs()
form_kwargs['data']['str_field_name'] = form_kwargs['data'['str_field_name'].lower()
return form_kwargs
Django complains "This QueryDict instance is immutable". And workaround is
data = kwargs['data'].copy() # mutable copy
data['foo'] = 'whatever' #supply the missing default value
kwargs['data'] = data

Return different reponse or data depending on method - Django rest framework

Please help. What I need to do is to get different responses or data depending on the method- something like this:
if request.method == 'POST':
return all
the items created including the last one (actually it returns only >the last item created)
else if request.method == 'PUT':
return the last item updated
Views.py
class RubroViewSet(viewsets.ModelViewSet):
queryset = Rubro.objects.all()
serializer_class = RubroSerializer
models.py
class Rubro(models.Model):
nombre = models.CharField(max_length=50)
descripcion = models.TextField()
class Meta:
verbose_name_plural = 'Rubros'
db_table = "core_rubros"
def __str__(self):
return self.nombre
serializers.py
class RubroSerializer(serializers.ModelSerializer):
class Meta:
model = Rubro
fields = '__all__'
Using viewsets.Viewset would be an easy way.
http://www.django-rest-framework.org/api-guide/viewsets/
or use #detail_route()
#detail_route(methods=['post'])
def some_method(self, request):
serializer = RubroSerializer(data=request.data)
if serializer.is_valid():
return Response({'status': 'success'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
Actually viewset allows you to implement create and update methods in viewset to control logic of different types of request. In your case you can do something like this:
class RubroViewSet(viewsets.ModelViewSet):
queryset = Rubro.objects.all()
serializer_class = RubroSerializer
# POST
def create(self, request):
super().create(request)
serializer = self.serializer(self.queryset, many=True)
return Response(serializer.data, status=status.HTTP_201_CREATED)
# PUT
def update(self, request, pk=None):
return super().update(request, pk)
1.Way:
You could use "yield" instead "return".
This may be support...
2.Way:
def __str__(self):
for n in self:
return self.n

Django: checking request user against object.owner

I've custom CBV delete view which should check object's owner against request.user.
What is the good practice to do it?
Currently I've been checking as shown below
equal_usernames = some_object.user.username in request.user.username
equal_emails = some_object.user.email in request.user.email
if equal_usernames and equal_emails:
# some actions
Sultan
As simple as:
some_object.user == request.user
Because Model as __eq__ defined as such:
def __eq__(self, other):
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
So it's "equal" as long as it's the same model class with the same pk.

Categories

Resources