Django request.user.has_perm('aaa.add_cust') - django-rest-framework

Hello I am so confused and new to Django.
I keep getting "False" returned to me when checking user permission. but when I print the results it is clearly detects the user permission. I am trying to add a #permission_required decorator to the view but I just won't work.
##permission_required('aaa.add_cust',raise_exception=True)
view.py
def permtest_view(request):
user_name = request.user
user_perm = request.user.get_all_permissions()
user_test = request.user.has_perm('aaa.add_cust')
print(user_name,user_perm,user_test)
Models.py
class cust(models.Model):
cust = models.CharField(max_length=10)
Serializer
class cust_serializer(serializers.ModelSerializer):
class Meta:
model = cust
fileds = "__all__"
output of the print statement.
test1#test1.com {'aaa.add_cust'} False
I can get the user and the perm but when I do
user_test = request.user.has_perm('aaa.add_cust')
I get "False" back every time
I rely don't know what I am doing wrong.

I built my own customised Decorator.

Related

How to get the id of a current object in Django serializers?

I have a model, 'Project'. The idea is that, a user will log in and create a project. After creating, the user will work on this project at any time. Certain details will be saved to other models where I have written custom functions for it in Serializers.py.
In order solve the idea I have, I need to retrieve the id of the current project that the user is currently working on in Serializers.py. Below is my code:
View.py
class MaterialTagExcelViewSet(FilteredModelViewSet):
queryset = MaterialTagExcel.objects.all()
serializer_class = MaterialTagExcelSerializer
permission_classes = (IsAuthenticated,)
http_method_names = ('get', 'head', 'post', 'options', 'patch')
Serializers.py
class MaterialTagExcelSerializer(BaseSerializer):
class Meta:
fields = "__all__"
model = MaterialTagExcel
def create(self, validated_data):
name = validated_data.get('name') # get current material name
if name is not None:
name_tag = MaterialTagExcel.objects.filter(name=name).first() # filter name to check if it already exists
client = self.context['request'].user.profile.client # get current client details
if name_tag is not None: # if name exists
objects = MaterialExcelClient.objects.filter(client_id=client.id, name_id=name_tag.id)
if objects.count() == 0:
material_excel_client = MaterialExcelClient(client_id=client.id, name_id=name_tag.id)
material_excel_client.save() # get current id and mat id and save to material_client_excel
return MaterialExcelClient.objects.filter(name_id=name_tag.id).order_by('-id')[0]
else:
return MaterialExcelClient.objects.filter(client_id=client.id, name_id=name_tag.id).first()
else:
MaterialTagExcel.objects.create(**validated_data)
MaterialTagExcel.objects.all() # save if material is new and does not exist
# return the id of this newly created material
obj = MaterialTagExcel.objects.filter(name=name).order_by('-id')[0]
# save the id of the newly created material and current client id into material_excel_client
material_excel_client = MaterialExcelClient(client_id=client.id, name_id=obj.id)
material_excel_client.save()
return MaterialExcelClient.objects.filter(name_id=obj.id).order_by('-id')[0]
From above serializer, I am able to get the client.id with the help of CurrentUserDefault. In my table user is related to profile and profile is related to client but not project. I tried to with a custom CurrentProjectDefault, but I didnt succeeded. I tried with many online sources to solve my problem.
Is there any way to get the id of the current object from client ?
I am apologizing in advance if the solution to my problem is very simple.
If you would need some more details, kindly write it in comment.
Thanks in advance.
Models.py
class MaterialTagExcel():
name = models.CharField(max_length=255, verbose_name='name', null=False, blank=False)
def __str__(self):
return "Material %s: %s" % (self.id, self.name)
#classmethod
def get_queryset_for_user(cls, user):
return cls.objects.all()
class Project():
client = models.ForeignKey(Client, related_name='projects', on_delete=models.PROTECT)
name = models.CharField(max_length=255)
class ToDo(BaseModel):
project = models.ForeignKey(Project, related_name='todos', on_delete=models.CASCADE)
owner_client = models.ForeignKey(Client, related_name='todos', on_delete=models.CASCADE)
You wish to retrieve the current project the user is working on. The goal of a REST API is to be stateless, which roughly means that the request contains all the necessary information to perform its action without relying on an external context.
This means that you have to provide the current project id in each of your request.
So, in your example, when you want to POST a new MaterialTagExcel, you'll have to provide the Project. You can modify your serializer like this to do so:
class MaterialTagExcelSerializer(BaseSerializer):
project = serializers.PrimaryKeyRelatedField(write_only=True, queryset=Project.objects.all())
class Meta:
fields = "__all__"
model = MaterialTagExcel
def create(self, validated_data):
name = validated_data.get('name')
project = validated_data.pop('project') # A Project object
Now, when you're doing a request, you'll have to specify the property project with the id. of the project the user has selected in the menu.

