Skip to content

mostlybadknits

I’ve been knitting A LOT since January when I started. It has quickly become something that I feel deeply passionate about. As I continue to learn more and grow through my experiences so far with knitting I wanted to reflect back a little bit.

I picked up knitting in a way to fill a void I felt in myself. A lot of this stemmed from feelings of boredom, loneliness, and depression. I felt at the time that most things were meaningless and that there just wasn’t much to look forward to. I’ve always lacked confidence, but felt especially down on myself and simply not interesting to others. I’ve always heard about how knitting helps with focus, how it can be a relaxing and therapeutic activity, but never looked into it before. During a manic upswing I began researching online and looking up videos, then ran to the store to pick up my first supplies.

I felt like giving up almost immediately. When I was not able to get the motion or began making mistakes I thought that it was a bad idea. I eventually let myself make those mistakes and kept plowing ahead. I eventually got the hang of it. One of the biggest things that I still continue to learn that it is ok to fuck up, things aren’t broken because I didn’t do a few things correctly. Over the months I could see and feel the process becoming easier, or at least more familiar. I understood more what I was doing, how looping and stitching together thread in different ways can create unique fabrics.

While I still suffer from depression and have some pretty down days, I find myself knitting and wanting to accomplish that next finished object. To me there is something really empowering about creating a new object that didn’t previously exist in the world. Being able to share these experiences also has helped me to not feel so alone or isolated in the world. I have made connections with people in Chicago and all over the world and I really enjoy seeing everyone’s creativity and perspective that they bring to the craft. I began a knitting group and made and effort to set up times to meet with people, something I’d never thought I’d do. All this has led to a bit more confidence in my abilities and in myself. I have gotten a lot of feedback from people that my work is impressive given how recently I started. I’m halfway towards believing the praise, but also proud of my effort and learning how creative I can truly be

Looking forward, I know that knitting is something I’ll always keep with me from now on and am excited about all the possibilities of where I can take it. I would like to get to the point where I can write patterns for people or put them up for sale. I’d also love to begin making unique knit items to put up on a store somewhere. Right now my favorite objects to make have been cowls. My goal for myself is to make 10 unique cowls and maybe develop a pattern or two based on these designs. Hopefully, by the time winter comes around, there will be a few items in my store for sale. Right now the dream is to make this into a career and create beautiful objects for a living. For the time being, I will continue to share updates and I continue to learn and grow personally and creatively through knitting.

Digging into Python, Part 3

In my last update, I went through setting up the models for Recetario. After discussing with Steve, we decided to move on to making the views work the way we want them. This involved primarily creating forms to save recipes when a user logs in. We took an iterative approach to this by first making individual forms for RecipeIngredient, and Instruction, then figuring out how to combine them into one big form. I appreciated this approach because I got to see more how individual models are working together to achieve the end result. This step was a bit challenging and required a lot of scouring documentation to get it just right. I am really proud of being able to work through this and get to the core of what my app does which is saving a recipe. Below is the end result.

Forms

Let’s look at some code. In my last post I shared the models that I created, below I am creating form objects using Django’s generic form views. These are very helpful in that Django will generate fields based on the attributes for my objects:


#recetario/recipes/forms.py

from django.forms import ModelForm, inlineformset_factory

from .models import Recipe, Ingredient, Instruction

class RecipeForm(ModelForm):

    class Meta:
        model = Recipe
        fields = ('title', 'cuisine', 'cooking_time', 'servings')

class IngredientForm(ModelForm):

    class Meta:
        model = Ingredient
        fields = ('quantity', 'measurement', 'name')

class InstructionForm(ModelForm):

    class Meta:
        model = Instruction
        fields = ('ordinal', 'instruction_text')

IngredientFormSet =
    inlineformset_factory(Recipe, Ingredient, form = IngredientForm, extra=1)
InstructionFormSet =
    inlineformset_factory(Recipe, Instruction, form = InstructionForm, extra=1)

