DEV Community

Cover image for Managing Drip Campaigns with Rootstrap Django Drip Library
brunomichetti for Rootstrap

Posted on

Managing Drip Campaigns with Rootstrap Django Drip Library

At Rootstrap we work with many initiatives, one of them is the Open Source one. The main goal in this case, is to analyze, maintain and develop open source software (OSS). In this blog post I'm going to talk about a particular project named Django Drip Campaigns and how was the process of publishing it as a pypi package.

Pypi (that stands for Python Package Index) is a repository of software for the Python programming language that helps us find and install software developed by the Python community. One of our contributions to the OSS community is to publish and maintain the mentioned project and I want to share that experience in this article.

The Django Drip Campaigns Project

Django Drip Campaigns Project is an open source app to create drip campaigns for email using Django’s admin interface and a User queryset. This means that using this app, you are able to easily schedule and send emails to the registered users, creating querysets in a friendly interface.

For example, you can very quickly configure your app to send a periodic email to the users that haven't logged in in a day or more, send a custom email to the users that registered more than a week ago, etc. To do this, you only need to define one or more querysets in the admin page.
If you want to install it and work with it, you can follow the simple steps documented in the github page of Django Drip Campaigns.

We didn't create this project, we just made a fork of the one written by Zapier that is no longer maintained. After this, we worked on fixing some bugs, doing a couple of enhancements, creating more documentation and publishing the app as a pypi package.

Since it's published, any programmer that wants to use this project in his django app is able to quickly download it with a simple command described in the mentioned docs.

Features

After a successful installation and configuration, you are able to easily create drip campaigns for email using the admin interface of Django. If you don't have an admin user, create one with the django createsuperuser command. After this, login into Django's admin page and click on Drips to manage them. There you are able to:

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

Creating a new drip

Click on the ADD DRIP + button to create a new drip. You will see a page like this:

Add drip

In the next section I will talk about the queryset rules that you can build in an easy way to create very useful drips.

Queryset rules

When you create a drip, you need at least one queryset so the users in it will be the ones that receive the defined email. In the METHOD TYPE menu you are able to choose to filter or to exclude the users in the defined queryset.

On the other hand, when you click in the FIELD NAME OF USER input, you will see the fields of your User model, and the fields of your user model in the models related to it:

Look Up Fields

In the previous image, for example, last_login is the field in the User model, and groups__user__id is the user id from the Groups model that is related to it. So you can enter the name of the field or select it from the list that you see when you click on the input.

After the selection of the field name, you have to choose the type of lookup that you want to do over the field. The possibilities are exactly, exactly (case insensitive), contains, contains (case insensitive), greater than, greater than or equal to, less than, etc. This lookup type will be done over the user field and the FIELD VALUE that you enter.

The FIELD VALUE input can be a string, a number, or a regular expression. The correctness of the queryset rule will depend on the type of the user field, the lookup type, and the field value.

When you enter a user field that has a date type, Django Drip Campaigns allows you to enter a date value in natural language combining the current time and some operation with seconds, hours, days, etc. 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
Enter fullscreen mode Exit fullscreen mode

or

now- 1 w
Enter fullscreen mode Exit fullscreen mode

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

To finalize this subsection, I would like to show you two examples to clarify the queryset rules creation:

  • Send a recordatory email to the users that haven't logged in for a week or more:
    • method type: filter
    • user field: last_login
    • lookup type: less than or equal to
    • field value: now- 1 week
  • Send an email to the users that have a gmail account, excluding the ones that registered yesterday:
    • Rule 1:
    • method type: filter
    • user field: email
    • lookup type: contains
    • field value: gmail
    • Rule 2:
    • method type: exclude
    • user field: date_joined
    • lookup type: exactly
    • field value: now- 1 d

As you can see, the queryset rules creation is very powerful and for each drip you can add as many as you want.

View the timeline of a drip

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

TimeLine

Message class

By default, Django Drip creates and sends messages that are instances of Django’s EmailMultiAlternatives class. If you want to customize in any way the message that is created and sent, you can do that by creating a subclass of EmailMessage and overriding any method that you want to behave differently. For example:

from django.core.mail import EmailMessage
from drip.drips import DripMessage

class PlainDripEmail(DripMessage):

    @property
    def message(self):
        if not self._message:
            email = EmailMessage(self.subject, self.plain, self.from_email, [self.user.email])
            self._message = email
        return self._message
Enter fullscreen mode Exit fullscreen mode

