:droplet: Use Django admin to manage drip campaign emails using querysets on Django's User model.

rootstrap, updated πŸ•₯ 2023-02-15 18:53:53

Maintainability Test Coverage License: MIT

Django Drip Campaigns

Build Status

Drip campaigns are pre-written sets of emails sent to customers or prospects over time. Django Drips lets you use the admin to manage drip campaign emails using querysets on Django's User model.

This project is a fork of the one written by Zapier.

You can check out the docs here.

Installation:

  1. Install django-drip-campaings using pip:

pip install django-drip-campaigns

  1. Add 'drip' to your INSTALLED_APPS list on your settings.

```python INSTALLED_APPS = [ 'django.contrib.contenttypes', 'django.contrib.comments', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin',

# ...

'drip',

] ```

  1. (Optional) Set DRIP_FROM_EMAIL = '<your_app_from_email>' in your settings, where <your_app_from_email> is the email account that is going to be shown in the sent emails. Otherwise EMAIL_HOST_USER value will be used.

  2. Finally, run python manage.py migrate drip to set up the necessary database tables.

Usage

If you haven't, create a superuser with the Django createsuperuser command. Login with the admin user, and select Drips to manage them. You will be able to:

  • View created drips.
  • Create a new drip.
  • Select and delete drips.

Now you can also manage campaigns, select Campaigns to manage them. You will be able to: - View created campaigns. - Create a new campaign. - Select and delete campaign.

Create Campaign

In the Django admin, after select Campaigns, you can click on ADD CAMPAIGN + button to create a new one. You will see the add campaign page:

Add Campaign

When you create a campaign, you need to decide if the related drips will be deleted along with the campaign, using the Delete drips field.

Here you will find an inline creation or edition for Drips this will not include the QUERY SET RULES section. It will only allow you to change the mail content in the Drip.

Campaigns will allow you to manage many Drips that need to be related between them.

Create Drip

In the Django admin, after select Drips, you can click on ADD DRIP + button to create a new one. You will see the add drip page:

Add Drip

Here you can relate the Drip to the corresponding Campaign. Grouping several drips under a campaign.

On the FIELD NAME OF USER input, when you click on it, you will be able to view:

  • The fields of your user's model.
  • The fields of your user's model in other models that are related with it.

Please take a look a this example:

Lookup fields

With this, you can select one or more fields to create useful drips. Additionally if you select a field name of user that has a date type, you can enter in the FIELD VALUE input, a date value written in natural language that combines operations on the current datetime. For example, if you have selected the field last_login that has a date type, and you want to create a drip to send emails to the users who logged in exactly one week ago; you can enter:

now-1 week

or

now- 1 w

Possible operations and values:

  • Add (+) or subtract (-) dates.
  • On the left side of the operation, write the current datetime value: now.
  • On the right side of the operation:
  • seconds or s.
  • minutes or m.
  • hours or h.
  • days or d.
  • weeks or w.
  • If you enter the number 1, you can write second, minute, etc.
  • Don't enter a space between now and the operation symbol. Optionally you can add (or not) a space around the number value.

Let's see some examples of the date values that you can enter:

  • now-1 day
  • now+ 8days
  • now+ 1 h
  • now-4hours
  • now- 3 weeks
  • now-1 weeks

View Timeline

In the Django admin, you can select a drip and then click on the VIEW TIMELINE button to view the mails expected to be sent with the corresponding receivers:

Timeline

Send drips

To send the created and enabled drips, run the command:

python manage.py send_drips

You can use cron to schedule the drips.

The cron scheduler

You may want to have an easy way to send drips periodically. It's possible to set a couple of parameters in your settings to do that. First activate the scheduler by adding the DRIP_SCHEDULE_SETTINGS dictionary:

```python

your settings file

DRIP_SCHEDULE_SETTINGS = { 'DRIP_SCHEDULE': True, }

```

After that, choose:

  • A day of the week: An integer value between 0-6, or a string: 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'. The name in the settings is DRIP_SCHEDULE_DAY_OF_WEEK (default is set to 0).
  • An hour: An integer value between 0-23. The name in the settings is DRIP_SCHEDULE_HOUR (default is set to 0).
  • A minute: An integer value between 0-59. The name in the settings is DRIP_SCHEDULE_MINUTE (default is set to 0).

With those values, a cron scheduler will execute the send_drips command every week in the specified day/hour/minute. The scheduler will use the timezone of your TIME_ZONE parameter in your settings (default is set to 'UTC'). For example, if you have:

python DRIP_SCHEDULE_SETTINGS = { 'DRIP_SCHEDULE': True, 'DRIP_SCHEDULE_DAY_OF_WEEK': 'mon', 'DRIP_SCHEDULE_HOUR': 13, 'DRIP_SCHEDULE_MINUTE': 57, }

Then every Monday at 13:57 the send_drips command will be executed. Last but not least, add this line at the end of your main urls.py file to start the scheduler:

```python

your main urls.py file

... from drip.scheduler.cron_scheduler import cron_send_drips

... cron_send_drips() ```

We recommend you to do it there because we know for sure that it's a file that is executed once at the beginning.

Some tips:

  • If you want to run the command every day in the week, hour, or minute, just set the corresponding parameter to '*'.
  • If you want to run the command more than a day in the week, just set the DRIP_SCHEDULE_DAY_OF_WEEK to more than one value. For example, if you set that to 'mon-fri' the command will be executed from Monday to Friday.