Django REST Framework - optimizing nested serialization of a queryset

I have a model and serializer like this:
models.py
class CalendarEvent(BaseMixin):
title = models.TextField(blank=True, null=True)
class CalendarEventReminder(BaseMixin):
event = models.ForeignKey(CalendarEvent, related_name = 'reminders')
minutes = models.CharField()
class Meta:
managed = False
db_table = 'calendar_event_reminder'
def __str__(self):
return self.minutes
serializer.py
class CalendarEventSerializer(serializers.ModelSerializer):
reminders = serializers.StringRelatedField(many=True)
class Meta:
model = CalendarEvent
fields = ('title', 'reminders')
In my view, I do the following:
def test(request):
#...
event = CalendarEvent.objects.filter(id__in = [930, 935])
serializer = CalendarEventSerializer(event, many = True)
print (serializer.data)
#...
When I open the Debug Toolbar, I see that the database hits reminders table twice for each of the calendar events.
The question is, how this behavior could be optimized.
The most straight-forward way would be prefetching the CalendarEventReminders of the CalendarEvents in your view:
# views.py
def get(request):
event = CalendarEvent.objects.filter(id__in = [930, 935]) \
.prefetch_related('reminders')
# ...
This will prefetch all CalendarEventReminders while getting the CalendarEvents.
Note that this will not trigger a sql join like select_related() would do. We can't use select_related() in this case because we're following the relation backwards. :)
Check out the Django Docs regarding prefetch_related.

Django rest framework - Raising exception / Handling empty results while filtering