In the above you can see that I’m importing the ModelForm module as well as inlineformset_factory. These will help me create the forms in my view and template. First I utilize ModelForm to create form objects, in this case RecipeFormIngredientFormInstructionForm. The model gets referenced along with the fields that I want to expose. Later on in my template, these fields will show up as individual input boxes. At the very end of my code I’m creating inline formsets which are like a form object but specifically use to associate models when there is a foreign key relationship. I created a formset for both Ingredient and Instruction in this case since they both have a relationship to Recipe.

Views

The views were the more complex part of this. It took a few tries and unfortunately most of the examples I was able to find were for on foreign key relationship, but I’m working with two. Let’s take a look at the RecipeCreateview which is used when a user wants to add a completely new recipe:


#recetario/recipe/views.py

from .forms import IngredientFormSet, InstructionFormSet
from django.views.generic.edit import CreateView, UpdateView
from django.urls import reverse_lazy
from django.db import transaction

from .models import Recipe, Ingredient, Instruction

class RecipeCreate(CreateView):
    model = Recipe
    fields = ['title', 'cuisine', 'cooking_time', 'servings']

    def get_success_url(self):
        return reverse_lazy('detail', args = (self.object.id,))

    def get_context_data(self, **kwargs):
        data = super(RecipeCreate, self).get_context_data(**kwargs)
        if self.request.POST:
            data['ingredients'] =
                IngredientFormSet(self.request.POST, prefix='ingredients')
            data['instructions'] =
                InstructionFormSet(self.request.POST, prefix='instructions')
        else:
            data['ingredients'] = IngredientFormSet()
            data['instructions'] = InstructionFormSet()
        return data

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        context = self.get_context_data()
        ingredients = context['ingredients']
        instructions = context['instructions']
        with transaction.atomic():
            if ( form.is_valid() and ingredients.is_valid() and
                     instructions.is_valid() ):
                self.object = form.save()
                ingredients.instance = self.object
                instructions.instance = self.object
                ingredients.save()
                instructions.save()
        return super(RecipeCreate, self).form_valid(form)

To begin, I am using Django generic view, CreateView which is used specifically for making a form to create an object. In this case it is for creating a Recipe object, the rest of the logic is so that I can associate Ingredient and Instruction data to it. I referenced the model (Recipe) as well as the fields I want to expose below it. CreateView has methods that can be overridden. get_success_url is used so that I can give the view somewhere to go once the object is created. I am using reverse_lazy here to get the recipe detail URL after the object is created. It is my understanding this is used when the url details aren’t immediately known, as with a new object. Within get_context_data this is where I am getting information from the two formsets I created. The Ingredient and Instructionobjects along with their attributes are assigned to data here for use in saving the form. With form_valid, I am utilizing this data in order to get my list of ingredients and instructions. Here I use transaction.atomic() to set up the objects to be saved, in this case multiple ingredients and instructions, so that they can be committed to the database in a single transaction.

To utilize this view, I needed to reference it in urls.py by utilizing as_viewon the view class and passing the template that I want to use:


#recetario/recipes/urls.py

from django.conf.urls import url
from .views import RecipeCreate

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^add/$',
        RecipeCreate.as_view(template_name="recipes/recipe_edit.html"),name='add'),
    url(r'^(?P[0-9]+)/$', views.detail, name='detail'),
]

Template

Finally, in the template, I loop through the forms so that it will render the fields for the models. I have condensed the below to include only the fields for ingredients:


#recipes/templates/edit_recipe.html
{{ "{% extends 'recipes/base.html' " }}%}
{{ "{% load static " }}%}

{{ "{% block content " }}%}</pre>
<div class="col-md-4">
{{ "{% csrf_token " }}%} {{ form.as_p }} {{ ingredients.management_form }} {{ "{% for form in ingredients.forms " }}%} {{ "{% for field in form.visible_fields " }}%} {{ "{% endfor " }}%} {{ "{% endfor" }}%}
<table class="table">
<tbody>
<tr class="ingredient_formset_row">
<td>{{ "{% if forloop.first" }}%} {{ "{% for hidden in form.hidden_fields" }}%} {{ hidden }} {{ "{% endfor" }}%} {{ "{% endif" }}%} {{ field.errors.as_ul }} {{ field }}</td>
</tr>
</tbody>
</table>
... <a>Go Back</a></div>
$('.ingredient_formset_row').formset({
 addText: 'add ingredient',
 deleteText: 'remove',
 prefix: '{{ ingredients.prefix }}',
 formCssClass: 'ingredients-formset'
 });

