Studying vs. Learning

I came across a thread on /r/LearnPython a few weeks ago that summed up my experience with Python. The thread was the typical “I’m learning Python, but I feel stuck and I’m not learning”. Someone replied with encouragement, and pointed out that studying Python is very different than learning Python and how it works.

I can relate. It’s been just over a year since I started down this path and almost two years (where does the time go!) since I decided I wanted to learn Python.

I started by buying a couple of books. That didn’t work for me at all – I don’t learn from reading and trying to apply the exercises. The Python for Everybody specialization at Coursera that I took last summer, with the video lectures and online exercises was the first time I felt I was actually learning. But in actuality, I was still studying. The same with the Python Jumpstart course. Having gone through Python for Entrepreneurs, and finally starting to apply what I’ve studied, I feel that I’m now learning.

Even though a large chunk of what I’m building in the NFLPool web app using Pyramid is copying and pasting from Python for Entrepreneurs, I’m starting to feel confident that the concepts are sticking.

As of Wednesday, I had a couple of the bigger components working. Users can visit the website and register, and the site recognizes when they’re logged in and out. I also created an admin panel that creates a new install and imports the NFL team information into one of the database table. This information is static and never needs to be updated. It uses a GET / POST / REDIRECT pattern and then redirects to the next page to insert all of the active NFL players for the new season.

Yesterday I sat down and needed to change this. Mr. Kennedy is always talking about the GET / POST / REDIRECT pattern , and though I thought I understood it, when I built the first one above, it took me a bit to get the redirect working. But I needed to change it so the next redirect would create a form to update the database for a new season and then redirect to import the active players.

I sat down and wrote the template and HTML code for the page, then wrote the controller for the GET / POST / REDIRECT routes, and then the service to interact with the database. I did this for the first time without referencing the training materials! The sense of accomplishment was huge. Not only was I writing code for the Pyramid web framework correctly, I was using requests and JSON to get the data MySportsFeed, manipulate it, and then put it in the database.

Of course, later yesterday, I wanted to write it so when you updated to a new season, it took a variable from a form rather than be hardcoded, and was stuck for two hours when it work. But it turned out it wasn’t the Python code – after my wife helped me for an hour, we realized it was the HTML form that had the error. So that was big, too – the Python code was right! It was just my lack of knowledge around HTML causing the latest headache.

Now I have two big things for the weekend:

  1. Re-write all of the requests so they’re not hardcoded and pass the season attribute from the database to the request so every year I don’t have to update the code.
  2. Right the controller and service for players to make their picks. This one is going to be tough – I’ll need to grab the user ID from their logged in session (which I’m not 100% sure how to do yet) and then grab a lot of stuff from the database and put it into a dropdown box for selection – which I also have no idea how to do. I feel ok that I know how to do the query, but putting the query results into a dropdown box is scary.

Either way, for the first time, I’m applying what I’ve studied – and I finally feel that after over a year I’m actually learning Python.

NFLPool Progress: 8/1/2017

I took the week off from work to see how much progress I could make on NFLPool this week (and to get some stuff done around the house, but really, for NFLPool). I told myself I’d blog my progress every day and here it is Wednesday already.

In my last blog post, I noted how I was going to have to move back to SQLite for the database. Over the weekend I ripped out most of the MongoDB code and started laying the groundwork for SQLite. The first thing I did Monday morning was going back through the SQLAlchemy chapter of Python for Entrepreneurs to learn how to properly set up classes in Pyramid using SQLAlchemy to create all the database tables. Back when I was building the first prototype for NFLPool, I had written a Python program that set up used the sqlite module and created all of the tables and then populated the database with the NFL teams information (Team ID, name of the team, city, etc.) and also populated the Active Players table with a list of all players in the NFL. This was all done using the SQL language – which I do not enjoy at all.

I won’t pretend that I still understand object oriented programming, especially the use of classes in Python. I’ve come a long way and I understand the concept of how a class creates an instance of the object, but putting it into practice is still a challenge. Using the Python for Entrepreneurs course examples, I was able to take my data model, write the SQLAlchemy classes, and get the database created.

One of the nice things about the course is that it does touch on how to create an index in a table and making foreign keys to join two tables together, which I’ll need. If I don’t ever migrate to MongoDB, I may want to just use MySQL, which technically, I believe, doesn’t support foreign keys. So I’m not sure how portable this code will be, but like everything else I’m doing, Future Paul can deal with that.

Monday afternoon was all about re-learning the Pyramid concepts of routes, abstracting the database in the viewmodel, and then writing the code in the controller. That took longer than I thought it would. The concepts are originally taught very early in the course, but then you go a long time without touching that part of the code. After all of the hands-on work, I think I’ve got a handle on it. I do like how Mr. Kennedy has you separate the viewmodel from the controller – he makes a point in the training you don’t have to do it – but if you don’t, I don’t see how troubleshooting your code could be easy.

