As an extension of the previous Part VIII, we’re going to take a look at the user authentication using Twitter.
If you didn’t follow this tutorial from the beginning, I recommend that at least, you take a look at the previous Part VIII, as I will skip some steps that are commented there.
The outline of this part is:
Let’s start! đ
Test First! Test First!
Edit the funcitonal_tests/test_allauth.py file and add the following test for Twitter:
class TestTwitterLogin(StaticLiveServerTestCase): fixtures = ['allauth_fixture'] def setUp(self): self.browser = webdriver.Firefox() self.browser.implicitly_wait(3) self.browser.wait = WebDriverWait(self.browser, 10) activate('en') def tearDown(self): self.browser.quit() def get_element_by_id(self, element_id): return self.browser.wait.until(EC.presence_of_element_located( (By.ID, element_id))) def get_button_by_id(self, element_id): return self.browser.wait.until(EC.element_to_be_clickable( (By.ID, element_id))) def user_login(self): import json with open("taskbuster/fixtures/twitter_user.json") as f: credentials = json.loads(f.read()) for key, value in credentials.items(): self.get_element_by_id(key).send_keys(value) for btn in ["allow"]: self.get_button_by_id(btn).click() return def get_full_url(self, namespace): return self.live_server_url + reverse(namespace) def test_twitter_login(self): self.browser.get(self.get_full_url("home")) twitter_login = self.get_element_by_id("twitter_login") with self.assertRaises(TimeoutException): self.get_element_by_id("logout") self.assertEqual( twitter_login.get_attribute("href"), self.live_server_url + "/accounts/twitter/login") twitter_login.click() self.user_login() with self.assertRaises(TimeoutException): self.get_element_by_id("twitter_login") logout = self.get_element_by_id("logout") logout.click() twitter_login = self.get_element_by_id("twitter_login")
And run it with
$ python manage.py test functional_tests.test_allauth.TestTwitterLogin
which of course… will fail.
Configure Allauth
In order to log in a user with a Twitter account we need to add the following app in settings.py:
INSTALLED_APPS = ( ... 'allauth.socialaccount.providers.twitter', ... )
And migrate our database:
$ python manage.py check $ python manage.py makemigrations $ python manage.py migrate
And finally, we are going to add a button in the base.html template (like we did with Google). This button will be used by the user to login with Twitter:
<div class="navbar-collapse collapse"> <div class="navbar-form navbar-right"> {% if user.is_authenticated %} <a id="logout" href="/accounts/logout" class="btn btn-success">Logout</a> {% else %} <a id="google_login" href="/accounts/google/login" class="btn btn-success">Sign in with Google</a> <a id="twitter_login" href="/accounts/twitter/login" class="btn btn-success">Sign in with Twitter</a> {% endif %} </div> </div><!--/.navbar-collapse -->
However, we don’t have a Twitter application yet! Let’s change that! đ
Create a Twitter Application
Create a new Twitter Application from here with:
- Website:Â http://127.0.0.1:8000 (twitter doesn’t allow localhost as an url)
- Callback Url:Â http://127.0.0.1:8000/accounts/twitter/login/callback/
Change this domain by your domain name in production, if applicable.
Next, create an Allauth social application in http://127.0.0.1:8000/admin/socialaccount/socialapp/add/ with
- Provider: Twitter
- Name: Twitter (or something similar)
- Client ID: Your Twitter app Consumer Key (API Key)
- Secret Key: Your Twitter app Consumer Secret (API Secret)
- Sites: Select the corresponding site
Both Consumer Key and Secret will be found in the Keys and Access Tokens tab.
Note: As we’ve seen with Google, Django tests run in another domain: 127.0.0.1:8081. Therefore, you’ll have to repeat this process an create another app for testing (Twitter doesn’t allow multiple urls in the same app).
Now it’s time to create the fixtures to use in the database. In settings/testing.py, select a dummy database:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
This will allow us to create fixtures from this testing database anytime we want to.
Activate your testing environment (to use this settings file) and configure the database:
$ workon tb_test $ python manage.py migrate $ python manage.py createsuperuser $ python manage.py runserver 127.0.0.1:8081
Modify the name of the default site to 127.0.0.1:8081 here. And create the corresponding social applications here (Google and Twitter for this tutorial).
Stop the server and create the fixture with:
$ python manage.py dumpdata --indent 2 --natural-foreign -e contenttypes -e auth.Permission > taskbuster/fixtures/allauth_fixture.json
To simulate the login of a user, we’ll write the user credentials in the file fixtures/twitter_user.json as:
{"username_or_email": "user@email.com", "password": "userpassword"}
where you should use valid credentials. Remember to include the fixtures folder in the .gitignore file, as it contains sensible data.
Finally, run your tests again!
$ python manage.py test functional_tests.test_allauth
Yes! They worked! đ
I also wanted to use Facebook, but they banned me đ I don’t know why I can’t sign up as a developer!
Now you’re ready to continue to next part! Model creation, OneToOne relations, signals and the Django Admin.
Please, +1 and share if useful! Thanks!! đ