docassemble allows you to create multi-user interviews.
- In a legal application, a client uses the interview to answer questions about the facts of a case, and then an attorney reviews the responses, answers questions about how the law applies to the facts, and then the client comes back to the interview to receive a legal advice letter.
- If a user’s language is not English, a translator will be invited to join the interview to translate the user’s textual responses into English before the interview process is completed.
- Two parties who are negotiating with one another will fill in answers to an interview, and when both are done, the interview will suggest a resolution based on the answers of both parties.
Multi-user interviews are implemented through the user login feature and three features that were introduced in other sections:
rolemodifier: designates certain questions as being answerable only by a particular user (or group of users).
default roleinitial block: sets the
rolemodifier for questions that do not have a
roleexplicitly set. The
codewithin this block is run as
initialcode. The responsibility of this
codeis to set the special variable
roledepending on the circumstances, which can include the identity and privileges of the person logged in, which can be retrieved with the functions
eventvariables: when the current user cannot proceed further with the interview because the interview needs input from a different user, docassemble will display a message for the current user. It finds this message by looking for a question marked with
event: role_event. Mako template commands can be used in this question to say different things depending on who the current user is and who the new user needs to be.
The following example of a three-role interview demonstrates how multi-user interviews are created in docassemble.
The interview starts with an organizer, who clicks past an introductory screen and is asked for the e-mail addresses of two participants who will bid on a contract. The organizer is then asked to invite the participants to bid by clicking on a particular link and logging in. Once both bidders have entered their bids, the winner (the participant with the lowest bid) is announced. Until both participants have entered bids, users will see a page telling them to wait and to press the “Check” button to see if both bids have been made yet (except for bidders who haven’t bid yet, who will be asked for their bids).
Most of the code is self-explanatory, but a few of the blocks warrant explanation.
Consider the second block:
Here, we set the
default role to
organizer. This simply means that
questions in the interview that do not have a
role specified will
initial code, the primary purpose of which is to set
role variable, which is the role of whichever user is currently
in the interview. This code runs every single time the page loads for
This code block also sets the special variable
True, which tells docassemble that multiple
users will be using this interview. When
docassemble will not encrypt the answers on the server. This
reduces security somewhat, but is necessary in order for multiple
users to participate in the same interview.
First, note that the
role for all users will remain
until the organizer has seen the introductory page and the
participants have been invited.
Second, note that the flow of the interview is being controlled here.
The references to
participants invited mean
that questions will be asked to define those variables if they are
undefined. This is the code that causes those questions to appear for
the organizer. After the role is set, the
code block controls the flow of the interview.
Third, note that by requiring
participants invited to be set before
we consider whether the user’s e-mail address is equal to
first_person_email, we ensure that the interview flow proceeds the
way we want it to. Suppose we did not check for
invited before doing this. If the organizer was logged in and gave
his own e-mail address as that of a participant, he would assume the
role of a participant before learning the URL that he needs to give to
the other participant.
There are times when you just want docassemble to figure out the
interview flow implicitly, and there are times when you want to be
explicit about it. Setting up roles is one situation where you want
to be pretty explicit, so that users do not see
Another block that warrants explanation is the
This code block sets a goal for the interview: finding the value of
announce_winner. Note that if we took out the two
the interview could still get done, because
implicitly asks for both
The problem with that (or the inconvenience) is that
looks for the value of
first_person_bid before it looks for the
second_person_bid. This means that the second participant
would have to wait to enter his bid until the first participant had
done so. This would be arbitrary and could cause unnecessary delay.
The additional code here will ask each participant for his bid
regardless of which one is first to log in.
The URL that is created through
interview_url() contains the secret
“session key” of the interview, which was created when the organizer
started the interview. When someone goes to this URL, they will enter
the interview that is already in progress, whatever the current state
of the interview is. Note that the URL in the location bar of the web
browser will be shortened after the first page load, but the
interview-specific information in the URL will not be forgotten
(essentially, it is moved from the location bar into a cookie in the
In the example above, there were two participants in the interview
(other than the organizer):
what if you will have more than two participants? Do you have to
roles up to
ten_thousandth_person? No – there are other
ways to handle multi-user interviews.
Consider the following example, which uses generic objects:
This interview asks every user how many cats he or she has, and then tells the user the total number of cats of all of the interview respondents.
Note that this interview allows multiple users but does not make use
default role features. The purpose of those
features is to put one user on hold while waiting for input from
another user. There are some situations, like the above interview,
that do not require one user to wait for another user. In that case,
it is not necessary to set user roles.
DAObject is the most basic type of docassemble object. Its
definition is in
docassemble.base.util. The fact that the
DAObject means that the
user can have attributes and
those attributes can be gathered with generic object questions.
initial code block also keeps track of all the users that have
used the interview (i.e. by either starting the interview from scratch
or clicking on the link given by
interview_url) so that the Mako
code in the
final_page question can loop over all of the users and
tally up the number of cats.
These lines in the
initial block define the
user variable and keep
track of each user:
user_info() is a special function that returns information about
the logged-in user. If the user was not logged in, the
objects block defines
respondents as an object of type
DADict acts much like an ordinary Python dictionary, except that it
has special properties that allow docassemble to set its
generic object questions.
However, it does not work to actually write that; the
method takes care of the docassemble internals that allow
docassemble to set undefined attributes.
The Mako code contains this line:
hasattr function is a built-in Python function that returns
respondent has an attribute called
False if not. We are saying here that we want to tally the total
number of cats for the user and all respondents who have answered the
question about the number of cats they have. If we did not exclude
respondents who had not yet indicated their number of cats, then the
user might be asked for the number of cats belonging to a different
respondent. It would be rare that this would ever happen – it would
happen if the user checked the number of cats between the time another
respondent logged in and the time the respondent entered his number of
his cats – but it is important to anticipate and control for rare
You do not need need to use the role-switching system to have a multi-user interview. It helps, though, to use the user login system to keep track of who the user is. Here is an example of an interview where two users each sign a document: