Adding Mailchimp actions to a Django model

As I get ready to try a second time to attract users, I decided to use MailChimp mailing lists to keep in touch with these users, as well as setting up some ‘tutorial’ emails at regular intervals. (I’m imagining something like “You’ve been using dynamic-efl.com for a week now, did you know you can do this to get more out of it?”)

To do this, I’d have to have code in Django that automatically signed members up. That means that this is my first attempt to work with an API, even by way of a library.

I decided to go with the mailchimp3 library and installed it in my virtualenv according to the instructions and set up some variables in my settings.py file.

# Mailchimp stuff
# Authentication
MAILCHIMP_LOGIN = 'login'
MAILCHIMP_KEY = '===>SECRET<==='

# The lists
MAILCHIMP_LISTS = {'welcome': 'listID',
                   'germany': 'listID',
                   'beta-testers': 'listID'}<span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>

The idea here is that I’ll be able to iterate over the keys in the lists, if I ever need to check that the user is in all the lists (for example, removing a user should include removing him from all lists).

To that end, I added a function at the beginning of my models.py file. (This probably isn’t good form).

def mailchimp_get():
    """ Returns a logged-in mailchimp client """
    return MailChimp(settings.MAILCHIMP_LOGIN, settings.MAILCHIMP_KEY)<span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>

It seemed like the easiest way to only write the login once.