Celery integration

IMPORTANT: We use Celery 5.2.2 that supports Django 1.11 LTS or newer versions.

If you need to use celery it can be configured in the same way you just need to add the following key SCHEDULER setted as "CELERY": python DRIP_SCHEDULE_SETTINGS = { 'DRIP_SCHEDULE': True, 'DRIP_SCHEDULE_DAY_OF_WEEK': 'mon', 'DRIP_SCHEDULE_HOUR': 13, 'DRIP_SCHEDULE_MINUTE': 57, 'SCHEDULER': "CELERY", } The default value of this key is "CRON", if you enable DRIP_SCHEDULE it will work with a Cron by default.

In order to make this happen, the project's celery.py setup shall invoke the autodiscoverttasks function. This task is scheduled with a simple Celery beat configuration.

Issues

Bump django from 3.2.15 to 3.2.18

opened on 2023-02-15 18:53:48 by dependabot[bot]

Bumps django from 3.2.15 to 3.2.18.

Commits
  • 722e9f8 [3.2.x] Bumped version for 3.2.18 release.
  • a665ed5 [3.2.x] Fixed CVE-2023-24580 -- Prevented DoS with too many uploaded files.
  • 932b5bd [3.2.x] Added stub release notes for 3.2.18.
  • c35a578 [3.2.x] Added CVE-2023-23969 to security archive.
  • 9bd8db3 [3.2.x] Post-release version bump.
  • aed1bb5 [3.2.x] Bumped version for 3.2.17 release.
  • c7e0151 [3.2.x] Fixed CVE-2023-23969 -- Prevented DoS with pathological values for Ac...
  • 9da4634 [3.2.x] Fixed inspectdb.tests.InspectDBTestCase.test_custom_fields() on SQLit...
  • 4c2b261 [3.2.x] Removed 'tests' path prefix in a couple tests.
  • d215431 [3.2.x] Adjusted release notes for 3.2.17.
  • Additional commits viewable in compare view


Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/rootstrap/django-drip-campaigns/network/alerts).

Bump ipython from 8.4.0 to 8.10.0

opened on 2023-02-11 01:50:54 by dependabot[bot]

Bumps ipython from 8.4.0 to 8.10.0.

Commits
  • 15ea1ed release 8.10.0
  • 560ad10 DOC: Update what's new for 8.10 (#13939)
  • 7557ade DOC: Update what's new for 8.10
  • 385d693 Merge pull request from GHSA-29gw-9793-fvw7
  • e548ee2 Swallow potential exceptions from showtraceback() (#13934)
  • 0694b08 MAINT: mock slowest test. (#13885)
  • 8655912 MAINT: mock slowest test.
  • a011765 Isolate the attack tests with setUp and tearDown methods
  • c7a9470 Add some regression tests for this change
  • fd34cf5 Swallow potential exceptions from showtraceback()
  • Additional commits viewable in compare view


Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/rootstrap/django-drip-campaigns/network/alerts).

Bump setuptools from 64.0.2 to 65.5.1

opened on 2022-12-27 17:14:07 by dependabot[bot]

Bumps setuptools from 64.0.2 to 65.5.1.

Changelog

Sourced from setuptools's changelog.

v65.5.1

Misc ^^^^

  • #3638: Drop a test dependency on the mock package, always use :external+python:py:mod:unittest.mock -- by :user:hroncok
  • #3659: Fixed REDoS vector in package_index.

v65.5.0

Changes ^^^^^^^

  • #3624: Fixed editable install for multi-module/no-package src-layout projects.
  • #3626: Minor refactorings to support distutils using stdlib logging module.

Documentation changes ^^^^^^^^^^^^^^^^^^^^^

  • #3419: Updated the example version numbers to be compliant with PEP-440 on the "Specifying Your Project’s Version" page of the user guide.

Misc ^^^^

  • #3569: Improved information about conflicting entries in the current working directory and editable install (in documentation and as an informational warning).
  • #3576: Updated version of validate_pyproject.

v65.4.1

Misc ^^^^

v65.4.0

Changes ^^^^^^^

v65.3.0

... (truncated)

Commits


Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/rootstrap/django-drip-campaigns/network/alerts).

Bump certifi from 2020.12.5 to 2022.12.7

opened on 2022-12-08 07:46:05 by dependabot[bot]

Bumps certifi from 2020.12.5 to 2022.12.7.

Commits


Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/rootstrap/django-drip-campaigns/network/alerts).

HTML Emails

opened on 2022-11-28 06:52:22 by josylad

Hello, Firstly, thanks for maintaining this package, it is very useful.

Secondly, is it possible to send HTML emails? Also, how about a WYSIWYG editor like CKEditor for composing a well formatted email.

Any ideas on how to achieve this?

add translator between a predefined grammar and django's filter lookups

opened on 2020-12-24 01:28:08 by jiss2891

Description

Allows django drips to write simpler Human readable queries to be applied to Drips

Examples

Input: (enable is False) and (sent_drips null True) and (name is "Nacho's Drip") Output: {'enabled': False, 'sent_drips__isnull': True, 'name': "Nacho's Drip"}

Usage

python input_expression = "(enabled is False) and (sent_drips null False)" filter = translate_query(input_expression, grammar) assert Drip.objects.filter(**filter).count() == 0

Changes include

  • [x] New feature (non-breaking change that adds functionality)

Other comments

There is needed some work to include OR branching and stuff.

hacktoberfest