Killer Web Development

by Marco Laspe

7.3 Showing Profile Pages

We are now able to register users. What we still need: a way to display them. If we look at our sketch we can easily extract the elements we need to display:

  1. the profile image
  2. the nickname of the users
  3. the Name of the user

You probably guessed it, we need to write a user test for it. Create a file test_profile.py in put the following code in there:

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
import os
from os import path

from functional_tests import FunctionalTest, ROOT
from dal import DAL

class TestProfile (FunctionalTest):

def setUp(self):
path_to_database = path.join(path.curdir, "databases")
self.db = DAL('sqlite://storage.sqlite', folder=path_to_database)
self.db.import_table_definitions(path_to_database)

# Create User John
self.create_user()
self.login()

# He now goes to his profile page
self.url = ROOT + '/tukker/default/profile'
get_browser=self.browser.get(self.url)


def test_can_view_profile(self):
# Let's check if the website was loaded ok => response code == 200
response_code = self.get_response_code(self.url)
self.assertEqual(response_code, 200)

def test_has_right_title(self):
# First he looks at the topbar and sees 'John's Profile'
title = self.browser.find_element_by_tag_name('title')
self.assertEqual("john's Profile", title.text)

def test_has_page_the_needed_elements(self):
# John looks at his profile page and sees his personal data
name = self.browser.find_element_by_id("profile-name")
self.assertEqual(name.text, "John Tukker")

nickname = self.browser.find_element_by_id("nickname")
self.assertEqual(nickname.text, "john")

image = self.browser.find_element_by_id("profile-image")
self.assertIn("auth_user.image", image.get_attribute("src"))# TODO Assertion

def tearDown(self):

# John logs out if any session are still open
self.url = ROOT + '/tukker/default/user/logout'
get_browser=self.browser.get(self.url)

# We need clean up our database, otherwise the tests will fail
# in the future
self.db.auth_user.truncate() # This resets the whole database table.
self.db.commit()

# Delete all files from the uploads directory
dirPath = path.join(path.curdir, "uploads")
fileList = os.listdir(dirPath)
for fileName in fileList:
os.remove(dirPath+"/"+fileName)

def create_user(self):

# John opens his browser and goes to the home-page of the tukker app
self.url = ROOT + '/tukker/user/register'
get_browser=self.browser.get(self.url)

# John fills in the form with his personal data
first_name = self.browser.find_element_by_name("first_name")
first_name.send_keys("John")

last_name = self.browser.find_element_by_name("last_name")
last_name.send_keys("Tukker")

email = self.browser.find_element_by_name("email")
email.send_keys("john@tukker.me")

password = self.browser.find_element_by_name("password")
password.send_keys("pass")

verify_password = self.browser.find_element_by_name("password_two")
verify_password.send_keys("pass")

nickname = self.browser.find_element_by_name("nickname")
nickname.send_keys("john")

image = self.browser.find_element_by_id("auth_user_image")
path_to_image = path.abspath(path.join(path.curdir, "fts/test_image.png"))
image.send_keys(path_to_image)

# John klicks on the register button
register_button = self.browser.find_element_by_css_selector("#submit_record__row input")
register_button.click()

# We need to logout after logging in
self.url = ROOT + '/tukker/default/user/logout'
get_browser=self.browser.get(self.url)

def login(self):
# John opens his browser, logs out if any session are still open
self.url = ROOT + '/tukker/default/user/logout'
get_browser=self.browser.get(self.url)

# John goes to the login-page of the tukker app
self.url = ROOT + '/tukker/default/user/login'
get_browser=self.browser.get(self.url)
#John enters his email address
user_email = self.browser.find_element_by_id("auth_user_email")
user_email.send_keys("john@tukker.me")

# John enters his password
user_password = self.browser.find_element_by_id("auth_user_password")
user_password.send_keys("pass")

# He clicks the submit button
submit_button = self.browser.find_element_by_css_selector("#submit_record__row input")
submit_button.click()

By now you should understand how this code works and what these tests do. It creates new test users via the registration form and then checks if the profile page of John contains the elements we exspect.

Now let's come to the interesting part: We show the profile page of the user. We need to create a new function in the default.py controller file:

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
def profile():
nickname = request.args[0]

response.title = nickname + "'s Profile"

result = db(db.auth_user.nickname == nickname).select()[0]

name = result.first_name + " " + result.last_name
image = result.image

return dict(nickname=nickname, name=name, image=image)

This function has a some new code, so let's walk it through line by line :

1.
nickname = request.args[0]

We assign the request.args[0] (Remember in the part after the controller function?) to a variable we name nickname. We do this to make the code more readable? Then we create the title for the profile page :

1.
response.title = nickname + "'s Profile"

we concencate to strings with the +-operator, beware that the +-operator works differently on strings than it does on numbers. :

1.
result = db(db.auth_user.nickname == nickname).select()[0]

We use web2py's db() method to retrieve all entries from the database table auther_userwhich attribute nickname has the same value as the variable nickname we assigned before. 'Cause nicknames must be unique there should be only one entry in the return list. We assign this one (or first) entry of the results list to the variable result (One thing: the return object from web2py db() function is not a Python list, but as with Python list's its entries can be selected with the [] operator).

Finally we assign the name and the image of the result to the variables name and image and return the variable in a Python dictionary to the corresponding view.

Now we need to create a corresponding view in the views directory views/default/profile.py:

1.
2.
3.
4.
5.
6.
7.
8.
9.
{{extend 'layout.html'}}

<div class="four columns alpha">
<img id="profile-image" width="100%" src="{{=URL('download',args=image)}}" />
</div>
<div class="twelve columns omega">
<h2 id="nickname">{{=nickname}}</h2>
<p id="name">{{=name}}</p>
</div>

This is just a simple snippet of HTML where we insert the variables from the profile function - similar how we did it with the index.html view.

Now let's see if our tests pass. If everything passes, we can commit the code to the repository :

1.
hg commit -m"Profile page"

If you register a user you could see a profile similar to that:

web2py profile


Books often read by web2py and Python experts:

Comments

Leave a Reply

Required fields are marked *.