Code Tutorial: Making a page that lists all the users

From Dreamwidth Notes
Jump to: navigation, search

First, start out from the develop branch and make a new branch for this feature:

git checkout develop
git branch feature/Listusers
git checkout feature/Listusers

Your git status will now say what branch you are on and that no changes exist to commit:

[email protected]:~/dw$ git status
# On branch feature/Listusers
nothing to commit (working directory clean)

First step: serve a blank page

Then, create blank pages for your templates: listusers.tt and listusers.tt.text. These files go into the views directory.

cd views
touch listusers.tt
touch listusers.tt.text

After this, you should see these untracked files pop up in your git status:

[email protected]:~/dw/views$ git status
# On branch feature/Listusers
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       listusers.tt
#       listusers.tt.text
nothing added to commit but untracked files present (use "git add" to track)

The controller goes into cgi-bin/DW/Controller/ListUsers.pm

#!/usr/bin/perl
#
# DW::Controller::ListUsers
#
# This controller lists all the users on the service.
#
# Authors:
#      foxfirefey <[email protected]>
#
# Copyright (c) 2009 by Dreamwidth Studios, LLC.
#
# This program is free software; you may redistribute it and/or modify it under
# the same terms as Perl itself. For a copy of the license, please reference
# 'perldoc perlartistic' or 'perldoc perlgpl'.
#
 
package DW::Controller::ListUsers;
 
use strict;
use warnings;
use DW::Controller;
use DW::Routing;
use DW::Template;
 
DW::Routing->register_string( '/listusers', \&index_handler, app => 1 );
 
# Lists all users on the service
sub index_handler {
 
    my $vars = {};
 
    return DW::Template->render_template( 'listusers.tt', $vars );
}
 
1;

Also go and add a title to the page to the text file for the template, and a title using that translation string into the template.

[email protected]:~/dw$ cat views/listusers.tt.text
;; -*- coding: utf-8 -*-
.title=User List
[email protected]:~/dw$ cat views/listusers.tt
<h2>[% '.title' | ml %]</h2>

Once you do this, run database updates to make sure the text from the file is loaded into the database, and restart the server. The page should show up displaying the title at the address:

http://www.memewidth.homeip.net/listusers

This is enough for your first commit to git. You current status has all the files:

[email protected]:~/dw$ git status
# On branch feature/Listusers
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       cgi-bin/DW/Controller/ListUsers.pm
#       views/listusers.tt
#       views/listusers.tt.text

Add the files:

git add cgi-bin/DW/Controller/ListUsers.pm views/listusers.tt views/listusers.tt.text

Then your status:

[email protected]:~/dw$ git status
# On branch feature/Listusers
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   cgi-bin/DW/Controller/ListUsers.pm
#       new file:   views/listusers.tt
#       new file:   views/listusers.tt.text
#

To review everything that will be committed:

git diff --cached

Then you can make the commit of the changes so far:

[email protected]:~/dw$ git commit -m "Initial creation of files--basic controller that returns a template with a title"
[feature/Listusers 4e4121b] Initial creation of files--basic controller that returns a template with a title
  3 files changed, 40 insertions(+), 0 deletions(-)
  create mode 100644 cgi-bin/DW/Controller/ListUsers.pm
  create mode 100644 views/listusers.tt
  create mode 100644 views/listusers.tt.text

Getting the users from the database

Exploring the database can be started out by invoking the ljdb command that will put you into a MySQL prompt:

$LJHOME/bin/ljdb 

Some example things you can do are...

Show all the tables in the database:

show tables; 

Show all of the columns from the user table:

show columns from user;

Count the number of lines in the user table:

select COUNT(*) from user;

Select all of the columns of all of the rows in the user table:

select * from user;

The selection command in SQL to get all the user IDs is:

SELECT userid FROM user;
  • Need to get a database handle--usually named "$dbh" in the code.
  • Need to construct a database query to get the userids from the user table in the database.
  • Need to load the list of userids.
  • Need to pass the loaded user objects into the template. Pass it in as "users".
#!/usr/bin/perl
#
# DW::Controller::ListUsers
#
# This controller is for navigation handlers.
#
# Authors:
#      foxfirefey <[email protected]>
#
# Copyright (c) 2009 by Dreamwidth Studios, LLC.
#
# This program is free software; you may redistribute it and/or modify it under
# the same terms as Perl itself. For a copy of the license, please reference
# 'perldoc perlartistic' or 'perldoc perlgpl'.
#
 
package DW::Controller::ListUsers;
 
use strict;
use warnings;
use DW::Controller;
use DW::Routing;
use DW::Template;
 
DW::Routing->register_string( '/listusers', \&index_handler, app => 1 );
 
# Lists all users on the service
sub index_handler {
 
    my $dbh = LJ::get_db_reader();    
    my $userids = $dbh->selectcol_arrayref( "SELECT userid FROM user;" );    
    my $users = LJ::load_userids(@$userids);
 
    my $vars = {
        users => $users,
    };
 
    return DW::Template->render_template( 'listusers.tt', $vars );
}
 
1;

In order to explore what is actually in the users variable, you can use data dumper.

[% USE Dumper %]
[% Dumper.dump_html(users) %]

The first bit of the dump looks something like:

$VAR1 = {
'1' => bless( {
'bdate' => '0000-00-00',
'clusterid' => '1',
'journaltype' => 'P',
'caps' => '192',
'opt_htmlemail' => 'Y',
'email' => '[email protected]',
'password' => undef,
'allow_getljnews' => 'N',
'user' => 'system',
'statusvis' => 'V',
'lang' => 'EN',
'allow_infoshow' => ,
'is_system' => 'N',
'has_bio' => 'N',
'name' => 'My name is 0.412015924783297',
'moodthemeid' => '7',
'opt_gettalkemail' => 'Y',
'statusvisdate' => undef,
'opt_showtalklinks' => 'Y',
'useoverrides' => 'N',
'txtmsg_status' => 'none',
'userid' => '1',
'status' => 'A',
'themeid' => '1',
'_orig_user' => 'system',
'opt_forcemoodtheme' => 'N',
'opt_mangleemail' => 'Y',
'defaultpicid' => '11',
'oldenc' => '0',
'dversion' => '9',
'allow_contactshow' => 'Y',
'_orig_userid' => '1',
'opt_whocanreply' => 'reg'
}, 'LJ::User' ),
...

The { and => both indicate a hash. The '1' is the first value, the bless item is a User object--indicated by the 'LJ::User' at the end. This means you will need to look at the Template Toolkit hash virtual methods to work with it in the template.

For instance, one way would be to use the pairs method and the method to display a username:

<h2>[% '.title' | ml %]</h2>

<ul>
[% FOR u IN users.pairs %]
<li>[% u.value.ljuser_display %]</li>
[% END %]
</ul>

One last tweak and commit

We can also change the way we do the title to the proper way, so that it shows in the browser title bar, by using the title section of the site scheme:

[% sections.title = '.title' | ml %]

Now, commit all the work done so far!

git commit -m "Add the list of users to the page"

Other Exercises

  • Turn the list into alphabetical order by username
  • Turn the simple list into an informative table; you can glean information from the data dump of the users variable or from user class functions.
  • Split the list up by journal types
  • Add in pagination, by # of accounts or by letter the account starts with