Features¶
Direct write to¶
In the pages of your site, you can put links containing the recipient name(s).
Example:
<a href="{% url 'postman:write' username %}">write to {{ username }}</a>
Separate multiple usernames with a :
character.
Example:
<a href="{% url 'postman:write' 'adm1:adm2:adm3' %}">write to admins</a>
Prefilled fields¶
You may prefill the contents of some fields by providing a query string in the link.
Example:
<a href="{% url 'postman:write' %}?subject=details request&body=give me details about ...">
ask for details
</a>
Recipients Min/Max¶
If you need to constraint the maximum number of recipients in the forms,
you can pass the optional max
parameter to the view.
There is no parameter for a minimum number, but you can code a custom form
and pass a min
parameter to the recipient field (see Advanced Usage below for details).
Views supporting the parameter are: WriteView
, ReplyView
.
But this parameter does not apply to the default AnonymousWriteForm
for visitors:
The maximum is enforced to 1 (see Advanced Usage below for knowing how),
in order to keep the features available to anonymous users to a strict minimum.
Example:
urlpatterns = patterns('postman.views',
# ...
url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',
WriteView.as_view(max=3),
name='write'),
# ...
)
Advanced usage¶
If you define your own custom form, you may specify a min
parameter and a max
parameter
to the recipients field.
For example:
from postman.forms import WriteForm
class MyWriteForm(WriteForm):
recipients = CommaSeparatedUserField(label="Recipients", min=2, max=5)
If you do not want the fixed max
parameter of the recipients field in your custom form,
to be superseded by the parameter passed to the view, set the can_overwrite_limits
form attribute to False
.
For example:
class MyThreeAnonymousWriteForm(MyBaseAnonymousWriteForm):
can_overwrite_limits = False
recipients = CommaSeparatedUserField(label="Recipients", max=3)
See also:
- the
POSTMAN_DISALLOW_MULTIRECIPIENTS
setting in Optional settings
User filter¶
If there are some situations where a user should not be a recipient, you can write a filter and pass it to the view.
Views supporting a user filter are: WriteView
, ReplyView
.
Example:
def my_user_filter(user):
if user.get_profile().is_absent:
return "is away"
return None
urlpatterns = patterns('postman.views',
# ...
url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',
WriteView.as_view(user_filter=my_user_filter),
name='write'),
# ...
)
The filter will be called for each recipient, for validation.
Input:
user
: a User instance, as the recipient of the message
Output:
If the recipient is allowed, just return None
.
To forbid the message, use one of these means:
- return
False
or''
, if you do not want to give a reason for the refusal. The error message will be: “Some usernames are rejected: foo, bar.” - return a string, as a reason for the refusal. The error message will be: “Some usernames are rejected: foo (reason), bar (reason).”
- raise a
ValidationError
with an error message to your liking.
Advanced usage¶
If you define your own custom form, you may specify a user filter inside.
For example:
def my_user_filter(user):
# ...
return None
from postman.forms import WriteForm
class MyWriteForm(WriteForm):
recipients = CommaSeparatedUserField(label="Recipients", user_filter=my_user_filter)
Exchange filter¶
If there are some situations where an exchange should not take place, you can write a filter and pass it to the view. Typical usages would be: blacklists, users that do not want solicitation from visitors.
Views supporting an exchange filter are: WriteView
, ReplyView
.
An example, with the django-relationships application:
def my_exchange_filter(sender, recipient, recipients_list):
if recipient.relationships.exists(sender, RelationshipStatus.objects.blocking()):
return "has blacklisted you"
return None
urlpatterns = patterns('postman.views',
# ...
url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',
WriteView.as_view(exchange_filter=my_exchange_filter),
name='write'),
# ...
)
The filter will be called for each couple, to validate that the exchange is possible.
New in version 3.3.0
In the case of a reply, there is an additional call for the implicit recipient when it is a User.
The value of the recipients_list
parameter allows to differentiate the context.
Inputs:
sender
: a User instance, as the sender of the message, or None if the writer is not authenticatedrecipient
: a User instance, as the recipient of the messagerecipients_list
: the full list of recipients or (New in version 3.3.0) None in the case of the implicit recipient for a reply. Provided as a convenient additional element of decision.
Output:
If the exchange is allowed, just return None
.
To forbid the exchange, use one of these means:
- return
False
or''
, if you do not want to give a reason for the refusal. The error message will be: “Writing to some users is not possible: foo, bar.” - return a string, as a reason for the refusal. The error message will be: “Writing to some users is not possible: foo (reason), bar (reason).”
- raise a
ValidationError
with an error message to your liking.
Advanced usage¶
If you define your own custom form, you may specify an exchange filter inside.
For example:
def my_exchange_filter(sender, recipient, recipients_list):
# ...
return None
from postman.forms import WriteForm
class MyWriteForm(WriteForm):
exchange_filter = staticmethod(my_exchange_filter)
Auto-complete field¶
An auto-complete functionality may be useful on the recipients field.
To activate the option, set at least the arg_default
key in the
POSTMAN_AUTOCOMPLETER_APP
dictionary. If the default ajax_select
application is used,
define a matching entry in the AJAX_LOOKUP_CHANNELS
dictionary.
Example:
AJAX_LOOKUP_CHANNELS = {
'postman_users': dict(model='auth.user', search_field='username'),
}
POSTMAN_AUTOCOMPLETER_APP = {
'arg_default': 'postman_users',
}
Don’t forget that not-custom channels are restricted to users having the is_staff
property.
In case of version 1.1.4/5 of django-ajax-selects:
Support for multiple recipients is not turned on by default by django-ajax-selects. To allow this capability, you have to pass the optionmultiple: true
to jquery-plugin-autocomplete.
Make your own templates, based on these two files, given as implementation examples:
postman/templates/autocomplete_postman_multiple_as1-1.html
postman/templates/autocomplete_postman_single_as1-1.html
These examples include a correction necessary for the support of the ‘multiple’ option.
In case of version 1.2.x of django-ajax-selects:
Refer to the installation guide of this application, in particular the use of AJAX_SELECT_BOOTSTRAP and AJAX_SELECT_INLINES. Support for multiple recipients is not as simple as an option: see the examples in the jQuery UI demos.
You can use the following working implementation example:
postman/templates/autocomplete_postman_multiple_as1-2.html
New in version 3.3.0 In case of version 1.3.x of django-ajax-selects:
To make your own
templates/autocomplete.html
ortemplates/autocomplete_<channel>.html
, you can use the following working implementation example:
postman/templates/autocomplete_postman_multiple_as1-3.html
Customization¶
You may attach a specific channel, different from the default one, to a particular view.
Views supporting an auto-complete parameter are: WriteView
, ReplyView
.
For the WriteView
view, the parameter is named autocomplete_channels
(note the plural).
It supports two variations:
- a 2-tuple of channels names: the first one for authenticated users, the second for visitors.
Specify
None
if you let the default channel name for one of the tuple parts. - a single channel name: the same for users and visitors
For the ReplyView
view, the parameter is named autocomplete_channel
(note the singular).
The value is the channel name.
Example:
urlpatterns = patterns('postman.views',
# ...
url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',
WriteView.as_view(autocomplete_channels=(None,'anonymous_ac')),
name='write'),
url(r'^reply/(?P<message_id>[\d]+)/$',
ReplyView.as_view(autocomplete_channel='reply_ac'),
name='reply'),
# ...
)
Example:
urlpatterns = patterns('postman.views',
# ...
url(r'^write/(?:(?P<recipients>[^/#]+)/)?$',
WriteView.as_view(autocomplete_channels='write_ac'),
name='write'),
# ...
)
Advanced usage¶
If you define your own custom form, you may specify an autocomplete channel inside.
For example:
from postman.forms import WriteForm
class MyWriteForm(WriteForm):
recipients = CommaSeparatedUserField(label="Recipients", channel='my_channel')