That night, I took the kids to the community center where they swim while I sit and watch them in the viewing area with my laptop and use the free WiFi. I pulled my code down from Github and then swore in my head for an hour when Pyramid would error out and wouldn’t create the database. Which it just should – when Pyramid starts, it looks and if the database doesn’t exist, it looks at the classes I’ve written in SQLAlchemy in my /data directory and creates the database and those tables from the classes. But it wouldn’t. It wasn’t until I was back home later that night that I had an epiphany, created the /db directory manually where the database should live, re-started Pyramid, and voila, my database was there. Now I don’t have to worry about not being portable and can code both at home and on the go.

Tuesday was all about what happens when you first install and setup NFLPool. Since I’m using SQLite, I want to make it easy for me and other to set it up. The easiest thing to do with SQLite is when you need to make changes to the database during development to just delete it and have the app re-create it. Since I’m constantly developing it, I just wanted it easy to re-create and in the case my code is ever used by anyone (it’s on Github, licensed under the GPLv3), it’s better to do this now than try to add this functionality later. (Why GPLv3 and not MIT? My code is so bad being so new to programming, that I want any changes to the source available so I can look at it and learn. Though I’ll probably make it MIT at some point because no one is ever going to use my code, to be honest. Though I could digress on a business model I have brewing…)

Well, the first step in NFLPool is to set up the tables with the team information, which is static – it’s just the team name, the abbreviation, the city, and the division and conference they play in. So I thought I’d make an admin webpage where the admin goes, presses a button, and that database table is populated. It would then re-direct to the next page to create a new season. You enter “2017” for example, and it would reach out to MySportsFeeds and pull all active players in the NFL. Now you’re ready for the players in NFLPool to make their picks.

Sounds easy, and then the next thing I knew it was 7pm and I was asking my wife for help. Using the original prototype, which had working Python code to populate the team info table and the active players, I couldn’t get the team info to populate. I thought this tweet summed it up pretty well:

Turns out I had a return statement at the end of my loop that shouldn’t be there. Took her five minutes – sometimes you just need another set of eyes. The loop itself is terrible code, but it’s working.

The other problem I had was with the template and styling of the Admin page to create the first table. The Chameleon template engine kept crashing on me in my browser – again, she looked at it, pointed out I was missing two divs to close it, and that was working. Coding is fun, I keep telling myself.

After the table populates, which works now, I still don’t have the re-direct working correctly either. I can’t get it to re-direct to a new page – I’m pretty sure it’s how I have the POST and the routes set up in the admin controller. I can get it to redirect back to the same page though after it populates the first table. I need to keep pushing forward as vacation is almost half over, so there’s another thing on the TODO list for Future Paul.

Today is about doing some code cleanup. This includes adding an admin or settings table in the database to store the current season. From there, I can set up a baseurl function that connects to MySportsFeeds and using the season variable above to create the URL needed to get the JSON data needed for that entire season. This way, at the beginning of each season, you don’t have to go in and manually change all this code. I’m hopeful to get this done this morning, but will probably get stuck, but who knows. From there, I have two major pieces to get done:

  1. Start the code to allow players to make their season picks. From the Active Players table, query the database and get a list of all players in a certain position. Then create a form or Javascript to store those in a drop down box. I have no idea how to make a drop down box.

  2. Account creation / login / authentication. The course has a great chapter on this, I’m not too worried about it.

If I can get these done, then players can create their accounts and start making their picks (though I have to store those picks in the database, but I’m feeling confident). In theory, I could launch next week, which is tight. And then the hard part starts: writing all the code to calculate the scores for each player.

Until then, I’ll just keep telling myself this:

Back to SQLite for NFLPool

I’ve had to throw in the towel on MongoDB and move back to SQLite for the datastore. For now.

I was successful in being able to call an API, take the JSON object from the API, and store that JSON in MongoDB as a collection. But I what really wanted was to store that JSON object as an EmbeddedDocument within a collection.

My original goal was to stick JSON objects into MongoDB and then query against that. I envisioned two collections, one for Users (registration) and the second for the NFL data, called Stats. Stats would have looked like:

Stats

—Season

—2016 (and one document this fall for 2017, one per year moving forward)

—Player Picks (Each User’s picks for the 2016 season)

–Week (1 – 17, 17 different Documents, each embedded with:)

—Individual Player Stats

—Division Standings, etc

I read dozens of articles on StackOverflow, Reddit, and others. I tried to code it as an EmbeddedDocument, DynamicFields, and more. Everything ended up as an error. I needed to put the JSON object as an embedded document in each Week document above. But I couldn’t figure out.