In that example, PlainDripEmail overrides the message property of the base DripMessage class to create a simple EmailMessage instance instead of an EmailMultiAlternatives instance.

In order to be able to specify that your custom message class should be used for a drip, you need to configure it in the DRIP_MESSAGE_CLASSES setting:

DRIP_MESSAGE_CLASSES = {
    'plain': 'myproj.email.PlainDripEmail',
}

Enter fullscreen mode Exit fullscreen mode

This will allow you to choose in the admin, for each drip, whether the default (DripMessage) or plain message class should be used for generating and sending the messages to users.

Send drips

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

python manage.py send_drips
Enter fullscreen mode Exit fullscreen mode

You can use cron to schedule the drips.

What we have been doing in the project

As I said, we didn't create this project. We forked it and started to make some fixes and improvements. The first thing we did was to upgrade the used Django version. Now it has django 3.0.7.

Besides we started to create the documentation with Sphinx to have this project in Read the Docs in the future.

Another enhancement was to add flake8 to enforce the use of style guides in the code. Finally we added an integration with travis-ci to have a continuous integration service on any change in the project.

We registered and fixed some issues such as the view of the User fields, and configuration problems to run the app locally. There are some issues to address and discover yet so if you like OSS you are more than welcome to work with Django Drip Campaigns.

In the open source initiative we wanted to publish this app as a pypi package, so I'll explain this a little more in the next section.

Publish a pypi package

Despite Django Drip Campaigns is still a work in progress, we already published the package in PyPI. It's nothing fancy, but it's a must to know a few things before starting, so in this section, I'll be talking about the main steps for publishing an app.

  • Project structure: Your project needs a couple of files in a determined place to be published correctly. An appropriate structure could be:
root_project_folder/
  |
  |__ docs/    # Documentation files
  |__ project_folder/  # Code of the app
  |__ AUTHORS.md
  |__ LICENSE.txt
  |__ MANIFEST.in
  |__ README.md
  |__ setup.py
Enter fullscreen mode Exit fullscreen mode
  • AUTHORS: Specify the author's information of your project in this file.

  • LICENSE: You have to specify the license of the project. That is a document that provides legally binding guidelines for the use and distribution of software. In OSS the most known are BSD and MIT. We used an MIT license in this case.

  • MANIFEST: Here you can specify the files that aren't programming files but you want to include anyway in the build of your project. For example the authors file, the docs, etc.

  • README.md: A file where you introduce and explain your project. It's very important because otherwise you can have a very good and useful project but if new people see it and don't understand what it does nor how it works, then it won't be used.

  • setup.py: This is a fundamental file. It contains a global setup function that is in charge of the building and configuration of your project at the moment of the installation.

  • docs folder: Here is where the files of the documentation are.

You can see examples of the described files in the django-drip-campaigns github page. Of course your project can have other files, the ones mentioned are the most important to publish a pypi package.

Having all set and ready to be published, you need now to register in the pypi.org page. After you are registered, go inside the terminal to your project folder and follow these steps:

  1. Install setuptools and wheel. They are used to generate the distribution package: a group of files needed to upload your app.
python3 -m pip install --user --upgrade setuptools wheel
Enter fullscreen mode Exit fullscreen mode
  1. Generate the distribution package. The next command will create all the necessary files under a dist/ folder:
python3 setup.py sdist bdist_wheel
Enter fullscreen mode Exit fullscreen mode
  1. Install twine, that a allows you to upload your app as a package:
python3 -m pip install --user --upgrade twine
Enter fullscreen mode Exit fullscreen mode
  1. Once installed, run twine to upload the archives under dist/. This will ask for a user and a password, that are the ones you used on the registration at pypi:
python3 -m twine upload --repository pypi dist/*
Enter fullscreen mode Exit fullscreen mode

If everything went well, you have published your project as a pypi package. Now you anyone is able to download it with:

pip3 install <project-name>
Enter fullscreen mode Exit fullscreen mode

Summary

In this blog post I talked about the Django Drip Campaigns project, its main features and what we did with it at Rootstrap. We love to make contributions to OSS because it's a wonderful way of learning, of sharing knowledge, and creating useful programs to be used by other programmers.

Besides I talked about the experience and how to publish a project as a pypi package so anyone who wants to give it a try can download it with a simple command.

OSS gives a great opportunity not only to see how some other group of people solves a problem addressed by the program, but also to purpose and contribute with fixes and improvements. Finally, I hope you have enjoyed this blog and feel motivated to use and work with Django Drip Campaigns and to contribute with OSS.

Top comments (0)