get current user in Django Form [duplicate] - django-forms

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
get request data in Django form
There's part of my Guest Model:
class Guest(models.Model):
event = models.ForeignKey(Event, related_name='guests')
user = models.ForeignKey(User, unique=True, related_name='guests')
...
Form to get the response from the Guest:
class RSVPForm(forms.Form):
attending_d= forms.ChoiceField(choices=VISIBLE_ATTENDING_CHOICES, initial='yes', widget=forms.RadioSelect)
attending_b = forms.ChoiceField(choices=VISIBLE_ATTENDING_CHOICES, initial='yes', widget=forms.RadioSelect)
number_of_guests = forms.IntegerField(initial=0)
comment = forms.CharField(max_length=255, required=False, widget=forms.Textarea)
....
def save(self):
guest = self.guest_class.objects.get(user=1)
guest.attending_status_d = self.cleaned_data['attending_d']
guest.attending_status_b = self.cleaned_data['attending_b']
guest.number_of_guests = self.cleaned_data['number_of_guests']
guest.comment = self.cleaned_data['comment']
guest.save()
return guest
The problem is in save method. How can I associate guest with the currently logged in user?
guest = self.Guest.objects.get(user=1)
Instead of user=1 I need to have id of the currently logged in user.
Thank you!

I found the way :)
Write a __init__ method on the form :
def __init__(self, user, *args, **kwargs):
self.user = user
super(RSVPForm, self).__init__(*args, **kwargs)
Change view function, and pass request.user to the form
def event_view(request, slug, model_class=Event, form_class=RSVPForm,
template_name='rsvp/event_view.html'):
event = get_object_or_404(model_class, slug=slug)
if request.POST:
form = form_class(request.user, request.POST)
if form.is_valid():
guest = form.save()
return HttpResponseRedirect(reverse('rsvp_event_thanks',
kwargs={'slug': slug, 'guest_id': guest.id}))
else:
form = form_class(request.user)
return render_to_response(template_name, {
'event': event,
'form': form,
}, context_instance=RequestContext(request))
the line of the save() method would look like this now:
guest = self.guest_class.objects.get(user=self.user)

Related

django - pass request.user to ModelForm

i am having a tricky issue. In my views.py i am passing a form in a DetailView. But i am not using a FormMixin. That has the reason that i only want my template to render the form. In the template i use that form to trigger an UpdateView.
class UpdateDetailView(LoginRequiredMixin, DetailView):
model = Balance
def get_context_data(self, **kwargs):
context = super(UpdateDetailView, self).get_context_data(**kwargs)
context['form'] = ManagerForm
return context
def get_queryset(self, *args, **kwargs):
request = self.request
pk = self.kwargs.get('pk')
select = self.kwargs.get('select')
queryset = Balance.objects.filter(pk=pk).filter(owner = request.user).filter(select = select)
return queryset
class BalanceUpdateView(LoginRequiredMixin, UpdateView):
form_class = ManagerForm
model = Balance
def get_success_url(self):
return reverse('url-year', kwargs={'year': self.object.year, 'select': self.object.select})
So far, so good. The issue is that the form in the UpdateDetailView the ChoiceFields are showing select option of other users which one is not supposed to see. Thus i need to override the queryset of the Modelform. Usually i could use the get_form_kwargs method to pass the request.user to the form. But since the UpdateDetailView is not a FormView it doesnt have that (i know, coz i tried desperately). I also tried context['form'] = ManagerForm(initial = {'user': self.request.user}) in the get_context_data method. But i was unable to access user properly with the __init__ method in the forms.py. I got a key error. If i passed it as arg then i get an attribute error. Does anyone have a solution to that problem? Do i need to use a FormMixin?
Thank you for your replies!

django rest permission called many times