Finally, I had to create a few methods in the Model in question (in my case, this is my teacher model, as my users are called ‘Teachers’ in this bit.

def mailchimp_add_teacher_to_list(self, listname):
    """ Takes a listname, checks that the teacher is not a member of the list, then adds it. """
    client = mailchimp_get()
    listid = settings.MAILCHIMP_LISTS[listname]
    if not self.mailchimp_teacher_in_list(listname):
        data = {
            'email_address': self.user.email,
            'status': 'subscribed',
            'merge_fields': {
                'FNAME': self.user.first_name
            }
        }
        client.lists.members.create(listid, data)

def mailchimp_lists_get(self):
    """ TEMPORARY - Returns a list of all mailchimp lists """
    client = mailchimp_get()
    return client.lists.all(get_all=True, fields="lists.name,lists.id")

def mailchimp_teacher_in_list(self, listname):
    """ Returns a bool indicating if this teacher's email address is in the list """
    email = self.user.email
    client = mailchimp_get()
    results = client.lists.members.all(settings.MAILCHIMP_LISTS[listname], get_all=True, fields="members.email_address")
    members = results['members']
    addresses = []
    for m in members:
        addresses.append(m['email_address'])

    return email in addresses

I think the names should be pretty self-explanatory. The mailchimp_lists_get() method was just an experiment based on following the instructions in the documents.

Lastly, I created a view and a URL just to test these functions by printing to the console and looking at the (currently empty) lists in mailchimp.

Summary

It was my first time sitting down and thinking critically about what I wanted and how to do it and I have to say that mailchimp and the library basically made it painless. I have other project ideas that will require more API integration, and it’s made me hopeful.

Advertisements

Live in the present moment

There is not a lot to explain about this chapter title in The Obstacle is the Way. So, I’ll jump to the first quote that jumped out at me further on in the chapter:

For all species other than us humans, things just are what they are. Our problem is that we’re always trying to figure out what things mean–why things are the way they are.

It’s true, and it’s something I think about often. I mean, I tell myself that a deer in the forest isn’t thinking about the looming Monday and returning to work… it’s just feeling safe or unsafe. (To be fair, the deer doesn’t have to go to work on Monday.  But also, its chances of dying of old age are worse than mine.)

The basic idea, the way I read this chapter, is to say that we shouldn’t have a programmed future, as that gives us something to measure ourselves against. Are we progressing towards that future? Is this moment the way we told ourselves it would be?

The book doesn’t say this, but I assume that there’s no indication that we shouldn’t make plans, only that we shouldn’t let those plans overwhelm us.

Something I like about this book is that the author, Ryan Holiday, makes some concrete suggestions:

You’ll find the method that works best for you, but there are many thigns that can pul you into the present moment: Strenuous exercise. Unplugging. A walk in the park. Meditation. Getting a dog–they’re a constant reminder of how pleasant the present is.

And, he goes on to provide one more great piece of advice:

On thing is certain. It’s not simply a matter of saying: Oh, I’ll live in the present. You have to work at it. Catch your mind when it wanders. Don’t let it get away from you.

When it’s not easy for me, it’s good to know that it’s not easy for anyone.

The Road Ahead

As I look at my coding journey, I realize I’ve stagnated a bit. I mean, I’m super proud of the Dynamic Worksheets program, but, to be honest, I’ve moved away from coding.

Lately, the coding work that I do is realizing that something is broken, and then spending an afternoon mostly realizing that my code really does make no sense. And then, eventually, finding the problem and fixing it. It is not as rewarding as actually building the thing was.

And, it’s not for lack of ideas. Or, really, for lack of time (though discipline is a thing that needs to be trained and maintained). I’ve kinda reached a place where I’ve lost track of my next steps.

So, it might help to write through this.

Logical next steps for the worksheet site

I had really hoped that I’d have users for the site before the end of 2017. And, though I shared it with a few people, only one of them actually went through the steps of making worksheets.

So, if I set “making dynamic-efl.com a community of teachers who actually use it (in Germany, at least) to make their classes better,” what are the logical next steps?

Here are the things it makes sense to work on in 2018:

  • Establish a list of exactly which “behind the scenes” tools I want before I advertise, and make them.
  • Draft the series of “welcome emails” as well as “explainer videos” that users will be sent/invited to view with time.
  • Write out a plan for how I’ll approach the market, planning on times to ‘force’ written reflection on lessons learned.
  • Implement the plan.

I’m not going to lie. Most of those things feel more like work to me, than like the play that creating the site was. I look forward to having people use something that I made, and think it’s fair to say that it’s not fully finished until people use it and value it.

So, what are the things I’m excited about doing?

Logical coding goals for the near future

I have ideas for other projects. They meet the standards of “things I would like to use” and “things I think would make the world better.” The thing is, starting a new project seems so daunting now that I see how hard it is to get a project truly finished.

Nonetheless, there are things that I think I can do to get ready for the next project. More than one Code Newbie podcast has included a guest saying something like “there is tons of Javascript in the world that wouldn’t need to exist if people would only learn CSS.” So, as an ongoing project, it seems to make sense that I find a good course and learn CSS before I get around to learning Javascript.

There’s something I’ve meant to get done that isn’t especially sexy. I’d like to create a bunch of reusable Django boilerplate that I could use for basic user management with projects in the future. This is based on the fact that I think I did users badly in the dynamic-efl project.

Django includes a basic User model, but I found myself wanting a lot of other things (some of which I haven’t implemented, yet) like email verification links, something to automatically delete accounts that haven’t been verified or logged into in the last year. There’s more, and I should write it down.

So, put all that together, and it seems that it seems as though it would make sense for me to set the following coding goals in the near future:

  • Pick a CSS course and learn it. (Possibly, also Javascript)
  • Practice writing a Django app that can be re-used
  • Write out what I want the Eternal Customer Model (working title) to be and do
  • Code the Eternal Customer Model and, finally, use it in a project such as
  • The Latin drill program.

That gives me stuff to work on. Look for updates.

The November Fitness Review

So, November was the first month I really wanted to stick to a written training plan. Ultimately, that training plan, while not very ambitious, was something of a stretch goal. I didn’t get it done but did do more than I would have without it.

Successes

I’m counting the fact that I still try to get my plank workout in each day as a success. It doesn’t always happen (happened early today, I’ve learned that I’m more disciplined in the morning) but it happens more often than not. And, as an extra plus, my back, shoulder and arm pain is much improved, if not yet eliminated.

My foot hurts less severely and less often. I’m chalking that up to the foot exercises and will continue them.

The realization that running form matters. While out on what should have been a hard run, I decided to focus more on form than intensity, because my food had been acting up. I was surprised that it was just as effective — as measured by speed — as focusing on intensity would have been, but not quite as mentally draining. (Focusing on actually doing something seems easier than just trying to push myself.)

Failures

For a variety of lame reasons, I only hit my three-times-a-week goal twice in November. And, that was evident in the fact that I slowed down for the first time ever in my monthly 5k for time. It was 28:38 this month, as opposed to 24:37 in October.

Summary

It’s ridiculous to think I’ll get a lot of exercise in in December. December is the month that I spend the rest of the year trying to work off. Still, the experiment was good enough that my next step will be making a plan for December. At least, for the time up to the holidays.

It’s easier to expand than to fix…

I feel like everything I learn about coding is already a well-known software truism. But, I wanted to report in on my progress with the EFL worksheet software by saying that it’s moved back to the top of the priorities list and I’m working on it, but slowly.

There was a bug where the gap fill sentences created for capitalized vocabulary (‘Baltic Sea’ and ‘Vienna’ are examples) didn’t work correctly.

I immediately realized that the code put the entire sentence into lowercase (with Python’s .lower() method) before looking for the word. No problem, I thought, I’ll just find where the word is searched for and have it search for the lowercase text of the word. Problem solved.

I genuinely thought that was something I could do quickly, by way of getting back into the coding game…

More than an hour later, I found the spot where I forgot the extra .lower() call and everything was fixed. But I needed a full hour to figure out where in my code that happened.

A full hour.

I’m discouraged that I had such a hard time finding my way through my own code.

BandLab: First impressions, my setup

I recently started experimenting with BandLab, a pretty cool combination cloud music editing platform and app. The idea is pretty cool: use your mobile device to start on a project, away (presumably) from your cushy office and laptop. Then, you can work more readily at your laptop, later.

The app includes collaborative tools, and the option to ‘fork’ someone else’s work (if they’ve made it available) in order to make it your own. I like the idea.

So, I downloaded the app, and I made an account.

This is a different kind of account. It’s an accounting of my first impressions.

Recording on my mobile device

Because the phone’s built-in mic seemed to pick up more of the sounds of my fingers on the keyboard than the actual piano, I bought a splitter and a patch cable to record directly from the piano’s headphone jack.

Initially, I planned to use one headphone jack for the phone, and the other for real headphones (because it’s valuable to hear what you are playing — at least at my level of incompetence).

It was an adventure. I plugged everything in, and it seemed to work, but something about the setup was sending phantom headset volume control signals to my phone. The phone volume wasn’t important, but the constant notification was overlapping other things on the screen.

Grr.

Google research was no help. Different apps were suggested, and I installed and then uninstalled them. (Guess whether they were effective or not.)

So, in case anybody is curious, here is what I learned the hard way: using the splitter with a microphone plugged in but no headphones caused the weird signal. I guess I could have gone digging for my old jogging headphones, just to have something plugged in, but I didn’t feel like standing up.

So, I tried using BandLab’s live patch-through setting, to hear what I was playing. That drove me crazy because there was a minuscule between playing a note and hearing it and that drove me crazy.

Now I know, and I think that the next time I sit down to record, things will go more quickly. (Most of the time I had blocked out to try recording went into sorting out the cables.)

My first impression

So, what did I think?

I’ll save you long, wandering reflections on how bad my piano playing sounded when played back to me. Instead, I had two takeaway lessons from my first attempt to record something in more than one track:

  1. Playing with a metronome is going to be important if I want this to work. Sure, you can listen to what you’ve already recorded as you play, but I need to get my rhythm locked down better. I loved that BandLab broke things down into measures (you can see them at the top of the multi-track window), but that’ll only be helpful if I stick with them.
  2. I’m going to need to think more deliberately about the building blocks of a piece. That goes for ABAC type song structuring, but also for ‘what is this track for?’ kind of thinking. What I did was pretty basic: play a piece I know on piano, play it again with the ‘strings’ setting on the epiano, combine them in the app.

Where is all this going?

I don’t know. With all the other things I’m working on, I don’t know why I have this in my head. There is a ton for me still to learn, but I’ve really enjoyed my time at the piano, and this gives me a little something to work towards.

Will I post songs that I’ve written? I don’t know. I have ideas for things to write about, though no real lyrics, yet.

More likely is that I’ll post MP3s of ‘orchestrations’ I’ve made for existing songs, or instrumental music that I’ve put together on several tracks.

Only time will tell.

 

Practice Objectivity

This is another post in my ongoing series on the individual chapters in “The Obstacle is the Way.” I don’t know how useful or interesting it will be out of context.


In a chapter about how assigning values to things before we fully comprehend them, I think my favorite couple of lines are these:

Everything about our animalistic brains tries to compress the space between impression and perception. Think, perceive, act–with millisecond between them.

A deer’s brain tells it to run because things are bad. It runs. Sometimes, right into traffic.

I think I those lines for a number of reasons. I like the acknowledgment of our ‘animalistic brains,’ I like the visual aid, and I like the juxtaposition of the animal and the modern, because our animalistic brains weren’t made for the environment in which we live.

Which isn’t to say that they don’t offer anything of value, but that reacting to an upset boss the way you’d react to a predator–or even an upset ‘chieftain’ in a hunter-gatherer society–is counter-productive and one of the ways we repress ourselves.

I’m diverging away from the material of the chapter by getting into this territory, but something I’d like to examine better (or, read more about) is the fact that I don’t think people believe what they think they believe. When the animalistic brain reacts, the rational brain is a few steps behind and supplies reasons after the fact. (No, it would be tragic if my boss were to get angry at me, because…)

Getting back to the material of the chapter, the two paragraphs above are followed by the following two paragraphs:

We can question that impulese. We can disagree with it. We can override the switch, examine the threat before we act.

But this takes strength. It’s a muscle that must be developed. And muscles are developed by tension, by lifting and holding.

And, this is another thing that I think isn’t talked about enough: the importance of controlling yourself when it’s not super-important, because it will be much harder when it’s important. (For me, one example is being careful of how I speak to my kids when I don’t need to be careful about what I’m telling them, so that I have ‘muscle memory’ there for when I’m more concentrated on content than on how I say it.”)

The chapter only offers three strategies for doing this: contempt, describing things by means of their strict content, and thinking of your own problems as the problems a friend has. The rationale for this last one is that we’re more objective when thinking about our friends’ problems than when thinking about our own.

I think, if I could expand on this chapter, it would be to add priorities. Something that frustrates me is when a person complains about something in their life (the town where I live is so expensive!) but rejects all suggestions to make changes. Eventually, it usually comes down to something being more important (as long as my parents are alive, I want to live close to them). When a conversation reaches that point, I suggest “Instead of feeling sorry for yourself in such an expensive city, why not be glad that your parents are alive, and you’re happy to sacrifice having a big apartment for being close to them?”

It has been my experience that, if something is important to you, moving the ‘downsides’ of life in general into the appropriate ‘cost column’ in the accounting ledger of life makes a big difference. After all, we all think things along the lines of “there isn’t anything I wouldn’t do for goal.” That suggests, after all, that living in an expensive city is better than living in an expensive and dangerous city. You’re ahead of the game! The price could be much higher!