Here is a snippet for sending an attachment by email in Django:
from django.core.mail import EmailMessage
def send_mail_w_attachment(to, subject, message, attachment_path,
:param to: a list of email addresses
:param subject: a string
:param message: a string
:param attachment_path: full path to attachment fil
email = EmailMessage(subject, message, to=to)
# Load file and Base64 encode
file_name = os.path.basename(attachment_path)
data = open(attachment_path, 'rb').read()
encoded = base64.b64encode(data)
email.attach(file_name, encoded, mimetype=mimetype)
# Send it
I just started using Django-AllAuth. I chose it because it supports “normal” login as well as Oauth based login.
For “normal” login, I have switched to using email address as the username. In general, people do not like having to think up a username and they do not remember it. Email is already unique and easier to remember because the user uses it all the time.
AllAuth says it can do email based logins. But how? Turns out its just a setting:
ACCOUNT_AUTHENTICATION_METHOD = “email”
For at least a year we have known that Django 1.5 would contain functionality to significantly alter the User model. For years, I thought I wanted to get rid of the Django User.username field and have email be the username. A few versions back, Django changed the username to allow the char @, which made it possible to put an email address in the username. Not a bad hack. I just modified the save method to copy the email into the username field. Now with Django 1.5 we don’t have to do that. But maybe I still want to…
Many years ago, I first considered using the email address as a username. I was motivated by the number of users who hand trouble logging in. A surprising number forgot their username. Email as username seemed like a good way to solve that problem. Not everyone was on board with this change. One objection was that some people share email addresses, thus they could not have individual accounts on our system. I think that problem is so rare, its worth ignoring. The other objection was that if there is something like a discussion board or messaging on the website, some users will not want their email displayed. This seems like a reasonable objection. Maybe even more so today.
So now that I can get rid of the User.username, I am not going to. With the exception of over-riding some of the methods, I am going to stick with the default Django User model.Since I am just over-riding methods, I will use a proxy model of User. Here’s how it will work:
When a new user is created, if a username is not specified, email address will be copied into the username field on save. Although its not completely DRY, this process will be done in forms because username is still a required field. Update: as of Django 1.5 the username is limited to 30 chars. Its not uncommon for a email address to exceed 30 chars. Thus not all usernames can be set to the email address. Thus is does not make sense to make any usernames be email addresses. I think the solution to this is to set the username to a unique random string.
- Users can edit their username to be whatever they want (but it still must be unique)
- I am using a custom authentication backend that allows users to login with either their username or email address. For more info, check out this blog post.
I was also considering adding some new fields to the User model, but the Django documentation convinced me to put those fields in another model with User as a foreign key. The reason for this is that User is a foreign key in lots of models. If you mess up a migration of User, lots of things will break. By putting those fields in another model, adding or removing fields is much less likely to break everything. This is similar to the UserProfile functionality in previous versions of Django. That functionality is deprecated in Django 1.5. With Django 1.5, this mechanism is normalized to be like any other one-to-one relationship.