My 2021 Devember Project - Create a Blog CMS with Flask

I don’t know if this is allowed, but I want to finish my project from last year. Last year, I had no idea what I was doing, but my goal was to figure it out. I figured I wouldn’t finish it last year, but I wanted to participate in Devember for the sake of participating and just making something. Really, it was more about self-improvement than the prizes. Looking back at my Raspberry Pi / Linux journey in 2016, I had a lot of a similar challenges to overcome. Many times it was frustrating because I didn’t know what I was doing; so as a result, my progress was painstakingly slow and cumbersome.

That being said, my project is a web app written in Python using the Flask web framework. I’ve learned a lot about Flask over the past year, so I think I will be able to finish it. The web app is going to be a blog. I know that there are tons of blog CMS’s out there, but my goal isn’t to reinvent the wheel. Rather it is to give myself a Python project to write to improve my programming skills and development methodology.

5 Likes

@CodeDragon57 Have you decided all the details of what your tech stack is going to be? What database are you going to use? Is your frontend going to be built up with Jinja templating or do you plan to do something else?

I’m interested in other people’s Devember projects because I plan to work on my own this year and I sorta wanna understand what approaches others are taking to their projects.

Yeah, definitely. As long as you’re working on something!

I am choosing my stack based upon what works well with Flask. Since Flask depends on Jinja2, Werkzeug, and Click; these are libraries that I am using for my Flask app. The only outside libraries I am using are Flask-SQLAlchemy and Markdown. Flask-SQLAlchemy is an Object Relational Mapper that makes it easy to integrate your code and database together. A major advantage of SQLAlchemy is that it can be used with SQLite3, MySQL, or PostgreSQL. So for development, to make my life easier, I am using SQLite3; but in production I’ll probably switch over to PostgreSQL. My use of the Markdown library is probably fairly obvious, but I haven’t even started on that part of the app. Ultimately, I want the blog CMS to store the individual entries externally rather than in the database. The database itself will actually house metadata about each entry instead. I think that this will give me more flexibility and also more data protection. For example, here is myModels.py file:

from datetime import datetime
from flask_sqlalchemy import SQLAlchemy

# Create an instance of the SQLAlchemy class called db
db = SQLAlchemy()

# Each Class represents a table within the database

# The Author table contains login information and meta information about each other
class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100), unique=True, nullable=False)
    passwd_hash = db.Column(db.String(100), unique=True, nullable=False)
    first_name = db.Column(db.String(50), unique=False, nullable=False)
    last_name = db.Column(db.String(50), unique=False, nullable=False)
    admin = db.Column(db.Boolean(), default=False)
    entries = db.relationship('Entry', foreign_keys='entry.id', backref='entries', lazy=True)

    def __repr__(self):
        return '<Author %r>' % self.username


# The Entry table only contains metadata about each post.
# f"{DATA_DIRECTORY} 
class Entry(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(35), nullable=False)
    genre = db.Column(db.String(25), nullable=False)
    content_path = db.Column(db.String(150), nullable=False)
    date_created = db.Column(db.DateTime(timezone=True), default=datetime.utcnow())
    author_id = db.Column(db.Integer, db.ForeignKey('author.id'))

    def __repr__(self):
        return '<Entry %r>' % self.title

    # Note: Entries will be stored and accessed at
    # f"{DATA_DIRECTORY}/{self.genre}/{self.title}'

"""
I learned about Normalization in class, 
so I am honestly worried about whether
or not my data is normalized. If it isn't please
tell me. Thanks
"""

The idea is to have entries organized neatly in a single data directory for easy backups. Inside the data directory, there will be more directories that categorize each item by genres, and finally in each genre will be yet more directories - one for each entry. Inside an entry directory there will be HTML files or something and images relevant to the entry if any. Each HTML file represents a page of the post like the pages of an ebook. My blog isn’t really a conventional blog, and I really don’t like calling it a blog. It’s really an outlet for me to post stories. I am a huge bookworm, and a pretty good writer according to my Freshman comp professor. Even in high school I liked to do a lot of creative writing projects. Now that I am out I don’t get that opportunity anymore, so I am making an opportunity for myself.

I know this last part is more than what you asked, but I felt it important to specify that my database is only going to contain metadata. It will not contain the data itself.

P.S, I am also using Python’s TOML library since my application’s config file is loaded from a TOML file.

3 Likes

So I’ve learned something. Writing this program in Flask and SQLAlchemy isn’t as fun as regular programming. I fell in love with programming because of mathematical algorithms - which is ironic considering my checkered relationship with math. There is no math here. It’s all honestly a bunch of method calls.

At this point, it is a legacy misconception that programming and math are intrinsically related skills.

This used to be the case back in the days when only scientists had computers, and used them to accelerate the math that what previously done by hand. This lasted for quite a while, resulting in that still lingering misconception.

But that hasn’t been the case for many decades now. Today computes are quite literally everywhere, used and abused for an increasing amount of purposes.