So I'm building a simple blog app and made custom permission so only owner of post can update or delete the post, so I added print statment to check if it's working but found out it's called 6 times every time calling the view!
here's the code
class PostUpdateDeletePermission(IsAuthenticated):
def has_object_permission(self, request, view, obj):
print("called")
if request.user.is_superuser:
return True
if (request.method == 'PUT' or request.method == 'DELETE') and request.user != obj.user:
return False
return True
class PostView(ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = (PostUpdateDeletePermission,)
def create(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
obj = serializer.save(user=request.user)
if request.data.get('files_length'):
PostFile.objects.bulk_create([PostFile(img = request.data.get(f"file-{x}"), post=obj) for x in range(request.data.get('files_length'))])
return Response({'posts' : serializer.data}, status=201)
that's how many times called printed when refreshing the drf browsable api
called
called
called
called
called
called

How to update another field when using partial_update?

I'm using partial_updates on my user model, and I wish to change the is_active to True on the user model instance when a partial_update happens - even though is_active is not exposed to the endpoint. My class looks like this:
class UserInvitationUpdate(mixins.UpdateModelMixin, generics.GenericAPIView):
serializer_class = serializers.UserSerializer
queryset = User.objects.all()
def get(request, *args, **kwargs):
username = kwargs.get('username')
token = kwargs.get('token')
return activated_user(username, token)
def get_object(self):
username = self.kwargs.get('username')
user = User.objects.get(username=username)
return user
def put(self, request, *args, **kwargs):
username = self.kwargs.get('username')
token = self.kwargs.get('token')
if my_if_statement_is_true:
# TODO set user to active
# how do I set is_active = True for the user model instance?
return self.partial_update(request, *args, **kwargs)
You have multiple way to deal with that. You could either change your serializer .save() method and set manually the field is_active to true, or set it in the view by updating the perform_update() method of your view :
def perform_update(self, serializer):
serializer.save(is_active=True)
More info here

passwords is changing for all users in django rest

I have made an API for password change but it's changing the passwords for all users instead of only one user.
seriealizer code is below:
class ChangePasswordSerializer(serializers.ModelSerializer):
password1 = serializers.CharField(write_only=True, required=True, validators=[validate_password])
password2 = serializers.CharField(write_only=True, required=True)
old_password = serializers.CharField(write_only=True, required=True)
class Meta:
model = User
fields = ('old_password', 'password1', 'password2')
def validate(self, attrs):
if attrs['password1'] != attrs['password2']:
raise serializers.ValidationError({"password": "Password fields didn't match."})
return attrs
def validate_old_password(self, value):
user = self.context['request'].user
if not user.check_password(value):
raise serializers.ValidationError({"old_password": "Old password is not correct"})
return value
def update(self, instance, validated_data):
instance.set_password(validated_data['password1'])
instance.save()
return instance
view code is below:
class ChangePasswordView(generics.UpdateAPIView):
queryset = User.objects.all()
permission_classes = (IsAuthenticated,)
serializer_class = ChangePasswordSerializer
what is wrong with this code ?
Password change is very straight forward. Django already has a form to do it. Try the below code:
#api_view(['PUT'])
#permission_classes([IsAuthenticated])
def change_password(request):
form = PasswordChangeForm(request.user, request.data)
if form.is_valid():
form.save()
serializer = UserSerializer(request.user)
return Response(serializer.data)
return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)
Read this page for more information on how to build user auth methods using DRF: https://kushgoyal.com/creating-a-sceure-login-api-using-drf-token-auth/
url for this will be of this format:
url(r'change_password/', views.change_password)

how to use check_password inside validate function?

I have this serializer:
class ChangePasswordSerializer(DynamicFieldsModelSerializer):
current = serializers.CharField()
confirm = serializers.CharField()
class Meta:
model = models.User
fields = ('password', 'current', 'confirm')
validators = []
def update(self, instance, validated_data):
if instance.check_password(validated_data.get('current')):
instance.set_password(validated_data['password'])
instance.save()
else:
raise serializers.ValidationError("Current password is not correct")
return instance
I have this inside my update function:
instance.check_password(validated_data.get('current'))
but I want this action happens outside of function update in validate_current function, but I dont know how
You can write custom validator for the current password
def validate_current(self, value):
if not self.instance.check_password(value):
raise serializers.ValidationError("Current password is not correct")
return value
you will have to pass instance from view in serializer

Resources