Including an extra button in a crispy form

I’m a big fan of using crispy forms with Django. In fact, since doing the Django girls tutorial, I don’t think I’ve made a form manually.

And, until now, I haven’t been super critical of aesthetics. Now, however, I’m updating the look of the worksheet generator and moved the login to a modal. Doing that, I thought… “Hmm, wouldn’t it be nice if the ‘reset password’ button was in a button group with the login button?

It turned out to be a bit of a challenge for me, and I couldn’t find anything on it specifically, so here’s what I did:

loginModal
The goal — Doesn’t that look nice?
oldLogin
What I had before. Too much screen real estate.

Functionally, it’s not a big deal, except that I’m using button groups more and more in the site in general, and why not use one here?

However, the old way I was rendering the form wouldn’t work. The crispy FormHelper object rendered the form so completely that I couldn’t get at the login button, much less wrap it together in in a button group.

Of course it was possible, but the solution turned out being telling crispy forms to let me create my own form tag:

# forms.py

class LoginForm(forms.Form):
    username = forms.CharField(label='Username:', max_length=100)
    password = forms.CharField(label='Password:', widget=forms.PasswordInput(), max_length=100)

    def __init__(self, *args, **kwargs):
        super(LoginForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False

The self.helper.form_tag = False bit turns off the form field.

Then, in the template rendering the form, I had to make some changes. To be honest, I should say that I took the easy way by having crispy forms render the form tag, and then copied that.

template
WordPress didn’t want to display this, so this seemed the easiest thing to do.

Initially, I did this without adding type=”button” to the second button in the group and, for reasons I don’t understand, both buttons functioned at a submit button. Obviously, that wasn’t ideal, and adding the extra type=”button” made it work.

It’s worth pointing out that I never (or, not yet) removed the old …/login.html page that rendered the form before. Nothing links to it, so I doubt anyone will ever hit it. But, if they did, the form would be broken because I didn’t update that template to include a form tag.

Advertisements

Some Coding Goals

Setting my own goals

It was not a super-productive summer for me, coding-wise. However, as I get away from ‘vacation-mode’ and back to ‘real life,’ in addition to improving as a teacher (more on that in another post), I want to improve as a coder.

Here’s the thing: There are a million ways to improve as a coder. And, I’m sticking to the ‘hobby coder’ label, so I don’t feel compelled to even try an know everything about coding, or even a specialization under the ‘coding’ header.

My task: is to be able to do the things I want to do, nothing more, but also nothing less. (To be honest, it will always be something less — I have an active imagination for what’s possible.) Now though, what I’d like to do is to make the things I make seem more like a ‘web application.’

What’s a web application?

The short answer is: it doesn’t matter. As a language teacher, I’m a big fan of the idea that words only mean what you and the person you’re speaking to understand. And, when I say web application, I mean it in contrast to a ‘web page.’

To me, a web page is static: Some guy (me) writes a bunch of stuff, takes a bunch of photos, makes a video, maybe, and puts it online. The web page is your chance to interact with what I’ve made, on my terms.

A web application, on the other hand, is magic. Sure, some guy (me) made it, but it’s a tool that I get to pick up and use how it best fits in my life. A web application is my chance to take something algorithmic I’ve made, and let you run with it.

Don’t you already do that?

To be fair, yes, I think that Dynamic EFL already qualifies as a web application. But, it doesn’t feel like it yet. It feels like a series of web pages that the user moves through, ending with a PDF, the most static document format of all time.

It’ll always end with a PDF, because the whole idea is that it’s supposed to be hidden. The learner isn’t supposed to know you used a ‘tool.’ The learner might hear the word ‘tool’ and think ‘shortcut.’ The whole idea is that the learner thinks “wow, the teacher invested time in me. I’m getting my money’s worth.”

So, maintaining the PDF format at the end, the way I see to make it feel more like an application is to make better use of transitions between pages and modals (the ‘foreground’ pages that open ‘over’ the rest of the page — logins are often done in modals).

The best web applications — gmail, Google calendar — don’t feel like pages at all. It feels like you enter an address into your browser, and then you interact with an application. That’s what I’d like to do.

A good argument for it

First, I rationalize it would help make what I do clear in comparison to what teachers are already paying for — static resources presented on web pages.

Second, it’s a sales point. Done smartly, the transitions and ‘web app experience’ simply feels more ‘modern.’ It helps to explain why I’m taking money.

A roadmap

I don’t have a roadmap in the traditional sense. That’s where this little goal-setting exercise breaks down. I’ve started experimenting and I’m finding it pretty hard. I have used JavaScript to dynamically change content on a web page, but I haven’t made the animation part of that work, and I haven’t been able to load a new django view into one <div> of a page.

So, I guess I have my work cut out for me.

The plan, now, is to leave Dynamic EFL how it is as I begin attracting beta testers. Instead, I have a new project idea that I want to start from scratch as a web application (using Google APIs, no less!) (more information on the actual project in a future post). Then, when that’s working, I’ll be able to apply lessons learned to Dynamic EFL.

Wish me luck.

I paid Google €11.04 to get four people to look at my site

A brief foray into AdWords

Part of the appeal of the whole “let me start a website and try to monetize it” thing is getting a look behind the scene at how these financial mechanisms of the Internet work. My life has exposed my quite a lot to the technical mechanisms of the Internet, but I only vaguely knew that “advertising is big business.”

So, having declared the Dynamic-EFL.com website to be officially finished (I now have a list of changes I want to make, so … whatever), I rationalized it was time to try and get some users who I don’t know.

I opened an account with Google’s AdWords.

The process of opening the account was painless, and making the ad was just like the YouTube tutorials I watched. However, it wasn’t easy because I tend to be a long-form writer, not the kind of guy who gets things said in six words. (Have you noticed that about me?)

Still, I got the add made, I was happy. This is how it looked:

ad1

(Fun fact: having that inline here still makes some part of my brain crazy, as I can feel myself trying not to read it.)

Advertising is expensive

I tried searches with the keywords I decided to market against. There were no ads shown to me (thinking my adblocking software might be the reason, it tried it in incognito mode and Firefox), it seemed reasonable to think that I wasn’t competing against many people in Google’s complex ad-auctioning system.

I set the price to €6/day for three days. It seemed like money I could afford, and it was hard to know what to expect.

 

ad2
My brief ad campaign

You can see how things went. Two dollars per click seems like a lot of money. Especially considering, when it was finished, I checked and there were no new user accounts, meaning people came, looked, and were not interested.

What I think I’ve learned

So, what have I learned? Well, I re-examined the landing page and have decided that it needs to be polished. I’d like it to reflect me as a person doing a thing more than looking like some impersonal internet software. After all, I’m a likable guy, right?

Further, I think it needs to more quickly move into the information of what can this site do for you? Because, humility aside, I think I have a compelling argument for the site being really useful.

My mistake, I think, was that, although I know I need the opinions of people who don’t know me, I didn’t put myself in the headspace of someone coming to the site.

The next campaign

I don’t know when it will be. I mean, I have some work to get done, some behind-the-scenes things I’m still working on (I’d like to be able to add resources, outside the worksheet creation process) and I still teach English more or less full time.

Still, when I come back to this, I’m going to target all of Germany, rather than my region, and use more limited keywords, rationalizing that people who come to the site looking for EFL vocab worksheets are more likely to be interested in what I have to offer than people who want EFL grammar worksheets (which my site does not create).

I’ll keep you posted.

New Projects

A project is finished

I’m planning to wind down the “actively developing” part of the worksheet generator app this week. It’s weird to think that I will then (well, really, already do now) have a project that is finished.

It is my first finished project.

But, that leaves me wondering what I’m going to be devoting my energies towards. I really enjoyed working towards something, and I’ve been wondering what to get at. There are, of course, a few candidates:

User administration

Originally, the next thing I thought I would be tackling would be creating some Model objects and views for user administration in Django. The logic is simple: I’ve been creating a disorganized hack of these things as I realize I need them. Wouldn’t it be better to have something unified?

Further, I’ve never created an app to be reused in Django. I know it can be done, and I’m certainly smart enough, so why not focus on that? I was thinking that it could incorporate the following, at least:

  • Integrating that wonderful “signup with Google” and “login with Google” functionality that I like in other sites
  • Support for beta testers and normal users
  • Payment integration, as well as support for “you haven’t paid” account locking and “your account expires on” account management.
  • Tools to see how many users are regularly using a website
  • Tools to automatically notify inactive account owners of impending deletion, and then, of course, to automatically delete said accounts.
  • Arbitrary numbers of user properties, as well as the ability for the administrator to sort users by those properties and to send mass emails. (Meaning: the ability to send an email to all the beta testers in Germany, for example)

However, I’m finding that, as I wind down work the worksheet generator (and look forward to spending no small amount of energy creating resources for it to use), I’m not very excited about tackling that. Though, logically, user management would be something I’d use before tackling the fantasy pilgrimage.

Fantasy Pilgrimage

Something I’ve thought about for a while, it remains in that golden sweet spot where “project I think people would use” and “project I think I can accomplish” overlap. The idea is simple: integrate with the Google Fit API to allow a user to set a start and finish point for a “fantasy pilgrimage” and then show on a map how far they would have progressed towards that destination, if all of the movement captured by Google Fit (or whatever app is integrating with it) were dedicated towards that.

In short: if all of my runs were strung together in a long line (rather than being circles that always end back where they started), how close would I be to the city of Rome?

It would have the advantage of being a usable web application that would give me some hands-on API experience, but it does seem to require the user management, and I just don’t seem too excited about that, for whatever reason.

But, I could move away from coding and try focusing on writing for a time. That’s the next candidate project.

The heartbreaking truth behind Destiny 2

This is a simple writing project that I keep thinking about whenever I play Destiny 2. I don’t play often (Sundays, with my brother), but it’s the only video game I do play. Back when we played Halo, I tried my hand at fan fiction where the Halo world intersected with the world you and I know. (My brother couldn’t play because he had to go to a wedding, so, of course, I wrote a story of him being at a wedding when a drop ship began disgorgin aliens and he alone was able to kill them all.)

The thing is, Destiny 2 doesn’t have really strong characters that I want to incorporate into fan fiction. Instead, we keep noticing details about the game that we love, and wondering how the developers came to settle on them. I’d like to write up those fake stories. (Including a cast of completely fictional programmers and their internal feud with the people in human resources).

It would be a change, but I don’t know that I’d be as proud of what I built as I am of the worksheet generator.

That brings me to the idea of creating an app.

ESL Detective game

Pirating parts of the idea of a boardgame that my kids play, I had a great idea for a mobile-device-based listening game for ESL students. The idea is this: with a very simple menu, students have to play the role of detectives solving a robbery. As they pass the device around, each person takes turns making decisions, but has to consult the group (sparking, I hope, conversation).

There’s nothing to watch, but everything you learn is played via audio. Like most teachers I know, I have good bluetooth speakers that everyone in the classroom could hear at once. That means everyone learns everything simultaneously, and that there would be paper on the table on which to record the things we learned.

Basically, as you moved through the story, you would learn things like:

  • Susan is very short
  • Edgar speaks German
  • The thief was very tall
  • Paula has short, grey hair

And, students would have to record these things on “suspect cards.” Eventually, as more is learned about each suspect, as well as about the thief in general, the class should be able to successfully accuse one in-game player.

It seems like it would generate conversation, practice listening, and be a change from normal classroom activities. So, of course I’m in favor of it.

I like the idea so much that I’ve started watching YouTube live-coding videos of people making apps with Flutter (which promises to make it possible to create apps for both android and iOS), but I’ve had trouble installing Flutter myself. (It doesn’t seem to find components that I think I’ve installed.)

Still, this is the one I’m most excited about, and it seems like it would be pretty straight-forward if I could get flutter working:

  • Plot out the story
  • Assign a few friends to read for me
  • Put the app together in a series of button interfaces
  • Test it in a classroom

It’d let me try creating an app, uploading things to the various play stores, and it would be useful to people outside Germany (unlike the worksheet generator, at the moment).

But… for all that to work, I need to get Flutter working.

Picture Matching!

 

picture_matching
A picture matching activity!

I didn’t plan to add images to the worksheet generator, yet. I just wanted to wrap up the interface and include images on the list of things that would be included in a 2.0 update. After all, there are other things that are really pulling at my attention now.

But then…
I found out that I’ll be teaching a beginning English group soon, and I knew that something I wish I had available would be picture-based activities. After all, things like definitions and gapfill exercises require a certain level of English knowledge before they’re helpful. And, though I’m ready to push my students, that seemed unnecessary.

As it stood, the only thing the worksheet generator would have done for a beginning group is create translation matching exercises, and manage classroom vocab lists. (But even the vocab lists would include definitions that would be impossible for the students to read.

Pictures were the way to go, and they’d been planned, anyway…

It was a bit hurried
Fortunately for me, I’d been poking around in the code, slowly getting the interface and behavior to where I wanted it to be. That meant that I’d already had the days-long process of asking myself “how did I manage that?” and “why is this here?” behind me.

Adding images went surprisingly quickly, though I did run into trouble with PNG files that had a transparency set. (They printed as solid black in PDFs, no help at all.) The internet had a solution, of course, and I quickly changed the way images were uploaded to automatically account for that.

Later, I realized that I could have made the images behave more like other resources (each teacher could add his/her own, there could be regional ones) and I’d still like to do that, but I’m still moving forward. There have to be some features to implement the next time I visit this project.

So, I moved from adding pictures and making a memory into creating the exercises.

Formatting the picture matching exercises was a bit harder. They had to look good (to me) and be compact enough that they could be the first page of a multi-page worksheet without breaking across two pages in an awkward way. (Don’t you hate that?) And, of course, they couldn’t be too small or you wouldn’t be able to see what the images were.

Worksheet progression needed fixing
The way the whole thing is supposed to work, nothing comes onto the second page of a worksheet without having been on the first page of the previous worksheet. The whole idea is to ‘automate’ reviewing the vocabulary for the students, right?

But, some words just can’t be part of a picture-matching activity. What’s a good image for ‘name’ or ‘industrial?’ So, picture-matching activities have to exist outside the whole system of progression, which was doable (and skipping code is certainly easier than creating new code) but it required a certain degree of concentration.

It’s not finished, yet
I’m not using this code in ‘production,’ yet because of one simple thing: after adding a bunch of images to the system, my existing groups would suddenly have a lot of picture matching activities with vocabulary stretching back to September of last year. One review activity seems reasonable, but after that the activities have to feature relatively recent vocabulary.

The solution for that is to make a tool that will mark vocabulary as ‘finished’ with the picture matching activities. The idea is that I’d be able to go into a group’s settings, and say “mark all the vocabulary from before January of this year as finished” and the system wouldn’t use them in new worksheets.

It should be straightforward, but I haven’t found the time to do it, yet. I want to, before I put a last few finishing touches on the interface and then start soliciting beta users (again).

Wish me luck.

 

Picture Memory

memory

Adding images to dynamic-efl.com was something I wanted to take care of in a ‘version 2.0’ or some other, later ‘new and improved’ update to the site. There are a lot of small things I want to clean up before soliciting users again.

However, I recently found out that I’ll be teaching a beginner’s class (the last ‘beginners’ I taught are now A2 and don’t really need pictures) and I figured that I’d better get the image activities working. After all, I’m the guy who beta-tests everything, and this seemed like an ideal opportunity to beta-test.

With that in mind, I’d like to announce that two of my groups will be playing picture memory tomorrow. (And, sadly, they probably won’t even appreciate that I’m excited about even having the activity to do.)

I got the basics done pretty quickly over two or three days. And, while there are still things to get done (right now users can create ‘translation memory’ or ‘picture memory,’ why not make a mixed mode that uses pictures where available and translations where they aren’t?) I’m back to focusing on ‘cleaning up’ the site to start asking people to try it.

Soon, I hope, I can report that I’m taking the next step.

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.