Need success_url to vary depending on user group in CreateView - django

I have two user groups, 'Owners' and 'Employees'. They can use the same form to enter data, but I want them to be directed to a different list view upon success. I have a working CreateView:
class ServiceAddBlankView(
views.LoginRequiredMixin,
views.FormValidMessageMixin,
views.SetHeadlineMixin,
generic.CreateView
):
form_class = ServiceForm
headline = 'Add Service'
form_valid_message = "Service Entered!"
model = Service
template_name = 'wesapp/service_add.html'
success_url = '/wesapp/service_list/'
But, I want to have the success_url vary by the user group.
I want the success_url to be /wesapp/service_list/ if the user group is 'Owner' and to be /wesapp/services/ if the user group is 'Employee'.
I tried this, but it is not finding any success_url at all:
owner_group = Group.objects.get(name="Owner").user_set.all()
employee_group = Group.objects.get(name="Employee").user_set.all()
class ServiceAddBlankView(
views.LoginRequiredMixin,
views.FormValidMessageMixin,
views.SetHeadlineMixin,
generic.CreateView
):
form_class = ServiceForm
headline = 'Add Service'
form_valid_message = "Service Entered!"
model = Service
template_name = 'wesapp/service_add.html'
if user in owner_group:
success_url = '/wesapp/services/'
if user in employee_group:
success_url = '/wesapp/service_list/'
The error is:
name 'user' is not defined
How do I access the user?

It's not possible to access the user in the class definition as you are doing. Instead, the CreateView has a get_success_url method, which allows you to set the success view dynamically.
In the method, you can access the request with self.request, therefore you can access the logged in user with self.request.user.
class ServiceAddBlankView(generic.CreateView):
def get_success_url(self):
if self.request.user.groups.filter(name="Owner").exists():
return '/wesapp/services/'
elif self.request.user.groups.filter(name="Employee").exists():
return '/wesapp/service_list/'
else:
return '/fallback/url/'
I've changed the query to check whether the user is in the Owner or Employee group. In your original code, you were unnecessarily loading every Owner and Employee. Note that my code is behaves slightly different if the user is an Owner and an Employee - if that's important, you need to change it.

Django's request object has access to the user. Refer to request.user as documented here :
https://docs.djangoproject.com/en/1.8/ref/request-response/#django.http.HttpRequest.user

Related

Obtaining data from user

How do I obtain the field data from a User auth query within a class View. It's on the django 2.2.x framework using Python3
This code works just fine...
from django.contrib.auth.models import User
class PaymentsReportView(ListView):
template_name = 'payments/Payment_list.html'
userid = 'James'
queryset = Payment.objects.filter(Landlord_FK__User_id=userid)
but this doesn't...
class PaymentsReportView(ListView):
template_name = 'payments/Payment_list.html'
userid = User.username # where the username is James
queryset = Payment.objects.filter(Landlord_FK__User_id=userid)
How can I check the output of User.username to see if it's valid? What am I missing to get the data? The code doaen't break. It just returns empty.
You can't do that at class level. What you need to do is to define a get_queryset method and do the filtering there:
class PaymentsReportView(ListView):
template_name = 'payments/Payment_list.html'
def get_queryset(self):
userid = self.request.user.username
return Payment.objects.filter(Landlord_FK__User_id=userid)
Although I must note that this implementation is odd; why is the userid the username, rather than the ID? Usually I would expect the filter to be (Landlord_FK=request.user). You should show your models.

I want to pass a parameter isloggedin user to the django frontend

I am passing a list of user objects to the frontend. The frontend wants to display currently logged in users' information seperately and other users info seperately.For that I want to pass one extra field in the users serializer. I am using viewsets and serializers to pass a list of users to the django frontend.How do i do it.
My serializer looks like
class SomeUserSerializer(serializers.ModelSerializer):
"""
Serializer for `some_user` table
"""
isLogedInUser = serializers.SerializerMethodField('is_logged_in_user')
user = UserSerializer(many=False)
def is_logged_in_user(self, request):
return self.user==request.user
class Meta:
model = SomeUser
fields = ('user', 'something', 'isLogedInUser')
Something is wrong with my is_logged_in_user method. It should be returning true or false flag along with the user object depending on whether or not it is a curently logged in user
The serializer method used by isLogedInUser is taking an argument called request. However, according to the documentation, the method is called with the object being serialized, an instance of SomeUser.
You need to change the argument and get the request via additional context, like this:
class SomeUserSerializer(serializers.ModelSerializer):
"""
Serializer for `some_user` table
"""
isLogedInUser = serializers.SerializerMethodField('is_logged_in_user', context={'request': request})
user = UserSerializer(many=False)
def is_logged_in_user(self, obj):
return obj.user == self.context['request'].user
class Meta:
model = SomeUser
fields = ('user', 'something', 'isLogedInUser')

Extending User model with one to one field- how to set user instance in view

