Prepare to act

It’s a bit funny that this is a ‘chapter’ in the book. And a whole page and a half, it’s more a segue from discussing perception to action. Because it’s so short, long excerpts would mean basically writing the whole chapter up.

Here’s the core message:

The demand on you is this: once you see the world as it is, for what it is, you must act. The proper perception–objective, rational, ambitious, clean–isolates the obstacle and exposes it for what it is.

And, that makes sense. After all, what good is seeing things for how they are if it just makes you apathetic.

I think what I like about Stoicism is that it requires action. We (I mean ‘I’) imagine a stoic person as a person who just sits there and takes whatever life dishes out, uncomplainingly. But, who needs a philosophy that reduces to “shut up and take it”?

Instead, a philosophy of “accept things for how they are, and then look at what you can do and do it.

When I’m rationalizing it in my own head, it’s like sitting down to card game every day and saying “what can I do to improve the cards I get tomorrow? Is it worth it? How can I play these cards to make the most out of today?” And then figuring out what needs to be done and doing it.

Advertisements

It grows!

Just a simple idea…

So, I invited some of the people who tried dynamic-efl.com (my worksheet making site) a while ago to return to the site and see if things appeared more streamlined, clearer. And what was the response?

“Toby, I tried to login, but I’ve forgotten my password. Doesn’t your site have one of those password-reset functions?”

Of course it doesn’t. Grr.

No problem, it should be pretty straight-forward to code and it needs to get done at some point, I suppose.

It still isn’t done.

Save the email addresses

It turns out that the way I had been creating users, I managed to accidentally forget to save their email addresses. Oops. So, even if the “email me a link to create a new password” function existed, it wouldn’t help.

I’ve fixed that.

Then, once I was working with the email addresses, it seemed logical to add them to the mailchimp list I’d been thinking about starting.

I got that done.

Of course, to avoid adding bad email addresses to the mailchimp list and getting flagged, it seemed logical to first add the addresses after they’ve been verified. But that required me to code up an email-verification system. No biggie, but that meant learning how to send email through django.

I got that done. (Interestingly, I can send it through gmail, which I find convenient.)

Since that was done, it seemed as good a time as any to add an ‘account_locked‘ flag to the Teacher model, which would throw up a message on several of the relevant pages saying “your account is locked…”

I got that done.

accountlocked

Then, it seemed ridiculous to have a ‘your account is locked’ message if the account wasn’t, actually, functionally locked. Once I dug out where exactly the downloads happened, it should be pretty simple to have it first check if the account is locked or not.

I got that done.

There still isn’t a password reset

It’s next on my list of things to do, but this sort of experience is pretty standard for me in my own coding. I think everyone imagines that ‘real coders,’ have a plan and sit down and build something logical from start to finish.

(Though there is comic evidence to suggest that isn’t true. I got this via “Coding explained in 25 profound comics,” which is worth a visit on its own.)

coding

So, perhaps this is just par the course for the coding experience. Either way, it’s part of why my next project will be to write a drop-in user management module for future django projects.

I’m enjoying this and learning to appreciate a lot about website administration. But I would not be upset if I only had to learn all this once.

If you’ll excuse me now…

…I’m off to write a password reset function.

Finding the Opportunity

Continuing my The Obstacle is the Way reading, I was glad to get into this chapter, of only because it starts with WWII history. More to the point, we’re slowly finishing the section dedicated to perception and getting ready for the section dedicated to action (which fits: as I’m ready to incorporate a bit more action in my life).

The thesis of the chapter is simple: look for opportunity in adversity. But I love the fact that it starts with Eisenhower in WWII. After describing the German Blitzkrieg and some counter-offensives made after D-Day, Ryan Holiday says this:

Striding into the conference room at headquarters in Malta, general Dwight D. Eisenhower made an announcement: He’d have no more of this quivering timidity from his deflated generals. “The present situation is to be regarded as opportunity for us and now disaster,” he commanded. “There will only be cheerful faces at this conference table.”

[…]

By allowing a forward wedge of the German army through and then attacking from the sides, the Allies encircled the enemy completely from the rear. The invincible, penetrating thrust of the German Panzers wasn’t just impotent but suicidal–a textbook example of why you never leave your flanks exposed.

Fortunately, he goes on to name some situations that are closer to home for most of us than being a five-star general in the world’s largest conflict. One of my favorites was the idea of turning a job where you’re so miserable you could quit on its head by turning the job you’d like to leave into an interpersonal laboratory until you’ve got your next job lined up.

The chapter is long and full of other examples and wisdom, but that’s the core of it: when faced with an obstacle, learn to look for what you can get out of it, since you’re going to be enduring it anyway.

As seems to be a tradition, I’ll close with the last paragraph from the chapter:

