My Django site sends out an email confirmation link, and everything seems to work fine on desktop. On mobile devices, however, the link text is highlighted blue and underlined (i.e. it looks like a link) but nothing happens when the user clicks it. It should open a browser tab and say, "you have confirmed your email, etc"
Thanks for any tips!
views.py:
def signup(request):
if request.method == 'POST':
#send signup form
email_address = request.POST['email']
if request.POST['password1'] == request.POST['password2']:
try:
user = User.objects.get(email=email_address)
return render(request, 'accounts/signup.html', {'error': "Email already in use."})
except User.DoesNotExist:
user = User.objects.create_user(request.POST['email'], password=request.POST['password1'])
#auth.login(request, user)
#send email confirmation link then redirect:
#user = User.objects.get(email=email_address)
current_site = get_current_site(request)
mail_subject = 'Welcome to My Site'
plain_msg = 'Thank you for signing up to My Site! Click this link to activate your account:\n\n'+current_site.domain+'/accounts/activated/'+urlsafe_base64_encode(force_bytes(user.pk)).decode()+'/'+account_activation_token.make_token(user)+'/'
msg = '<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>title</title></head><body>Confirm your email address to continue:<br/>Confirm my email address</body></html>'
print(msg)
send_mail(mail_subject, plain_msg, 'my_email#gmail.com', [email_address], html_message=msg)
return render(request, 'accounts/activation-link-sent.html', {'email': email_address})
#truncated for Stack Overflow post
You should use build_absolute_uri to create fully qualified links that include the current domain and protocol, then use this link in your email
link = request.build_absolute_uri('/accounts/activated/'+urlsafe_base64_encode(force_bytes(user.pk)).decode()+'/'+account_activation_token.make_token(user)+'/')
Do you have a url pattern that matches this URL? You should consider using reverse for building URLs
path = reverse('activate', kwargs={
'pk': user.pk,
'token': account_activation_token.make_token(user)
})
link = request.build_absolute_uri(path)
Related
I am trying to respond to the ajax when it successfully gets login but on the other hand, I want to check based on what user profile, it will redirect to the profile.
Following is my function in views.py
#csrf_exempt
def login_view(request):
next = request.GET.get('next')
email = request.POST.get("email")
password = request.POST.get("password")
user = authenticate(username=email, password=password)
if user is not None and user.is_active:
login(request,user)
if user.is_male:
return redirect('/male_profile')
elif user.is_female:
return redirect('/female_profile')
elif user.is_other:
return redirect('/other_profile')
data_json = {"error" : False, "errorMessage" : "Login Successful!"}
return JsonResponse(data_json, safe=False)
else:
data_json={"error":True,"errorMessage":"Username or password is incorrect!"}
return JsonResponse(data_json,safe=False)
What the problem I am facing is it only returns Ajax response or redirects to a user-based profile.. but not both together. Can anyone please help me out with how can I first send the response to ajax and then I redirect it to another page in views.py based on the user profile?
Thanks.
here you are returning JSON response so you cant redirect but this can be done as follow:
#csrf_exempt
def login_view(request):
next = request.GET.get('next')
email = request.POST.get("email")
password = request.POST.get("password")
user = authenticate(username=email, password=password)
if user is not None and user.is_active:
login(request,user)
if user.is_male:
redirect = 'male_profile'
elif user.is_female:
redirect = 'female_profile'
elif user.is_other:
redirect = 'other_profile'
data_json = {"error" : False, "errorMessage" : "Login Successful!",
"redirect": redirect}
return JsonResponse(data_json, safe=False)
else:
data_json={"error":True,"errorMessage":"Username or password is incorrect!"}
return JsonResponse(data_json,safe=False)
in HTML (on client side) on response, success check redirect key in response and
make redirect
in response success condition add
if (response.redirect){
location.href = response.redirect;
}
I am implementing a basic web scraping webapp that requires registration and login to use the features. I am now facing an issue in the login [see below the code, please] when trying to decrypt a pwd from the mongodb database. I cannot pass the correct value in the sha512_crypt function, resulting in errors such as: '''ValueError: not a valid sha512_crypt hash'''
I have extensively researched the problem and tried multiple things, but still issues: What can you suggest? Thanks
#route for the signin page
#app.route("/signin", methods = ['GET', "POST"])
def signin():
form = Signin(request.form)
if request.method == 'GET': # make sure the method used is define above
return render_template('signin.html', form = form), print("you are under the signin page now, well done mrbacco")
if request.method == 'POST' and form.validate():
# the following are the data from the init form
email = form.email.data
password_form = form.password.data
print("these are the email and password inserted", email, password_form)
user_db = mycol_u.find_one({'email' : email})
for key, value in user_db.items():
print ("these are the fields in the db ", key, value)
if user_db is None:
flash("No USER FOUND!!, please try again", "danger")
return render_template('signin.html', form = form), print("user not found, flashed a message on the web page")
if sha512_crypt.verify(user_db['password'], password_form):
flash("You are now logged in", "success")
return redirect(url_for("home.html",form = form))
else:
flash("credential not correct, please try again", "danger")
print("redirecting to scraping page")
return render_template('signin.html', form = form)
I'm searching for solution to this problem for many hours but can't find anything related. I want to get user's email from input and send mail from admin to that email address. Here are my codes:
views.py:
def index(request):
context = {
'questions': Question.objects.all(),
'applicants': Applicant.objects.filter(status=1),
'empty_cards': range(4 - Applicant.objects.filter(status=1).count())
}
if request.method == "POST":
if request.POST.get('message_text'):
Message.objects.create(
sender_name = request.POST.get('sender_name'),
sender_email = request.POST.get('sender_email'),
message_text = request.POST.get('message_text'))
if request.method == 'POST':
subject = 'Welcome !'
message = 'We will back to you.'
from_email = settings.EMAIL_HOST_USER
recipient_list = 'don't know how to get email'
send_mail(subject, message, from_email, recipient_list)
return render(request, 'index.html', context)
from your code I assume that you already have access to the user's mail
inside the request.
so you can try this:
sender_email = sender_request.POST.get('sender_email')
recipient_list = [sender_email]
I've got a simple website for a Screenprinting company built using Django 1.10 and Python 3.5.2, but I am having issues with my "Get a Quote" page.
The idea is a user can go to www.example.com/quote/ and they are presented with a form. Here they put in their Name, Email Address, a Brief Message, and most importantly they can upload an image.
When they click submit, this data gets sent to my email address as an email using the EmailMessage method. I have set up a simple email form plenty of times in the past so I know my settings.py file is fine.
Here is my forms.py:
class QuoteForm(forms.Form):
name = forms.CharField(required=True)
from_email = forms.EmailField(required=True)
subject = "Quote"
uploaded_image = forms.ImageField()
message = forms.CharField(widget=forms.Textarea)
Here is my views.py:
def quote(request):
form = QuoteForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
from_email = form.cleaned_data['from_email']
message = form.cleaned_data['message']
message = "From: " + name + "\n" + "Return Email: " + from_email + "\n" + "Subject: " + subject + "\n" + "Message: " + message
uploaded_image = form.cleaned_data['uploaded_image']
msg = EmailMessage(subject, message, from_email, ['example#email.com'], reply_to=[from_email])
msg.attach_file(uploaded_image)
try:
msg.send()
except BadHeaderError:
return HttpResponse('Invalid header found')
return HttpResponseRedirect('thankyou')
return render(request, "quote.html", {'form': form})
When I test this on 127.0.0.1 I click submit and the form refreshes with the same info, except the image is no longer there.
Also, When I test it using the console.EmailBackend there are no errors. In fact, clicking submit doesn't seem to have any effect other than it reloads a few css files.
Any ideas?
A file is not in the request.POST attribute, it is in request.FILES. Your views.py should look like this:
def quote(request):
form = QuoteForm(request.POST, request.FILES)
if form.is_valid():
...
uploaded_image = request.FILES.getlist('uploaded_image')
...
Please note that this is a raw draft. I haven't tested it. Also note that you might have to sanitize the file for your own safety. For example: checking on the maximum filesize and contenttype.
More information about all of this: https://docs.djangoproject.com/en/1.10/topics/http/file-uploads/
My problem in the short version:
I have added the login_required decorator to one of my views. If I enter the URL in the browser which executes this view, the browser correctly redirects to the URL that contains my login form if the user is not authenticated. However, the browser never redirects back to the previous page and I have no idea why this does not work. I have tried hundreds of things.
My problem in the long version:
I have a Django project with a single app, let's call it my_app. All the templates of my project reside in templates/my_app/. I have a template called main.html which contains several forms, among them my login form. With an additional POST parameter called form-type, I check which of the forms has been submitted. The code looks like this:
def process_main_page_forms(request):
if request.method == 'POST':
if request.POST['form-type'] == u'login-form':
template_context = _log_user_in(request)
elif request.POST['form-type'] == u'registration-form':
template_context = _register_user(request)
elif request.POST['form-type'] == u'password-recovery-form':
template_context = _recover_password(request)
else:
template_context = {
'auth_form': AuthenticationForm(),
'registration_form': RegistrationForm(),
'password_recovery_form': EmailBaseForm()
}
return render(request, 'my_app/main.html', template_context)
The function _log_user_in() looks like this:
def _log_user_in(request):
message = ''
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
else:
message = 'Your account has been disabled. ' \
'Please contact the administrator.'
else:
message = 'Your username and password didn\'t match. Please try again.'
template_context = {
'auth_form': AuthenticationForm(),
'registration_form': RegistrationForm(),
'password_recovery_form': EmailBaseForm(),
'message': message,
}
return template_context
I also include the necessary <input> elements in the template, e.g. for the login form this is:
<input type="hidden" name="form-type" value="login-form" />
<input type="hidden" name="next" value="{{ next }}" />
The URL pattern for this view is:
url(r'^$', process_main_page_forms, name='main-page')
My second view renders two forms for changing email address and password for an authenticated user. It looks like this:
#login_required(login_url='/')
def change_user_credentials(request):
if request.method == 'POST':
if request.POST['form-type'] == u'change-email-form':
template_context = _change_email_address(request)
elif request.POST['form-type'] == u'change-password-form':
template_context = _change_password(request)
else:
template_context = {'change_email_form': ChangeEmailForm()}
return render(request, 'my_app/user.html', template_context)
The URL pattern for this second view is:
url(r'^account/$', change_user_credentials, name='user-page')
Whenever I access /account/ when I'm not authenticated, I'm successfully redirected to the main page that contains the login form. The resulting URL is http://127.0.0.1:8000/?next=/account/ that contains the necessary next parameter. However, when I log in my account, I'm still on the main page. I never get redirected to the user page, although I provided the necessary next parameter in the login form. It seems that this parameter is always empty, but I don't know why. I also don't have any other redirection calls in my code.
Can you help me solving this problem? Thank you very much in advance.
Possibly a trite answer, but the reason that no redirect is happening is because you don't seem to be doing anything with the next query parameter.
In fact, in the event that a user logs in successfully, you show the same page (albeit with a different context dictionary) as if they attempted to do something else:
def process_main_page_forms(request):
if request.method == 'POST':
if request.POST['form-type'] == u'login-form':
template_context = _log_user_in(request)
...
...
return render(request, 'my_app/main.html', template_context)
As the Django docs explain, it's the contrib.auth.views.login() function that processes the next parameter, and you're not using that view (although you are using the confusingly-identically-named contrib.auth.login function).
You should either just use the included view (which, in addition to processing next, also checks for is_active), or add the redirect functionality to your view, in which case it's probably worth bringing the authentication code into process_main_page_forms() unless you're sure you'll need _log_user_in() elsewhere:
from django.http import HttpResponseRedirect
from django.conf import settings
def process_main_page_forms(request):
if request.method == 'POST':
if request.POST['form-type'] == u'login-form':
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
if request.GET.get('next', False):
return HttpResponseRedirect(request.GET.get('next'))
else:
return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
else:
message = 'Your account has been disabled.'
else:
message = 'Your username and password didn\'t match. Please try again.'
# If we've reached this point then the login failed
template_context = {
'auth_form': AuthenticationForm(),
'registration_form': RegistrationForm(),
'password_recovery_form': EmailBaseForm(),
'message': message,
}
elif ...:
# Do things with other form types
else:
return render(request, 'my_app/main.html', template_context)
The example usage of contrib.auth.login has the following:
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
# Redirect to a success page.
else:
# Return a 'disabled account' error message
else:
# Return an 'invalid login' error message.
Your code is almost there, but you were missing the "redirect to a success page" part, which is where next would come into play.