I want a logged in user to be able to send a copy of the model object they created that has been saved in the database. Am using the get(pk=id) to recognize the particular one the user wants to send. The problem is, the send_mail() doesn't recognize the recipient email (to).
#login_required
def email_query(request, id):
history = Carloan_form.objects.get(pk=id)
subject = 'Nigerian Loan Calculator Query e-mail'
from_email = 'xxxx#gmail.com'
email = request.user.email
to = "email"
send_mail(subject,get_template('carloan/loancalc-query.txt').render(Context({'history':history})),\
from_email,[to], fail_silently=False)
return HttpResponse('sent')
Update
#login_required
def email_query(request, id):
history = Carloan_form.objects.get(pk=id)
subject = 'Nigerian Loan Calculator Query e-mail'
from_email = 'ajibike.ca#gmail.com'
email = request.user.email
send_mail(subject,get_template('carloan/loancalc-query.txt').render(Context({'history':history})),\
from_email,[email,], fail_silently=False)
return HttpResponse('/history_query_sent/')
Just decided to pass the email straight into the send_mail() and it worked. Thanks
Because you've set to to the string "email". I doubt that is what you wanted to do.
Why not pass the email variable directly into the send_mail call?
Related
I'm making a small solution to restore user credentials. I decided to try to do it with my algorithm. I request the user's mail and compare it with the database of postal addresses. If the mail exists, I want to send the user his credentials (login and password). I have already done the acceptance and verification of mail, as well as configured the sending of emails to postal addresses. But how to get access to credentials with only mail and the fact that the user is not logged in, I do not understand. I know that maybe my solution based on security is not very good, but there was interest and I really want to understand how to do it.
It may be possible to make a quick login and get data from there, or it can do without it? As a result, I have to send the used as a message to views.py this data.
views.py
def recovery(request):
if request.user.is_authenticated:
return redirect("/accounts/exit/")
else:
if request.method == 'POST':
email_form = UserRecoveryForm(request.POST)
if email_form.is_valid():
email = email_form.cleaned_data['email']
try:
send_mail("Восстановление учетных данных.", "message", "from#gmail.com", [email], fail_silently=False)
except BadHeaderError:
return HttpResponse('Ошибка в теме письма.')
return render(request, 'registration/recovery_done.html')
else:
email_form = UserRecoveryForm()
return render(request, 'registration/recovery.html', {'email_form': email_form})
Just in case forms.py
class UserRecoveryForm(forms.ModelForm):
email = forms.EmailField(label='Почта', help_text='На почту мы отправим дополнительную информация в случае необходимости')
class Meta:
model = User
fields = ('email',)
def clean_email(self):
email = self.cleaned_data.get('email')
username = self.cleaned_data.get('username')
if (not(email and User.objects.filter(email=email).exclude(username=username).exists())):
raise forms.ValidationError('Такой почты не существует.')
return email
I'm new to django. I'm trying to create a sports betting game as my first django app.
I have form, using which I'm able to save home goals and away goals for particular game to database, but I can't find a way to insert a username there. Hope you can help!
Here is my view:
#login_required
def group_games(request, groupname):
games = Match.objects.filter(groupname=groupname)
template = loader.get_template('C:\djangoenvs\\typer\\typer\\templates\group_games.html')
username = User.get_username()
for game in games:
game_id = get_object_or_404(Match, pk=game)
form = BetForm(request.POST or None)
if form.is_valid():
print ('valid form')
form.save()
else:
print ('invalid form')
print (BetForm.errors)
context = {
'games': games,
'groupname': groupname,
'form': form,
}
User.get_username() raises the following error:
get_username() missing 1 required positional argument: 'self'
I tried to change it to User.get_username(self) but then:
name 'self' is not defined
Thanks for every answer!
User.get_username()
User represents the complete table, not the record. This is why you get an error.
So remove:
username = User.get_username()
A user might be able to change their username in your application, you can save a foreign key to the user instead. When you save the form do this:
if form.is_valid():
print ('valid form')
bet = form.save(commit=False) # the bet isn't saved just yet
bet.user = request.user # you add the user here
print bet.user.username
bet.save() # finally save the bet in the database
In your Bet model, you need to add a field to record the user. For example:
class Bet(models.Model):
...
user = models.ForeignKey(to=User, related_name="bets", blank=True, null=True)
...
I am looking to add email account verification in Django. I have attempted using the django-registration app to do so, but it doesn't appear that it has been updated to be fully compatible with custom user models which causes too many problems. Is there another reliable and well-documented app out there which will allow me to send a verification email on user registration in django?
How I handle the email registration personally:
First of all, my Profile extending Django Users (models.py):
class Profile(models.Model):
user = models.OneToOneField(User, related_name='profile') #1 to 1 link with Django User
activation_key = models.CharField(max_length=40)
key_expires = models.DateTimeField()
In forms.py, the Registration class :
class RegistrationForm(forms.Form):
username = forms.CharField(label="",widget=forms.TextInput(attrs={'placeholder': 'Nom d\'utilisateur','class':'form-control input-perso'}),max_length=30,min_length=3,validators=[isValidUsername, validators.validate_slug])
email = forms.EmailField(label="",widget=forms.EmailInput(attrs={'placeholder': 'Email','class':'form-control input-perso'}),max_length=100,error_messages={'invalid': ("Email invalide.")},validators=[isValidEmail])
password1 = forms.CharField(label="",max_length=50,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder': 'Mot de passe','class':'form-control input-perso'}))
password2 = forms.CharField(label="",max_length=50,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder': 'Confirmer mot de passe','class':'form-control input-perso'}))
#recaptcha = ReCaptchaField()
#Override clean method to check password match
def clean(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password1 != password2:
self._errors['password2'] = ErrorList([u"Le mot de passe ne correspond pas."])
return self.cleaned_data
#Override of save method for saving both User and Profile objects
def save(self, datas):
u = User.objects.create_user(datas['username'],
datas['email'],
datas['password1'])
u.is_active = False
u.save()
profile=Profile()
profile.user=u
profile.activation_key=datas['activation_key']
profile.key_expires=datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(days=2), "%Y-%m-%d %H:%M:%S")
profile.save()
return u
#Sending activation email ------>>>!! Warning : Domain name is hardcoded below !!<<<------
#The email is written in a text file (it contains templatetags which are populated by the method below)
def sendEmail(self, datas):
link="http://yourdomain.com/activate/"+datas['activation_key']
c=Context({'activation_link':link,'username':datas['username']})
f = open(MEDIA_ROOT+datas['email_path'], 'r')
t = Template(f.read())
f.close()
message=t.render(c)
#print unicode(message).encode('utf8')
send_mail(datas['email_subject'], message, 'yourdomain <no-reply#yourdomain.com>', [datas['email']], fail_silently=False)
Now, in views.py, we need to handle all that, let's go :
The register view:
def register(request):
if request.user.is_authenticated():
return redirect(home)
registration_form = RegistrationForm()
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
datas={}
datas['username']=form.cleaned_data['username']
datas['email']=form.cleaned_data['email']
datas['password1']=form.cleaned_data['password1']
#We generate a random activation key
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
usernamesalt = datas['username']
if isinstance(usernamesalt, unicode):
usernamesalt = usernamesalt.encode('utf8')
datas['activation_key']= hashlib.sha1(salt+usernamesalt).hexdigest()
datas['email_path']="/ActivationEmail.txt"
datas['email_subject']="Activation de votre compte yourdomain"
form.sendEmail(datas)
form.save(datas) #Save the user and his profile
request.session['registered']=True #For display purposes
return redirect(home)
else:
registration_form = form #Display form with error messages (incorrect fields, etc)
return render(request, 'siteApp/register.html', locals())
The activation views :
#View called from activation email. Activate user if link didn't expire (48h default), or offer to
#send a second link if the first expired.
def activation(request, key):
activation_expired = False
already_active = False
profile = get_object_or_404(Profile, activation_key=key)
if profile.user.is_active == False:
if timezone.now() > profile.key_expires:
activation_expired = True #Display: offer the user to send a new activation link
id_user = profile.user.id
else: #Activation successful
profile.user.is_active = True
profile.user.save()
#If user is already active, simply display error message
else:
already_active = True #Display : error message
return render(request, 'siteApp/activation.html', locals())
def new_activation_link(request, user_id):
form = RegistrationForm()
datas={}
user = User.objects.get(id=user_id)
if user is not None and not user.is_active:
datas['username']=user.username
datas['email']=user.email
datas['email_path']="/ResendEmail.txt"
datas['email_subject']="Nouveau lien d'activation yourdomain"
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
usernamesalt = datas['username']
if isinstance(usernamesalt, unicode):
usernamesalt = usernamesalt.encode('utf8')
datas['activation_key']= hashlib.sha1(salt+usernamesalt).hexdigest()
profile = Profile.objects.get(user=user)
profile.activation_key = datas['activation_key']
profile.key_expires = datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(days=2), "%Y-%m-%d %H:%M:%S")
profile.save()
form.sendEmail(datas)
request.session['new_link']=True #Display: new link sent
return redirect(home)
Finally, in urls.py:
url(r'^register/$', 'register'),
url(r'^activate/(?P<key>.+)$', 'activation'),
url(r'^new-activation-link/(?P<user_id>\d+)/$', 'new_activation_link'),
With all that you should have something to start with, use the appropriate templatetags in the .txt emails and HTML and it should work.
NB: This code isn't perfect, there is duplication (for instance, the generation of the random key could be defined in a function), but it does the job. Also: the activation key is not generated using proper cryptographic functions. An alternative is to use a function like the following to generate the keys:
from django.utils.crypto import get_random_string
def generate_activation_key(username):
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!##$%^&*(-_=+)'
secret_key = get_random_string(20, chars)
return hashlib.sha256((secret_key + username).encode('utf-8')).hexdigest()
NB2: Django send_mail doesn't provide any tools to authenticate your emails. If you want to authenticate your emails (DKIM, SPF), I advise you to look into this: https://djangosnippets.org/snippets/1995/
NB3: There is a security issue with the view new_activation_link: it should check if the user requesting the re-send is the right one and also if he isn't already authenticated. I let you correct that.
You may also be interested in the simple but powerful django-verified-email-field.
Simply use VerifiedEmailField in Your forms:
from django import forms
from verified_email_field.forms import VerifiedEmailField
class RegistrationForm(forms.ModelForm):
email = VerifiedEmailField(label='email', required=True)
Or in Your models:
from django.db import models
from verified_email_field.models import VerifiedEmailField
class User(models.Model):
email = VerifiedEmailField('e-mail')
It renders two input fields: e-mail and verification code. The verification code is sent to the e-mail address using AJAX or during field's clean if there is no valid code for given e-mail, so it works even without javascript.
I have my models defined as:
class MyUser(AbstractUser):
created = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=256)
phone = models.IntegerField()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'name', 'phone']
MyUser._meta.get_field_by_name('email')[0]._unique=True
now when I am calling create_user by sending all the arguments in the form
my view.py looks like
def new_user(request):
email = request.POST.get('email','')
phone = request.POST.get('phone','')
name = request.POST.get('name','')
password = request.POST.get('password','')
confirm_pass = request.POST.get('confirm_password','')
if password and confirm_pass and password == confirm_pass:
try:
user = MyUser.objects.get(email=email)
except MyUser.DoesNotExist:
user = None
if user:
message = 'User with the following email id already exists'
return render(request, 'signup.html', {'message':message})
else:
user = My.objects.create_user(email, email, name, phone, password)
user.save()
login(request, user)
return render(request, 'details.html', {'username':request.user.username})
else:
message = 'Paaswords does not match each other'
return render(request, 'signup.html', {'message':message})
Now each time this function executes it shows me the following error
create_user() takes at most 4 arguments (6 given)
I could'nt understand why is create_user not working.
create_user function takes the parameters as *args, so you need to call the function like that:
create_user(email = email, name = name, phone = phone, password = password)
or easily pass your request.POST:
create_user(request.POST)
I'm seeing that your view is a little bit complex, have you ever try Class Based Views?
With class based views you can create method do deal with get querysets and form rendering.
That a look https://docs.djangoproject.com/en/dev/topics/class-based-views/
At last advice, you can create a register_form to deal with data validation:
https://docs.djangoproject.com/en/dev/topics/forms/
You're sending 6 arguments from your views.py where as you have only 4 required.
Note that password and confirm pass count as your 2 additional arguments. That's what I think anyway
Take a look at THIS example. It helped me with creating my abstract user.
If you'd like some code examples, HERE is a good breakdown (if you're on Django 1.5 that is)
I keep working with django and I was building a contact form.
I want to retrieve the information in the contact form, which I was able to do so far, but I am facing the problem that the user that fills in the form is also receiving an email with the information and MY email ( which I don't want ).
I am using the function EmailMultiAlternatives in my view, and have configured propertly my settings.py with the email account, and extra data needed for emails.
Can the information from a form be only received by me (administrator)?
Here is my view:
form = ContactForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
name = form.cleaned_data['name']
message = form.cleaned_data['message']
to = #my email
html_content = "received from [%s] ***message*** %s"%(email,message)
msg = EmailMultiAlternatives('Subject', html_content, 'from#server.com', [to])
msg.attach_alternative(html_content, 'text/html')
msg.send()