I am using the Django REST framework and I'm trying to send a mail with sendgrid inside an action.
Here is my code:
#action(detail=True, methods=['GET', 'POST', 'DELETE'])
def invite(se1f, request, pk=None):
workspace = self.get_object()
if request.method == 'GET':
users = workspace.users.all()
serialized = UserSerializer(users, many=True)
return Response(status=status.HTTP_200_OK, data=serialized.data)
elif request.method == 'POST':
id = request.data.get('id', None)
if id:
#user = User.objectsoget(id=id)
user = get_object_or_404(User, id=id)
workspace.users.add(user)
return Response(status=status.HTTP_200_OK)
send_mail('Subject here', 'Here is the message.', 'from#examp1e.com', ['from#examp1e.com'],
fail_silently=False)
call send_mail() before the return statement.
#action(detail=True, methods=['GET', 'POST', 'DELETE'])
def invite(self, request, pk=None):
workspace = self.get_object()
if request.method == 'GET':
users = workspace.users.all()
serialized = UserSerializer(users, many=True)
return Response(status=status.HTTP_200_OK, data=serialized.data)
elif request.method == 'POST':
id = request.data.get('id', None)
if id:
#user = User.objectsoget(id=id)
user = get_object_or_404(User, id=id)
workspace.users.add(user)
send_mail('Subject here', 'Here is the message.', 'from#examp1e.com', ['from#examp1e.com'],fail_silently=False)
return Response(status=status.HTTP_200_OK)
Related
I am trying to get the list of all users from the group "Manager", the post request works
#api_view(['GET','POST'])
def managers(request):
username = request.data['username']
if username:
user = get_object_or_404(User, username=username)
managers = Group.objects.get(name="Manager")
if request.method == 'POST':
managers.user_set.add(user)
elif request.method == 'DELETE':
managers.user_set.remove(user)
return Response({"message": "ok"})
return Response({"message": "error"}, status.HTTP_400_BAD_REQUEST)
I got this error below.
KeyError at /api/groups/manager/users 'username'
Please, can I get a guide?
In case it is a GET request, you can work with:
#api_view(['GET', 'POST', 'DELETE'])
def managers(request):
if request.method == 'GET':
users = User.objects.filter(groups__name='Manager')
serializer = UserSerializer(users, many=True)
return Response({'data': serializer.data})
username = request.data['username']
if username:
user = get_object_or_404(User, username=username)
managers = Group.objects.get(name='Manager')
if request.method == 'POST':
managers.user_set.add(user)
elif request.method == 'DELETE':
managers.user_set.remove(user)
return Response({"message": 'ok'})
return Response({'message': 'error'}, status.HTTP_400_BAD_REQUEST)
With UserSerializer a ModelSerializer for the User model.
For the benefit of others. Thank you Willem Van Onsem
users = User.objects.filter(groups__name='Manager')
I have multiple links on my page which redirects user to take quiz.
Some quiz requires user to login or create an account and some does not.
def dispatch(self, request, *args, **kwargs):
self.quiz = get_object_or_404(Quiz, url=self.kwargs['quiz_name'])
if self.quiz.draft and not request.user.has_perm('quiz.change_quiz'):
raise PermissionDenied
try:
self.logged_in_user = self.request.user.is_authenticated()
except TypeError:
self.logged_in_user = self.request.user.is_authenticated
if self.logged_in_user:
self.sitting = Sitting.objects.user_sitting(request.user,
self.quiz)
else:
self.sitting = self.anon_load_sitting()
if self.sitting is False:
if self.logged_in_user:
return render(request, self.single_complete_template_name)
else:
return redirect(settings.LOGIN_URL)
return super(QuizTake, self).dispatch(request, *args, **kwargs)
I would like user to redirect like how method decorator does
login/?next=/quiz/f506cb92-ccca-49ff-b2e5-730bbfea6a5a/take/
but instead I get /login/
I would like my user to come back to the page instead of going to "/dashboard"
In my settings I have
LOGIN_REDIRECT_URL ="/dashboard"
My LoginView:
class LoginView(FormView):
template_name = 'login.html'
form_class = LoginForm
success_url = '/dashboard'
def get(self, request, *args, **kwargs):
if request.user.is_authenticated:
return redirect ("/dashboard")
else:
return super(LoginView, self).get(request, *args, **kwargs)
def dispatch(self, request, *args, **kwargs):
if (self.request.user.is_authenticated) and (self.request.user.user_type==4):
return redirect('/dashboard')
else:
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
"""Use this to add extra context."""
context = super(LoginView, self).get_context_data(**kwargs)
if 'show_captcha' in self.request.session:
show_captcha = self.request.session['show_captcha']
context['show_captcha'] = True
return context
def form_valid(self, form):
user = form.login(self.request)
recaptcha_response = self.request.POST.get('g-recaptcha-response')
url = 'https://www.google.com/recaptcha/api/siteverify'
payload = {
'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
'response': recaptcha_response
}
data = urllib.parse.urlencode(payload).encode()
req = urllib.request.Request(url, data=data)
# verify the token submitted with the form is valid
response = urllib.request.urlopen(req)
result = json.loads(response.read().decode())
if result['success']:
if user.two_factor_auth is False and (user.phone_number_verified is True):
login(self.request, user)
try:
UserLog.objects.filter(username=user.id).update(failed_attempt=0)
except Exception:
print("No failed attempts ")
return redirect('/dashboard')
else:
try:
response = send_verfication_code(user)
pass
except Exception as e:
messages.add_message(self.request, messages.ERROR,
'verification code not sent. \n'
'Please retry logging in.')
return redirect('/login')
data = json.loads(response.text)
if data['success'] == False:
messages.add_message(self.request, messages.ERROR,
data['message'])
return redirect('/login')
if data['success'] == True:
self.request.method = "GET"
print(self.request.method)
kwargs = {'user':user}
return PhoneVerificationView(self.request, **kwargs)
else:
messages.add_message(self.request, messages.ERROR,
data['message'])
return redirect('/login')
else:
messages.add_message(self.request, messages.ERROR, 'Invalid reCAPTCHA. Please try again.')
return redirect('/login')
You should be fine by using #login_required() decorator docs are here.
This appends a ?next=... field which within login field you can take from the request.REQUEST.get('next', '/dashboard') and use this for redirect on successful login also look up this question to see if any other answer there satisifies the requirements
Also since you don't want decorators you can try saving to session as request.session["next"]=(source url) and within login view get session param and use it
I am trying to write a a Function-based View (FBV) as a Class-based View (CBV), specifically a CreateView. So far I have been able to write the FBV as a generic View but not as a CreateView. How would I go about doing this?
FBV
def register(request):
registered = False
if request.method == 'POST':
user_form = UserCreationForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
registered = True
else:
print(user_form.errors)
else:
user_form = UserCreationForm()
return render(request,'accounts/registration.html', {'user_form':user_form, 'registered':registered})
Converted View
class RegisterView(View):
def get(self, request):
registered = False
user_form = UserCreationForm()
return render(request,'accounts/registration.html', {'user_form':user_form, 'registered':registered})
def post(self, request):
registered = False
user_form = UserCreationForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
registered = True
else:
print(user_form.errors)
return render(request,'accounts/registration.html', {'user_form':user_form, 'registered':registered})
You may follow it
class RegisterView(CreateView):
model = User
form_class = UserCreationForm
template_name = 'accounts/registration.html'
def post(self, request, *args, **kwargs):
registered = False
user_form = UserCreationForm(data=request.POST)
if user_form.is_valid():
user = user_form.save(commit=False)
user.set_password(user.password)
user.save()
registered = True
else:
print(user_form.errors)
return render(request,'accounts/registration.html', {'user_form':user_form, 'registered':registered})
I just started with Python and Django and want to redirect a user to a home page after successful form-registration with a head-massage changed to "You have successfully registered".
My code without changing a massage after redirection is:
urls.py:
urlpatterns = [
path('', IndexView.as_view(), name = 'index'),
path('register/', views.register, name = 'register'),
]
views.py:
class IndexView(TemplateView):
template_name = 'first_ap/index.html'
def get_context_data(self, *args, **kwargs):
t_user = 'Hello my friend'
context = {
'viva':t_user
}
return context
def register(request):
if request.method == "POST":
form = RegForm(request.POST)
if form.is_valid():
new_user = form.save(commit=False)
new_user.set_password(form.cleaned_data['password'])
new_user.save()
return redirect('index')
else:
form = RegForm()
return render(request, 'first_ap/register.html', {'form': form})
In html file I put:
<h1>{{ viva }}!</h1>
How should I modify a code to change a context after redirection from "Hello my friend" to "You have successfully registered"? I tried several options but they all failed.
Why dont you just save the message in an object variable:
class IndexView(TemplateView):
template_name = 'first_ap/index.html'
text='Hello my friend'
def get_context_data(self, *args, **kwargs):
context = {
'viva':self.text
}
return context
def register(request):
if request.method == "POST":
form = RegForm(request.POST)
if form.is_valid():
IndexView.text='You have registered'
new_user = form.save(commit=False)
new_user.set_password(form.cleaned_data['password'])
new_user.save()
return redirect('index')
else:
form = RegForm()
return render(request, 'first_ap/register.html', {'form': form})
Solution:
from django.urls import reverse
class IndexView(TemplateView):
template_name = 'first_ap/index.html'
def get_context_data(self, *args, **kwargs):
# request.GET contains the query parameters, check if `first_visit` is 1 or not
is_first_visit = self.request.GET.get('first_visit', 0) == "1"
if is_first_visit is False:
t_user = 'Hello my friend'
else:
t_user = 'You have successfully registered'
context = {
'viva': t_user
}
return context
def register(request):
if request.method == "POST":
form = RegForm(request.POST)
if form.is_valid():
new_user = form.save(commit=False)
new_user.set_password(form.cleaned_data['password'])
new_user.save()
# add a query parameter to indicate user's first visit
return redirect(reverse('index') + "?first_visit=1")
else:
form = RegForm()
return render(request, 'first_ap/register.html', {'form': form})
Add a query parameter first_visit as 1 (random value) in the redirect call after successful registration.
Access the query parameter using self.request.GET dict
Change the context value based on the value of first_visit
my ModelForm definition looks like this:
class UserForm(ModelForm):
password = forms.CharField(required=True, label="Password", widget=forms.PasswordInput)
So password is required when I'm creating a new user. However I'd like to NOT require it when editing the user. My edit/add is handled in views.py in the following way
#user_passes_test(lambda u: u.is_superuser)
def add(request):
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
new_user = User.objects.create_user(form.cleaned_data['username'], form.cleaned_data['email'], form.cleaned_data['password'])
new_user.save()
messages.success(request, "User '%s' created" % new_user.username)
return HttpResponseRedirect('/user')
else:
form = UserForm()
return render(request, 'user/add.html', {"form": form})
#user_passes_test(lambda u: u.is_superuser)
def edit(request, id):
user = User.objects.get(id=id)
if request.method == 'POST':
f = UserForm(request.POST, instance=user)
if f.is_valid():
f.save()
messages.success(request, "User '%s' altered" % user.username)
return HttpResponseRedirect('/user')
else:
form = UserForm(instance=user)
return render(request, 'user/edit.html', {"form": form, "user": user})
Thanks for the answer.
Michal
This is what I would do:
class UserForm(ModelForm):
def __init__(self, *args, **kwargs):
is_edit = kwargs.get('is_edit', False)
if 'is_edit' in kwargs:
del kwargs['is_edit']
super(UserForm, self).__init__(*args, **kwargs)
if is_edit:
self.fields['password'].required = False
Then, in your edit() function:
f = UserForm(request.POST, instance=user, is_edit=True)
I use this type of thing fairly regularly in our codebase.