No one is talking glass-half-full-style platitudes here. this must be a complete flip. Seeing through the negative, past its underside, and into its corollary: the positive.

Living in a man’s body

The Internet is full of motivational messages saying things like “we’re all just pretending to be adult” and I have that feeling pretty often. In my case, I have the added complication of people telling me that they were intimidated by me when they first met me.

Intimidated? By me?

It always surprises me, in spite of my hearing it often. I’m such a big goofball.

But, I’m huge and bearded and look obviously like a man approaching forty. (Some would say I look older, but they’d only say it once!) And I forget that. In fact, get me on school grounds and I have to remind myself that I’m one of the adults, not one of the kids. (Ha! Teachers have to speak to me as an equal! In theory, anyway…)

Recently, though, I’ve had moments where I realized that I’m living in a man’s body. I can’t explain what exactly triggers it, but it’s generally at times when I’m in motion and I feel somehow… manlier? Not stronger, not even fitter. But whatever it is, it’s closer to ‘strong’ and ‘fit’ than it is to ‘old’ or ‘creaky.’ I’m not talking about feeling like an old man. (That I had more often when my back was giving me trouble.)

My best guess is that the plank workouts and all the burpees are giving me a degree of core strength that I didn’t have as a kid, or, apparently, in my early thirties. So, maybe it is fitness.

On the other hand, maybe I’m just developmentally slow in this as I am in so many other things and whatever this feeling is, it’s what made jocks walk around the school what that particular gait of theirs all those years ago. If I am slower, does that mean I get to die later?

And, if it is a question of fitness, I wonder if I’ll eventually find a broader link between my (hopefully) increasing fitness and the way I behave.

Mailchimp’s Subscriber Hash

I learned something today. In sitting down to finish up my mailchimp functions, I wanted to create a mailchimp_remove_teacher_from_list(listname) function and a mailchimp_blanket_unsubscibe_teacher() function. I thought that, after my previous success, it would go quickly.

I was wrong.

Over here, in the docs, there’s reference to how to delete list members, which is what I basically want to do:

client.lists.members.delete(list_id=”, subscriber_hash=”)

I knew what a list_id was, but wasn’t sure what the subscriber_hash was. After a bit of Googleing (I thought I’d have to ask mailchimp for the hash) I found this page and was able to piece it together:

In previous versions of the API, we exposed internal database IDs eid and leid for emails and list/email combinations. In API 3.0, we no longer use or expose either of these IDs. Instead, we identify your subscribers by the MD5 hash of the lowercase version of their email address so you can easily predict the API URL of a subscriber’s data.

For example, to get the MD5 hash of the email address Urist.McVankab@freddiesjokes.com, first convert the address to its lowercase version: urist.mcvankab@freddiesjokes.com. The MD5 hash of urist.mcvankab@freddiesjokes.com is 62eeb292278cc15f5817cb78f7790b08.

In short, the subscriber_hash argument is something you produce at your end and use to look a subscriber up. There’s something elegant about it — you have no business accessing the subscriber if you don’t know the email address, already — but I needed some time to get it done.

Here’s how I did it:

import hashlib # A standard library that does hashes

# The following is in .lower() case because mailchimp forms
# hashes from lowercase strings.
# The .encode() method tagged on the end encodes it as a byte literal
email = request.user.email.lower().encode(encoding='utf-8)

# This uses the hashlib library to make the hash. The .hexdigest()
# seems to be about equivalent to str() [forgive me internet!]
hash = hashlib.md5(email).hexdigest()

client.lists.members.delete(list_id=list_id, subscriber_hash=hash)

This is not a complete solution. It basically tags onto my last post. At some point, I want to compend everything I do into something more universally applicable. When I do, I have no plans to keep it secret.

Forming a running habit

After writing about how surprisingly motivational the Google Fit weekly running goals are for me, I thought it’d be nice to post an update:

Screenshot_20180121-132845

It took quite a bit of work and more than once I caught myself saying “if I don’t get a run in, I’ll have to wait a long time to push an incomplete week out the other side.” (If that phrasing makes any sense.)

The result was me having more back-to-back runs in the week: generally one 5k and a 7k, and a long run on the weekend. Maybe it’s not the structured approach to running I’d been hoping for, but it’s running.

Glory Days

I think a lot about the song “Glory Days” and of the danger of becoming a person who lives in the past. (‘A lot’ in this context means at least half a dozen times in my life.) The thing is, I used to run pretty regularly and it’s weird for me to struggle to get something done that used to be so fundamental to me.

I can rationalize that my kids are getting bigger, that I’m doing more with them, that I didn’t use to try and code a website in the same off-time that used to be just for reading and running. Nonetheless, it’s important to me that I continue to be the kind of person that I want to be, rather than assuming that having once run a marathon means I get to claim “runner” status forever.

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.