I have a user profile class and am checking if a user exists and if not want to create that user.
Am using the filter class for userprofile so that the client can call :
http://localhost:8000/users/?email=a#b.com
and if the result is empty will create a user with the email address.
Is there a way to intercept the query result and raise an exception when its empty and handle that to create the user.
If there is a better way would like to be corrected as well.
class UserQueryFilter(django_filters.rest_framework.FilterSet):
email = django_filters.CharFilter(name="user__email")
username = django_filters.CharFilter(name="user__username")
class Meta:
model = UserProfile
fields = ['email', 'username']
class UserViewSet(viewsets.ReadOnlyModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserSerializer
filter_class = UserQueryFilter
Any help is appreciated.
Thanks
Anand
Django Rest Framework provide a functionality that is disabled by default. Maybe it could give you another approach to resolve your problem: PUT as create
In other hand, if you really need to create the user through a GET request with a querystring, you can use a MethodFilter from django-filters, for example:
class UserFilters(FilterSet):
user = MethodFilter(action='filter_user')
class Meta:
model = User
fields = ['user']
def filter_user(self, queryset, value):
if not value:
# Here Raise Exception
else:
# Check if the user exists, if not create it
users = queryset.filter(Q(username=value) | Q(email=value))
if not users.exists:
user = User.objects.create(...)
return queryset.filter(pk=user.id)
else:
return users
Hope this can help you. I'm not pretty sure about it works in that exact way but it's the idea.
Personally, I recommend you that try to execute that tasks through a more appropriate request like POST or PUT and manage in the corresponding method.

Django 1.3 CreateView, ModelForm and filtering fields by request.user

I am trying to filter a field on a ModelForm. I am subclassing the generic CreateView for my view. I found many references to my problem on the web, but the solutions do not seem to work (for me at least) with Django 1.3's class-based views.
Here are my models:
#models.py
class Subscriber(models.Model):
user = models.ForeignKey(User)
subscriber_list = models.ManyToManyField('SubscriberList')
....
class SubscriberList(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=70)
....
Here is my view:
#views.py
class SubscriberCreateView(AuthCreateView):
model = Subscriber
template_name = "forms/app.html"
form_class = SubscriberForm
success_url = "/app/subscribers/"
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
return super(SubscriberCreateView, self).form_valid(form)
Here is my original form for adding a Subscriber, with no filter:
#forms.py
class SubscriberForm(ModelForm):
class Meta:
model = Subscriber
exclude = ('user', 'facebook_id', 'twitter_id')
Here is my modified form, attempting to filter, but doesn't work:
#forms.py
class SubscriberForm(ModelForm):
class Meta:
model = Subscriber
exclude = ('user', 'facebook_id', 'twitter_id')
def __init__(self, user, **kwargs):
super(SubscriberForm, self).__init__(**kwargs)
self.fields['subscriber_list'].queryset = SubscriberList.objects.filter(user=user)
If I change this modified form as so:
def __init__(self, user=None, **kwargs)
It works - It brings me NO subscriber lists. But any way I try to pass the request user, I invariably get a a name "request" or name "self" not defined error.
So, how can I modify my code to filter subscriber_list by the request.user, and still use Django 1.3's CreateView.
I see you've been posting this question in various places.. and the way I found that is because I was trying to figure out the same thing. I think I just got it working, and here's what I did. I overwrote get_form() from FormMixin to filter a specific form fields queryset:
class MyCreateView(CreateView):
def get_form(self, form_class):
form = super(MyCreateView,self).get_form(form_class) #instantiate using parent
form.fields['my_list'].queryset = MyObject.objects.filter(user=self.request.user)
return form

Django Ajax field help

I have a Django application where I'm trying to have a form that populates a drop down dynamically based on a previous dropdown.
simplified Models:
class VehicleMake(models.Model):
make = models.CharField(max_length = 30)
class VehicleModel(models.Model):
model = models.CharField(max_length = 80)
make = models.ForeignKey(VehicleMake)
class Listing(models.Model):
make = models.ForeignKey(VehicleMake)
model = models.ForeignKey(VehicleModel)
Form:
class DynamicChoiceField(ModelChoiceField):
def clean(self, value):
return value
class MyForm(ModelForm):
category = ModelChoiceField(VehicleCategory.objects, widget=forms.Select(attrs={'onchange':'FilterMakes();'}))
make = DynamicChoiceField(VehicleMake.objects,widget=forms.Select(attrs={'disabled':'true','onchange':'FilterModels();'}), empty_label="Select Model")
model = DynamicChoiceField(VehicleModel.objects,widget=forms.Select(attrs={'disabled':'true'}), empty_label="Select Make")
class Meta:
model = Listing
View:
def new_listing(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
form.save()
else:
form = MyForm()
return render_to_response("newlisting.html", {
"form": form,'model_id':model_id,'make_id':make_id
})
I also have some ajax defined for the auto-populate but this is not the problem
When I submit the form I get the following:
Cannot assign "u'2'": "Listing.make" must be a "VehicleMake" instance.
if I try
make=VehicleMake.objects.get(pk=request.POST['make'])
form.fields['make'] = make
then I get
'VehicleMake' object has no attribute 'widget'
After the suggestion of one of the commenter's that the DynamicChoiceField class was the culprit I removed it and set the form objects for ModelChoiceFields with the exact same other parameters. The object appears to pass and validate correctly as well. The extra class existed based on an old tutorial I found. it appears that what the author did there works with the forms.ChoiceField but is not required for using a ModelChoiceField
thanks everyone for the help

Resources