I am trying to extend the user model using a one to one relationship to a UserProfile model. I added some boolean fields and in the view I am trying to use those fields as permissions.
Here is my model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
FirstName = models.CharField(max_length=25)
LastName = models.CharField(max_length=25)
ProximityAccess = models.BooleanField(default=True)
NewProxAccess = models.BooleanField(default=False)
def __unicode__(self):
return self.user.username
and here is the view I am trying to use:
#login_required
def NewProx(request):
if UserProfile.NewProxAccess:
if request.method == 'POST':
form = ProxForm(request.POST)
if form.is_valid():
ProxPart_instance = form.save(commit=True)
ProxPart_instance.save()
return HttpResponseRedirect('/proximity')
else:
form = ProxForm()
return render(request, 'app/NewProx.html', {'form': form})
else:
raise PermissionDenied
I don't get any error messages but it does not work as intended. I was hoping that if the user profile had NewProxAccess set to False it would raise the PermissionDenied but it doesn't. I have the admin module wired up and I can select or deselect the checkbox for that field but it has no effect. If I comment out the rest I can get it to show the Permission Denied error so it has to be in the view (I think). I think I am missing a line the establishes the logged in user as the user instance so we can check to see if the user has the permission or not. I know there are a ton of ways to do this and there is probably a better way but for the sake of learning, what is it that I am missing for this to work?
Thanks
Scott
As you want to check access for particular profile but not UserProfile model you need to do:
if request.user.userprofile.NewProxAccess:
# your code
As a note: according to PEP8 best practices you should use camelCase only for naming Classes. For attrs, functions use underscore: my_function

set template_name on django ListView according to user data

my User model have a field which define there structure level in a firm.
my goal is to let each user to see his data plus extra data related to user under him.
I Have set groups permission to try and see if it would help me get what I want.
but permission is not really the point here
only redirect to different html( I want to handle logic in the back end )
on function base view this is straight foreword ( i think )
if request.user is *****
my problem is on class base view like this
class IndexHome(ListView):
model = Task
template_name = 'index.html'
I am not sure how can I access user in the class?
I know I can access the user from an instance self.request.user
but how can i make this work
class IndexHome(ListView):
user = request.user
if user.department_director.all():
department_director = list(user.department_director.all())
template_name = 'index1.html'
elif user.group_leader.all():
group_leader = list(user.group_leader.all())
template_name = 'index2.html'
elif user.team_leader.all():
team_leader = list(user.team_leader.all())
template_name = 'index3.html'
elif user.tech_leader.all():
tech_leader = list(user.tech_leader.all())
template_name = 'index4.html'
else:
template_name = 'index5.html'
model = Task
or maybe there is a way of setting template_name from the instance and my problem solved?
As with anything that you want to do dynamically in a class-based view, you need to put this into a method. In this case the appropriate method to define is get_template_names, which needs to return a tuple or list of template names.
The only other change is that you will need to refer to self.request.user, not just user.

How to filter objects by user id with tastypie?

I have the following user resource:
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'user'
fields = ['username', 'first_name', 'last_name']
allowed_methods = ['get']
filtering = {
'username': ALL,
'id': ALL,
}
and the following model resource:
class GoalResource(ModelResource):
user = fields.ForeignKey(UserResource, 'user')
class Meta:
#authentication = BasicAuthentication()
#authorization = ReadOnlyAuthorization()
queryset = Goal.objects.all()
resource_name = 'goal'
filtering = {
'user': ALL_WITH_RELATIONS,
}
I want to be able to filter the goal by user id rather than username.
I can get a list of goals from certain usernames by doing a GET request on this:
http://localhost:8000/api/v1/goal/?user__username=test
But I want to be able to sort by user id instead:
http://localhost:8000/api/v1/goal/?user__id=1
How would I get the second part to work?
Also, what is the general procedure for accessing a currently logged in user's id through Javascript? I am using backbonejs, and I want to do a post for all of a logged in user's goal. I thought about putting a hidden field on the page with the user's id. Then extracting the value of the hidden field from the DOM, but I figured it's easy to use chrome's developer tools to change the id whenever I want. Of course, I will use authentication to check that the logged in user's id matches the one that I extract from the hidden field, though. But what is the accepted way?
I am not sure if what I propose here can work in your authorization. It works for me using ApiKeyAuthorization and Authorization.
I read the idea from:
http://django-tastypie.readthedocs.org/en/latest/cookbook.html [Section: Creating per-user resources ]
My suggestion is:
What about uncommenting authentication and authorization, and overriding obj_create and apply_authorization. I am using that in my project, and it works. In the code of the method apply_authorization, I just added the if condition checking for superuser, you can just return the object_list+filter without checking that (I do it cause if is not superuser, I return data related to groups of users).
class GoalResource(ModelResource):
user = fields.ForeignKey(UserResource, 'user')
class Meta:
authentication = BasicAuthentication()
authorization = ReadOnlyAuthorization()
queryset = Goal.objects.all()
resource_name = 'goal'
filtering = {
'user': ALL_WITH_RELATIONS,
}
def obj_create(self, bundle, request=None, **kwargs):
return super(EnvironmentResource, self).obj_create(bundle, request, user=request.user)
def apply_authorization_limits(self, request, object_list):
if request.user.is_superuser:
return object_list.filter(user__id=request.GET.get('user__id',''))
Hope is what you were asking, and it helps.
best with that!
Note - apply_authorization_limits is deprecated.
The alternative way to filter by the current user, is to override read_list in you authorization class. This is what I have. My class overrides DjangoAuthorization.
def read_list(self, object_list, bundle):
klass = self.base_checks(bundle.request, object_list.model)
if klass is False:
return []
# GET-style methods are always allowed.
# Filter by user
if not hasattr(bundle.request, 'user'):
return None
object_list = object_list.filter(user__id=bundle.request.user.id)
return object_list