Improve and document JSON serialization for Mandrill API

* Add some context to exceptions on unserializable
  values (addresses #89).
* Document need to format merge data
  (into something JSON-serializable).
* Add RemovedInDjrill2 DeprecationWarning.
* Deprecate blanket date/datetime serialization.
This commit is contained in:
medmunds
2015-05-12 13:29:52 -07:00
parent 52de627af1
commit cc56b96efa
9 changed files with 214 additions and 13 deletions

View File

@@ -7,6 +7,35 @@ Among other things, this means that minor updates
and breaking changes will always increment the
major version number (1.x to 2.0).
Upcoming Changes in Djrill 2.0
------------------------------
Djrill 2.0 is under development and will include some breaking changes.
Although the changes won't impact most Djrill users, the current
version of Djrill (1.4) will try to warn you if you use things
that will change. (Warnings appear in the console when running Django
in debug mode.)
* **Dates in merge data and other attributes**
Djrill automatically converts :attr:`send_at` `date` and `datetime`
values to the ISO 8601 string format expected by the Mandrill API.
Unintentionally, it also converts dates used in other Mandrill message
attributes (such as :attr:`merge_vars` or :attr:`metadata`) where it
might not be expected (or appropriate).
Djrill 2.0 will remove this automatic date formatting, except
for attributes that are inherently dates (currently only `send_at`).
To assist in detecting code relying on the (undocumented) current
behavior, Djrill 1.4 will report a `DeprecationWarning` for `date`
or `datetime` values used in any Mandrill message attributes other
than `send_at`. See :ref:`formatting-merge-data` for other options.
Change Log
----------
Version 1.4 (development):
@@ -15,6 +44,9 @@ Version 1.4 (development):
(Specifying a :ref:`Reply-To header <message-headers>`
still works, with any version of Django,
and will override the reply_to param if you use both.)
* More-helpful exception when using a non-JSON-serializable
type in merge_vars and other Djrill message attributes
* Deprecation warnings for upcoming 2.0 changes (see above)
Version 1.3:

View File

@@ -198,6 +198,9 @@ Most of the options from the Mandrill
message.global_merge_vars = {'company': "ACME", 'offer': "10% off"}
Merge data must be strings or other JSON-serializable types.
(See :ref:`formatting-merge-data` for details.)
.. attribute:: merge_vars
``dict``: per-recipient merge variables (most useful with :ref:`mandrill-templates`). The keys
@@ -209,6 +212,9 @@ Most of the options from the Mandrill
'rr@example.com': {'offer': "instant tunnel paint"}
}
Merge data must be strings or other JSON-serializable types.
(See :ref:`formatting-merge-data` for details.)
.. attribute:: tags
``list`` of ``str``: tags to apply to the message, for filtering reports in the Mandrill
@@ -245,12 +251,18 @@ Most of the options from the Mandrill
message.metadata = {'customer': customer.id, 'order': order.reference_number}
Mandrill restricts metadata keys to alphanumeric characters and underscore, and
metadata values to numbers, strings, boolean values, and None (null).
.. attribute:: recipient_metadata
``dict``: per-recipient metadata values. Keys are the recipient email addresses,
and values are dicts of metadata for each recipient (similar to
:attr:`merge_vars`)
Mandrill restricts metadata keys to alphanumeric characters and underscore, and
metadata values to numbers, strings, boolean values, and None (null).
.. attribute:: async
``Boolean``: whether Mandrill should use an async mode optimized for bulk sending.

View File

@@ -37,6 +37,45 @@ and will ignore any `body` text set on the `EmailMessage`.
All of Djrill's other :ref:`Mandrill-specific options <mandrill-send-support>`
can be used with templates.
.. _formatting-merge-data:
Formatting Merge Data
~~~~~~~~~~~~~~~~~~~~~
If you're using dates, datetimes, Decimals, or anything other than strings and integers,
you'll need to format them into strings for use as merge data::
product = Product.objects.get(123) # A Django model
total_cost = Decimal('19.99')
ship_date = date(2015, 11, 18)
# Won't work -- you'll get "not JSON serializable" exceptions:
msg.global_merge_vars = {
'PRODUCT': product,
'TOTAL_COST': total_cost,
'SHIP_DATE': ship_date
}
# Do something this instead:
msg.global_merge_vars = {
'PRODUCT': product.name, # assuming name is a CharField
'TOTAL_COST': "%.2f" % total_cost,
'SHIP_DATE': ship_date.strftime('%B %d, %Y') # US-style "March 15, 2015"
}
These are just examples. You'll need to determine the best way to format
your merge data as strings.
Although floats are allowed in merge vars, you'll generally want to format them
into strings yourself to avoid surprises with floating-point precision.
Technically, Djrill will accept anything serializable by the Python json package --
which means advanced template users can include dicts and lists as merge vars
(for templates designed to handle objects and arrays).
See the Python :class:`json.JSONEncoder` docs for a list of allowable types.
How To Use Default Mandrill Subject and From fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~