Consider that for the bulk of everything that computers added to their list of applications doesn’t even rely on any sort of complex math - multimedia, graphics, even machine learning - it all relies on basic arithmetic operations - just doing them in the billions. It is a very useful, but tiny, and rather simple subset of all that math is. It takes a 3rd grade math foundation to be able to effortlessly learn math for multimedia and graphics in like a couple of weeks.

No, it is not about math, all you really need to be a good programmer is basic conceptual knowledge of simple arithmetic. The deeper you get into math tends to actually impede the type of creativity that makes a good programmer - the ability to design, to structure, to build simple things out into functional process systems.

What makes a good programmer is ultimately LOGIC. Math is a rather small subset of it. It is not math, but logic that is the language of the universe. It takes logic to recognize, understand and solve a problem. You put math and algorithms together, but it is logic that designs algorithms, math is just a formulation of it. In fact, putting too much emphasis on math develops a rather lopsided form of logical thinking, which explains why most programming mathematicians don’t really do all that much with programming, they work on niche problems, rather than creating amazing new things.

And of course, the deeper you go into purpose specific solutions, the easier it is to do the things they do, but also they are entirely worthless outside of that usage context. If you want to exercise more of your logical thought, you can always go into something more lower level and less restrictive that offers you creative freedom.

Okay, for a little context. I’ve been doing a lot of discrete math homework here lately. Discrete Math is largely about logic. So when I wrote the term “mathematical algorithms”, this is where I was coming from. I think though, that perhaps I am not applying the same mindset to my Flask project that I’ve done with previous programs or in Discrete Math.

Okay, so I’ve been trying to think of a way to word this, but I think I’ve finally figured it out. How can I keep my unfamiliarity with the Flask API from interfering with my logic? This is the first time I’ve ever tried to use someone else’s framework for an application.

Have you tried a glance at the documentation? Usually there is a good overview of the options you have, and from then on you just use your logic to combine and extend them.

There is a common issue with people expecting to find the doExactlyWhatIneed(magic args) function.

Your logic flows through your options, it is not a straight line between intent and result. It has to step on things that are actually there. Very often, you might find dead ends and will need to find workarounds.

My personal experience from running my own logic into dead ends in frameworks, due to bugs or design limitations, has taught me to always keep external dependencies to a minimum. My core logic has to be all pure, free of any external API calls, all 3rd party library usage must always be peripheral - this way it doesn’t get in the way conceptually, and it makes it also quite easy to port to another lib.

Yeah. I’ve been using the Flask documentation heavily. And I am starting to think that I’ve been leaning on it too heavily. I’ve honestly been trying to model the login system after the tutorial’s login system. But all the stuff that Flask offers is a bit overwhelming.

That’s why I said “overview”. I didn’t say “go through the whole thing”. You need a coarser grain. In this case, having done more than what I said does not amount to having done it and then some…

You don’t learn frameworks by reading them as books. You read the overview, then you go into details only when you need to, for the use case you need it.

I see that the Quickstart section of the Flask documentation is basically the overview I am talking about. It gives you a good idea on the bulk of what you can and will be doing with it, and naturally, if you need customization beyond the trivial examples it provides, you go to the documentation for that particular thing.

To learn takes time and practice to memorize. You will naturally memorize the most commonly used stuff, it is ok to look up everything else each time, even in the industry, the expected output rate is low enough, giving you ample time to research stuff on demand.

I didn’t believe it when someone told it to me back when I started, until it happened to me exactly as I was told - it takes 3 years to become OK, 5 years to become good, and 10 years to become great. You may learn to sing the entire documentation by hearth and in tune, but there is no substitute to experience.

You have to be persistent, and if that doesn’t give results, maybe put some scrutiny on your methodology. Don’t expect the documentation to have all the answers, all it has is dots that you have to connect.

1 Like

Thanks for that. That sorta gave me the kick in the butt that I needed. Anyway, I was able to make substantial progress in like a day. I made a video of part of it working, but I don’t know how to upload it to the forum.

create a channel on some platform somewhere, like YT for example. unless its really small (in size), then you can put it in GH repo ( myDevember2021 ), or create a secondary repo ( myDevember2021-theVideo ), or use the GH-docs folder to make it available to a web browser.

BTW a name or description instead of “My 2021 Devember Project” might go a long way to understanding your own project.

I’m glad you did, because it gave me a chance to find another use for a (possible) BubbleFS that (in this case) would contain a “wrapper” around your complete directory structure, allowing one endpoint to be linked to multiple genre, while allowing more entrypoint’s than just “genre”

So thanks to your explanation, I now have 3 possible uses for (the currently hypothetical) BubbleFS

So I am cutting it down to the wire here, but my project is almost done. I don’t think I am going to win any prizes anyway, but my goal is to learn something while also creating a use for my domain at https://linuxdragon.dev

And boy howdy have I learned a lot. The latest push to Github is outdated as of this post, but I have yet to push my work - and it is going to be a huge update to the repo.

Hey so right on the heels of my Devember project (now technically complete minus CSS styling), I am participating in MIT Battlecode https://battlecode.org. It looks really fun this year.

1 Like