{{ "{% endblock" }}%}

There are various things going on here. The main part of this is that form.as_p will render the main Recipe form. Further down I am looping through for form in ingredients.forms in order to get my fields for an Ingredient to render. At the very bottom, you can see some JavaScript. I utilized the django-dynamic-formset JQuery plugin in order to dynamically add more fields for adding additional ingredients. Most important to note about this is the ingredient_formset_row classname I used on each tr that will allow the rows to be grouped up and passed to the RecipeCreate view for saving the transaction.

Now I can serve up this heaping bowl of code soup in order to create tons of recipes for my app! It took some work and head scratching but I’m really happy with how this is turning out. Taking a break from all this back end work to move on to styling my templates so that they are a bit more user friendly. Stay tuned for the next update.

Digging Into Python, Part 2

A few weeks in and things are going great with the mentorship. I have met with Steve and had a couple of informative hangouts to set up and go through how my Django application will work. I have settled on a name: Recetario. Directly translated it can mean “cookbook”, but specifically a collection of recipes for a specific family or household. In other usages it can mean medical handbook or list of prescriptions. I felt like this was fitting for the intention of my app: a place for avid home cooks to jot down and store recipes they create or modify. A collection of their own personal recipes, procedures, and bits of inspiration for their creation. Apart from a listing of ingredients and instructions, my hope is that a cook will have the option to include a blog-like post with the recipe describing their motivation and thought process behind what they made. They will also be able to tag the type of cuisine if one (or multiple) apply. I’m looking forward to thinking of more features to add. As someone who plans to use this heavily, I’m pretty excited!

Mentor Meetings

Steve has been a great help these past several weeks. It has been a great experience getting all these bits of knowledge and guidance from someone who has been working in the industry for a while. There are various aspects of developing a web application that I know to do but don’t know necessarily WHY I’m doing them. It has been an eye opening experience to get a breakdown of how data structures work or how to break down the development steps into smaller more consumable pieces. I have noticed feeling less overwhelmed by the different things needed to create a web application and see know that it is totally manageable thanks to Steve’s insight.

Project Progress

At this point, I have been utilizing the Django Tutorial as a guide for the beginnings of my application. We found that the first few sections provide a good outline for some of the views and models I needed to implement for Recetario. So far, I have models and URLs set up for my recipes. What I like about Django is how easy it is to read the models and see exactly what they are doing:


#recetario/recipes/models.py
from django.db import models
from django.contrib.auth.models import User

class Recipe(models.Model):
    title = models.CharField(max_length=200)
    cuisine = models.CharField(max_length=50)
    cooking_time = models.IntegerField(blank=True, null=True)
    servings = models.IntegerField(blank=True, null=True)
    created_by = models.ForeignKey(User, related_name='recipes')

class Ingredient(models.Model):
    quantity = models.IntegerField(blank=True, null=True)
    measurement = models.CharField(max_length=50)
    name = models.CharField(max_length=100)
    recipe = models.ForeignKey(Recipe, related_name='ingredients')

class Instruction(models.Model):
    ordinal = models.IntegerField(blank=True, null=True)
    instruction_text = models.TextField(null=True)
    recipe = models.ForeignKey(Recipe, related_name='instructions')

In the above you can see my three main Recipe related models and the attributes for each. Setting up the relation between Ingredient or Instruction and Recipe felt pretty straightforward. I was somewhat surprised I was able to save a recipe with ingredients and instructions in the console right away. Getting to this point felt good as I began to see how all the other pieces will fall into place.

I am up to chapter 4 of the tutorial and currently working on user signup, login, and logout functionality. I’m really happy to say that as of today, a user is able to sign up and log into Recetario. They can’t create a great recipe yet, but that is my next step: creating recipe forms and having a saved recipe associate to the logged in user. Creating the sign up was probably my biggest challenge so far, but an enjoyable one nevertheless. I used a guide from Simple Is Better Than Complex to help with this process. I found that they have a lot of useful tidbits for working with Django on their site, even though the Django docs are my primary source since they do a great job of including everything. For my Login and Logout views, I used the Django built in authentication views. Conveniently, Django provides user authentication views, from there all I needed to do was create templates. More info can be found here