I’m out of time. I’ve procrastinated enough and I really want to get a prototype and / or minimum viable product up in the next two weeks. There are two things that are a must:

  1. User registration and login system
  2. User pick submission

The first one shouldn’t be a problem as how to build a secure user registration system with passlib is included in the Python for Entrepreneurs course. The second requirements shouldn’t be that hard, but every time I think that, I’m proven wrong.

When I was using SQLite previously, I had all the code written to create the tables and do the initial import of the data needed. I’ll need to re-use some of that code and port the rest from the pure SQL statements I was using to SQLAlchemy.

I was also stuck on what the weekly results table should look like. My wife had some thoughts on it that thoroughly confused me, but when we chatted about it yesterday, neither of us could remember why she was recommending the design she did. I gave it some more thought and I think I have a database model that will work. I’ve written all the class files I need for SQLAlchemy and have taken the week off work to see how much progress I can make.

The big think I need to do is figure out the Javascript within Pyramid and the Chameleon template language to allow a user to make their picks. I have a table that stores all the active players in the NFL with columns for their first name, last name, player ID, team ID and position. I will need to create drop down boxes allowing them to choose, for example, which quarterback they think will lead the league in passing. That part of I have no idea how to do…. yet.

But one thing at a time.

NFLPool Prototyping with MongoDB

Yesterday was a good day.

With the static pages for nflpool.xyz complete, I started thinking about the dynamic pages. These are going to require access to the database and I’ll be using MongoDB. I had started the MongoDB course from Talk Python, but put that aside to go back to the Python for Entrepreneurs course to get the site up using Pyramid.

I took a step back and did some brainstorming about the data model I’ll need for the database. I grabbed a spare whiteboard and started scribbling.

nflpool whiteboard brainstorming

Using MongoDB requires you to shift your mental model from traditional SQL and joining tables as MongoDB doesn’t technically do joins. I needed to think about what a collection looks like and do I embed more documents within a collection or have multiple collections?

I went back through the MongoDB course chapter on Modeling and Document Design. Mr. Kennedy has you ask 6 questions when it comes to embed or not embed:

  1. Is the embedded data wanted 80% of the time?
  2. How often do you want the embedded data without the containing document?
  3. Is the embedded data a bounded set?
  4. Is that bound small?
  5. How varied are your queries?
  6. Is this an integration DB or an application DB?

The answers that I came up (that are hopefully correct):

  1. Yes
  2. Almost always
  3. I’m such a newbie I don’t even know what a bounded set is.
  4. I think so.
  5. Not very.
  6. This is an application database.

Keeping in mind that MongoDB has a 16MB limit, which sounds a lot smaller than it really is as I’m only dealing with text and not embedding images or anything like that, the answer is to embed everything.

The next step was to go back through the MySportsFeeds APIs and figure out which ones I’ll be using. In no particular order:

  • Cumulative Player Stats (for individual player picks, such as the passing yards leader)
  • Roster Players (used for the league players to pick who the individual player leaders are)
  • Playoff Team Standings (Used for wildcard playoff picks)
  • Division Team Standings (Used for which teams will finish 1st, 2nd and last in each division)
  • Conference Team Standings (Used for the team that will lead its conference in points for as well as some team data, such as the team name, abbreviation, etc.)

I may want the full game schedule at some point, but that’s a bigger challenge than I need to get into right now.

I ended up deciding that I need two collections within my database:

  • Users: this will store the registration information for each player in the league and be used for logging into the website
  • Seasons: Here I will embed all of the data for each season of play and have a document for 2016, 2017, etc. Within each year I’ll embed the league player’s picks and then a document for each of the APIs above that has 17 embeds – one for each week of the NFL season. One of my goals is that player can go back to 2016 and look at their progress for each week and see their point total versus the rest of the league. Getting ahead of myself, this will not be available in MLBPool2 (if and when I ever build that) as that will only be a real time look at your score and then show the final year results.

So it may look something like this, with two collections: Users and Seasons:

nflpooldatabase
–Users (embed a document for each player in the league in this collection)
–Seasons (Example: “2016” – and then embed the following in the 2016 document:)

  • 2016
    • player-picks
      • 1 document for each player’s picks
    • Week 1 through 17 (17 documents total) with the NFL stats for that week embedded here:
      • AFC East
      • 11 more documents for division picks like AFC East above
      • 6 documents for individual leaders
      • Tiebreaker
      • Documents for Points For, Wildcard, etc.
  • 2017
    • player-picks
    • Weeks 1-17 (One document per week)
      • NFL stats with all the embedded documents above

Now it was time to re-build the functions to go get the data from the MySportsFeeds API. I had this working in the last iteration of the app when I was using SQLite, but I’ve never used MongoDB before. Over my lunch hour, I successfully prototyped taking one query and putting it into my MongoDB running locally.

The feeling of euphoria in successfully using MongoDB was huge.

Last night after work, I took the next step. Keeping in mind the size limitation of MongoDB, I could take steps to filter the API calls, especially for cumulative stats. I only need a few key stats for a subset of all players in the NFL. For example, I just need passing yards for quarterbacks. The MySportsFeeds API provides a ton of stats for every player – such as fumbles, passes over 20 yards, QB Rating, completions, and defensive stats (even though they’re an offensive player).

Thankfully, Brad Barkhouse of MySportsFeeds is always available in the MSF Slack channel. I couldn’t figure out how to build a filter for just certain positions and a specific stat. (It turns out it’s just an & sign). So if I just want sacks for defensive players, it looks like this:

https://api.mysportsfeeds.com/v1.1/pull/nfl/2016-2017-regular/cumulative_player_stats.json?position=LB,SS,DT,DE,CB,FS,SS&playerstats=Sacks

So my task for the weekend is to figure out if I want to just embed a document for each individual category or one document with all of the cumulative stats and then just build queries for each category I care about (sacks, interceptions, passing yards, etc.)

I probably should just focus on the next phase of the Python for Entrepreneurs training though, and get the user login and authentication built and then go through the Albums part of the training, which I’ll mimic for the the league players to submit their picks. I’m running out of time as I really have only a few weeks before I need the player picks to be submitted before the start of the season.

Prioritizing is fun. But I’m so happy with some of the breakthroughs and progress and not trying to think of all the challenges ahead and just take it one step at a time.

Python for Entrepeneurs Progress

I sat down excited at dinner last night excited to share with my wife the two things I learned in my Talk Python course yesterday. The first was learning the basics of CSS, something I’ve avoided for years. I’m not going to even pretend I understand CSS, but it’s a base knowledge to work with and there is still a whole chapter of applied front-end frameworks, so I’m sure there will be more on CSS.

The second was a cache-busting technique, making it easy to both develop a website and see the changes right away without having to clear the browser cache and great for users that they’ll see the updates in production when it happens.

As I follow along in the Python for Entrepreneurs class, I’m trying something different this time. Rather than code along with the examples and do the examples as Mr. Kennedy does them, I’m trying to build nflpool.xyz using similar code as to what is is in the training. There has been a couple gotchas doing it this way, as you’ll start a chapter doing something one way and then learn a different and better way to do it. Overall, I kind of like doing it the way I’m doing it as the hands-on applications is one of the ways I learn best.

Unfortunately, the cache-busting code broke Pyramid and I got a myriad of errors in my Chameleon templates. I didn’t realize this until after I had started the routing section of the training and then lost an hour or two trying to trouble shoot the cache-busting. I finally gave up and ripped out cache-busting code from the templates and everything is working again. Well, working without the cache-busting code.

As I worked on the routing section, I’m not going to say I truly understand it yet, but it started to click for me why using a framework like Pyramid using Python makes sense. When I’ve mentioned to a couple of people that I’m going to use Python and Pyramid to build a site, I’m usually asked why I just wouldn’t use Javascript like everyone else these days. For me, focusing on one language at a time and not trying to learn too much is key. I’m pretty sure that I could do everything I want to do with nflpool in Javascript (including both the game calculations and website), but Python’s readability and reputation for being a good language to start with really appeals to me. So why wouldn’t I build it in Python? It gives me more hands-on experience with the language, which I need, and I can include the code needed for the scoring right into the application and don’t have to build two things – the game scoring and a website.

I still have a lot to get through this week. I need to finish the applied web development including forms (yay! Maybe I will have the ability to take user picks up by next month. Now, don’t get ahead of myself…); then front-end frameworks with CSS and Bootstrap; the biggest of them all – databases (more on that in a second); as well as account management; and finally, deployment. I skimmed the deployment chapter Sunday night – lots of good stuff (even if they use an Ubuntu VPS in the training) and I’m excited to give Ansible a chance.

One of the nice things about the trainings from Talk Python is that Michael Kennedy offers office hours for a Q&A section if there is something you’re stuck on. The next one is tomorrow, which is perfect. I’m going to see if I can solve my cache-busting problem, and if not, maybe ask for help. I also want to ask him his thoughts on using MongoDB instead of SQLite after taking his MongoDB training last week, while Python for Entrepreneurs uses SQLite.

I’m really enjoying the class and glad I’m making time for it. I don’t know if I’m going to have a skeleton up by the end of the weekend or not, but it’s coming along.