Next Steps

After I finish user authentication, I will be taking a trip to template town. I will be creating templates for recipe creation, recipe edit, recipe detail, recipes listing, and better user templates along with profile pages. For styling I will be using bootstrap so apart from Python there will be a fair deal of HTML and CSS coming up. Eventually, when I have a good deal of the basic functionality set up, I want to into setting up tests and familiarize myself with TDD. Hopefully this will lay down the groundwork for added additional features such as the text posts on recipes that I mentioned previously. I’ve got a lot cooking right now and can’t wait to see how everything comes out!

 

Digging Into Python, Part 1

As you might already know, I’m an avid cook. I love looking at a set of given ingredients and figuring out what I can make with it. It allows me to solve a problem while being creative. It is something that I can share with others and perhaps put a smile on their face. It gives me joy to come up with something different, see the end result, and hopefully make someone happy in the process.

I feel like much of what appeals to me about cooking is what draws me to programming. Being able to take my base knowledge and to build on it to improve and explore other tools and methods for creating the end result. For me it is a way of expressing myself and impacting the world around me. One of my first interests in learning to program has been to create a recipe management application to help me keep track of and take notes on dishes I make. In the process, I have become fascinated by programming languages and development. At one point I thought I would like to change careers and be a cook. What happened in the end is I have found a passion working with code and a desire to work as a web developer.

The ChiPy Mentorship Program

One of the things that I felt I lacked in my process to become a web developer is a bit of direction or answers to the question of “what’s next?” I realized after a while that what would be helpful is to have a guide, a mentor to work with to see a project to fruition as a developer would. In comes the ChiPy Mentorship Program. I heard about the program a while back after attending a couple of their meetings. At the time I wasn’t sure which language to go with as I began my learning process. Over time and after seeing friends having a great time working with Python, I decided I wanted to learn more and to work more with the language. I decided to finally take the plunge and apply. I was accepted and am very excited to be part of the process! My mentor is Steve Kain and he has been very helpful in answering my questions and providing guidance via email (I have been in Germany for the past couple of weeks). I look forward to meeting in person when I return next week.

Goals

In the past, I have focused primarily on Ruby and looking into web development utilizing Ruby on Rails. I will say my main interests have lied in full stack web development, having looked at React and Elm in the past as well. I also have fun solving puzzles and working on coding challenges such as the cryptopals challenges. I have tended to hop around from one thing to another in moments of inspiration but not leaving a project complete to a point where I would be satisfied with it. I would say this is one of my main goals with the mentorship program. Some of my other goals include:

  • A better understanding of the Python programming language
  • Learn more about data structures and working with databases
  • Become comfortable with testing a web application and TDD
  • Get exposure to how someone in the industry works and develops a solution
  • Contribute to open source projects in Python
  • Gain the experience and confidence to change to a career in development

My Project

Going back to my interest in cooking and tracking recipes, I would like to create an application that will allow a user to enter and post a recipe and save it to their “cookbook”. This is something I have played with in the past but also felt it was lacking in some ways. In talking with my mentor, it seemed like a good idea to take it one step further and to work with the data provided by the users to analyze different aspects of recipes. Of interest to me is being able to see trends in terms of the types of recipes and ingredients are being used, the cuisines that are most popular, ingredients that appear more frequently, and which ingredients are most likely to be found together. I feel like this would be a good starting off point for doing more with Python including machine learning. Perhaps a game that guesses your recipe or cuisine based on the ingredients being entered. This project will most likely be a Django application utilizing a PostgreSQL database. Over time, I will add additional features to visualize recipe data provided and display recipe trends.

I hope to get closer to my goals through this project. I look forward to further working with my mentor and becoming more of a part of the Python community as well. I’m excited to be a part of the mentorship program and look forward to honing my skills as a web developer and creating more applications that people will enjoy.