Seite wählen

Below I describe the second week of my #100DaysOfCode challenge.
In the opening blogpost you can find out more about my Why, my goals and the rules which I set for myself.
Or find the collection of all my posts related to the #100DaysOfCode challenge.

ModelForm in practice | Day 027 (2022-02-02)

  • quick test: change CharField of contactDetails to EmailField
  • refactor/simplify createAd() method in view to fit ModelForm approach
  • add README.md to document documentation, general workflows and rules for project
  • merge ModelForm branch to master and to createAd
  • create a short How to create a ModelForm in practice?

How to create a ModelForm in practice?

  • presuming you’ve prepared the urlpattern in urls.py (of prject and app) correctly
  1. define a models.Model class in models.py
class Ad(models.Model):
    """
    This is a basic Ad with the most general information people may need/give.

    Individual needs, puposes and goals of people who post ads may differ.
    But this class should cover all basic information which would otherwise cause repetition in classes which inherit from this Ads()-class.
    """
    def __str__(self) -> str:
    return self.projectTitle

    projectTitle = models.CharField(max_length=100)
    creatorName = models.CharField(max_length=50)
    projectDescription = models.TextField(max_length=1500)
    contactDetails = models.CharField(max_length=300)
    pubDate = models.DateTimeField('publication date (of ad)', auto_now_add=True, blank=True)
    projectStartDate = models.DateField('project started (date)', blank=True)
  1. create a ModelForm in forms.py
  • to define form appearence
from .models import Ad
from django.forms import DateInput, ModelForm

class createAdForm(ModelForm):
    class Meta:
        model = Ad
        fields = ['projectTitle',
        'creatorName',
        'projectDescription',
        'contactDetails',
        'projectStartDate']
        widgets = {
        'projectStartDate': DateInput(attrs={'type': 'date'}),
        }
  1. create a view method in views.py
  • to handle the processing of the form data
def createAd(request):
    """
    This view method enables to publish own individual ads on the page.
    """
    # if POST request: process form data
    if request.method == 'POST':
        # create form instance + populate it with request data
        form = createAdForm(request.POST)
        # check if it's valid
        if form.is_valid():
            # process form.cleaned_data as required
            newAd = form.save()
            # redirect to new URL:
            return HttpResponseRedirect(reverse(viewname='codermatch:adDetail', args=(newAd.id,)))
    # if it's a GET request: show the unpopulated form
    elif request.method == 'GET':
        form = createAdForm()
    # if it's neither a POST, nor a GET request: send back to index page
    else:
        raise Http404('Only GET and POST requests are allowed')

    return render(request=request, template_name='codermatch/createAd.html', context={'form': form})

quick learning:

If you create model instances to save them in your database using ModelForm, you don’t need to assign all the fields of the model instance one by one.
But you can save them automatically (using the shortcut) by saving the form data to a variable for a new model object: newAd = form.save()

What you don’t need to do (compared to a normal Form):
if form.is_valid():
   # process form.cleaned_data as required
   newAd = Ad(projectTitle=form.cleaned_data['projectTitle'],
   creatorName=form.cleaned_data['creatorName'],
   projectDescription=form.cleaned_data['projectDescription'],
   contactDetails=form.cleaned_data['contactDetails'],
   projectStartDate=form.cleaned_data['projectStartDate'])
   newAd.save()

Validation on a ModelForm

  1. validate Form
  1. Form.cleaned_data() gives Python representation of user’s Form input (Accessing „clean“ data)
  2. Form.is_valid() returns a boolean: data in bound Form instance valid or not?
  3. validate model instance (=objects)
  • several validation steps involved, which can be adjusted (Model.clean_fields(), Model.clean(), Model.validate_unique() -> performed automatically when using Model.full_clean()`)
  • in ModelForm: validation steps usually done automatically when using Form.is_valid() (see above)
  • exception: may use Model.full_clean() for validation error handling or when excluding certain fields

ModelForm: creation and validation (summary)

  • create urlpattern, model, form and view
  • Form.is_valid() to make sure, you got all your data correctly from the form on the frontend
  • Form.cleaned_data() to access form data like a Python dictionary
  • error messages will be given automatically when calling the Form.save() method

Wireframes: first approach | Day 028 (2022-02-03)

  • scibble wannabe wireframes (at least start some basic visualization)
  • take notes on target groups, needs, potential monetization

Throwbacks: 🤔Thoughts and ❤️Feelings

  • feeling high pressure, uncertaintly and unability to develop such a huge project on my own or to manage a team or to build a community which develops such an app – to say nothing about all the work of creating marketing strategies, bring the app to market…😫
    • having huge doubts about the outcome and the possibility of success
    • feels like impossible to be successful with the creation, marketing and maintenance of that huge project😩
    • feeling exhausted and like making no progress
  • feeling like getting stuck in thinking processes unability to come up with good design suggestions (don’t feel competent enough to design a good user experience or user journey or even some basic wireframe-like order of objects on pages😵)
    • feels like making no (or at least to little) progess on real project and then even getting stuck in planning😩

Wireframe: digitalize🤖 | Day 029 (2022-02-04)

I’ve scribbled wireframes for the main page and the landing page of CoderMatching.
The idea was to try motivating people to engage with the wireframes and to add their own ideas – or at least to comment on it… which didn’t really happen.😑

WirFrame CoderMatching
First wireframe I’ve ever built – for the main page of the CoderMatching web app

Django Forum: Trust Level, Ad Gallery and Commuity💡| Day 030 (2022-02-05)

I’ve designed two wireframe sketches for the ad gallery.
I highly appreciate your feedback! Feel free to comment and add your own ideas!🤗

wireframe sketch for add gallery
This was my prefered sketch for the ad gallery – at that time😉

Classifieds: Communalities shared between different types

Besides I’ve noted down several assumptions about communalities, which should be shared between the different types of classifieds (in my opinion).

minimal commonalities all classifieds must share

  • must offer something
  • must have needs (based on certain goal / intention)

Django Forum: Trust Level Promotion🎉

That day I’ve discovered the email which said that I was promoted within the Django Forum.🥳
This made me really happy although it wasn’t a hard or even a planned achievement but rather a nice surprise.😁
It felt like really becoming more of a part in the community however.😊

I’ve read the blogpost about trust levels in Discourse on their blog.
Since I really like the idea of trust levels I was thinking whether it’s possible to implement something like this in the classifieds community of my CoderMatching app at some time in the future, too.🤔💡

Django Forum Trust Level Promotion
Email: Announcement of trust level promotion in Django forum🤗

MVP: Minimum Viable Product – release it to go on🚀| Day 031 (2022-02-06)

Besides I’ve created another wireframe for the landing page by merging the main page and the ad gallery together.
After reading several blogposts by Pieter Levels‘ (a great idol for me), I’ve realized that I probably should try to break my idea down into the simplest functional version.
Hereby I could build a minimum viable product (MVP) to test the demand for my CoderMatching app as early as possible.
After doing so I have several oppportunities:

  • leave it as it is and not giving a thought to it anymore (maybe hope that the traffic raises for some unexpected reason)
  • use it as portfolio project (to improve my reputation in Django (fullstack) development)
    • to find a job in Django development eventually
    • to have a reference which I could use to gain clients as a freelancer
  • improve it
    • add features
      • based on user feedback
      • based on own ideas
      • based on learning topics (e.g. APIs, web3, …)
    • pretty up appearance
    • build a community around it
    • make it open source
    • monetize it
  • do applied market analysis / research (in a real world environment, using a real project) – case study
    • test different approaches to increase traffic
    • scale it
  • maintain it as a hobby project (and focus on other topics/projects)
Wireframe Landing Page
Landing page: merging ideas for main page and add gallery

Classifieds creation form and detail view: wireframes | Day 032 (2022-02-07)

That day I’ve added two more wireframes.
One is a form which people can use to create classified ads.
The other one represents the detail view of the created and published classifieds on the CoderMatching platform.

Ad creation form
Form which people can use to create classified ads on CoderMatching
Ad detail wireframe
Detail page: representing a classifieds ad created and published the CoderMatching platform

Errors, issues, questions and solutions😖😊😌 | Day 033 (2022-02-08)

That one was obviously a busy day.😣

  • create wireframe for contribution page (rather trivial; just including hypothetical texts, which may describe how to help developing CoderMatching and another one for companies people who want to make direct money using the classifieds app)
  • plan project steps in jira (using backlog)
  • publish blog post about thoughts on static files, stylesheets and .gitignore🥳🤩

Stylesheets in Django: CSS for the frontend

  • try to implement a stylesheet in project
    • failed at first but solved the issues later

Django and Stylesheets: Implementation

projectDirectory/templates/base.html

<!-- Template inheritance based on
https://docs.djangoproject.com/en/4.0/ref/templates/builtins/#extends
https://docs.djangoproject.com/en/4.0/ref/templates/language/#template-inheritance
https://docs.djangoproject.com/en/4.0/howto/overriding-templates/#how-to-override-templates

https://learndjango.com/tutorials/template-structure    -> either use the app or the project level approach (recommendation: project level)
( https://stackoverflow.com/questions/16899917/django-template-inheritance-how-many-levels-and-what-page-to-render/#answer-16900872 )

-->

{% load static %}

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="A simple HTML5 Template for new projects.">
        <meta name="author" content="SitePoint">
        <title>{% block title %}CoderMatching - Build a team for your coding projects, gather experience and to START developing real world applications{% endblock title %}</title>
        <link rel="stylesheet" type="text/css" href="{% static '/codermatch/style.css' %}">
    </head>
    <body>
        <header>
        {% block header %}
        <nav>
        </nav>
        <div>
            <a href="{% url 'codermatch:index' %}"><img src="{% static '/codermatch/images/Logo_CoderMatching.png' %}" alt="CoderMatching Logo" width="200"></a>
            <p>
                Find collaboration for coding projects<br>
                build teams with complementing skills<br>
                👩‍👩‍👧 👨‍👨‍👦‍👦
            </p>
            <a href="{% url 'codermatch:createAd' %}">create ad</a>
        </div>
        {% endblock header %}
        </header>
        <main>
        {% block howTo %}
        <h2>How to find contribution on CoderMatching?</h2>
        <img src="{% static '/codermatch/images/22-02-08_How_to_CoderMatching.png' %}" alt="How to CoderMatching">
        {% endblock howTo %}
        {% block main %}
        {% endblock main %}
        </main>
        <footer>
        {% block footer %}
        {% endblock footer %}
        </footer>
        {% block scripts %}    
        <script src="js/script.js"></script>
        {% endblock scripts %}    
    </body>
</html>

projectDirectory/static/codermatch/style.css

/*--- base.html ---*/
body {
    text-align: center;
}

images

  • projectDirectory\static\codermatch\images\Logo_CoderMatching.png
  • projectDirectory\static\codermatch\images\22-02-08_How_to_CoderMatching.png

CSS in Stylesheet and some images: handsome web app in Django🥰

Here you can see the result of the first implementation very basic CSS.
However I like it so far.🤗

Landing Page in app
Landing Page: First approach for a somewhat handsome appearence of the CoderMatching classifieds platform🤗

TypeError: fromisoformat: argument must be str

When I tried to apply my migrations using py manage.py migrations, I encountered a TypeError: fromisoformat: argument must be str.
You may anticipate: We didn’t become friends.🤦‍♂️

I had a really hard time figuring out how to solve it.
But thanks to Adam Johnson🙏, I solved it – two days(!!) later😫 – by editing my previous migrations.

Adam also pointed out that I was having two more issues:

  • One was concerning the expirationDate property of my Ad model (and partially caused the TypeError).
  • The other issue (mysql.W002) was related to a database warning which occured when I was calling py manage.py migrate:
(venv) PS C:\Users\Name\codingprojects\CoderMatching\codermatching> py manage.py migrate  
System check identified some issues:

WARNINGS:
?: (mysql.W002) MariaDB Strict Mode is not set for database connection 'default'
        HINT: MariaDB's Strict Mode fixes many data integrity problems in MariaDB, such as data truncation upon insertion, by escalating warnings into errors. It is strongly recommended you activate it. See: https://docs.djangoproject.com/en/4.0/ref/databases/#mysql-sql-mode

Adam enabled and guided me to solve all the issues.
I’ll just give a quick overview of the solution here and describe them more detailed in the blog post of day 35 (week 6).

  1. mysql.W002: fix database warning

I’ve basically fixed that one by applying the hints from the link to the Django documentation in the WARNING (see above) – adding the following OPTIONS part to DATABASES in the settings.py file of my Django project:

DATABASES = {
    'default': {
        ...
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        }
    }
}
  1. Callable Default: Fix issue in expirationTime property of Ad model

solution:

class Ad(models.Model):
    ...
    def in30Days():
        return timezone.now() + datetime.timedelta(days=30)
    ...
    expirationTime = models.DateTimeField('expiration time (of ad)', default=in30Days)

Jira: Prepare bug fixes + Celebration🥳 | Day 034 (2022-02-09)

After spending a lot of time figuring out my bugs and describing them on the Forum, I’ve taken the time to read Adams replies on my thread in the Django forum.🙏
I’ve jumped at the chance to become friends with Jira (after our diffucult first encounter in week two and after I felt like getting stuck while using it in week three).
Using the Jira backlog I’ve prepared to fix the bug, which I had encountered the day before and also the ones which Adam pointed out.

Writing the summary of that day, I just realize that I didn’t really work on the #100DaysOfCode – hence the CoderMatching project.
But I’ve written a blogpost about celebration, goals, execution and persistance🥳, which was very important for myself.
And it partly explains why the #100DaysOfCode challenge wasn’t specifially in the focus that day.

What I’ve learned and accomplished this week – retrospective summary

I’ve learned and done several things this week:

  • learned and used Jira effectively👍
  • fixed several huge bugs (maybe just huge for me…)
  • got promoted in the Django Forum
  • celebrated accomplishments🎉
  • connected to and got help from some very great people!🙏
  • created some basic MVP wireframes for the CoderMatching platform
  • started to apply wireframe designs by implementing some basic styling in the real app
  • learned a lot about marketing and online businesses
  • learned how to create a ModelForm in Django
  • write and publish 4(!!!) blog posts🚀

That’s really a lot.
And it’s really encouraging for me to see that only a few days ago I’ve been struggling with the basics of form creation in Django.
And now I’ve already created several wireframes for an MVP.
Of course it’s still a long way to go until I can deploy the app and really share them and receive feedback and eventually carry off the laurels.
But the past week I’ve really spend huge amounts of time on topics related to the app.
I became evermore desperate every single day on a variety of thoughts and doubts about the whole programming, my career and the competition.
But in the end it’s really relieving to see the progress in hindsight.

Thanks again to all the people who support me!💚

How to go on?

In the subsequent blogpost about the following week of my #100DaysOfCode challenge you can read how I really continued my journey.
Or find the collection of all my posts related to the #100DaysOfCode challenge.

Besides you are very welcome to follow my daily progress on Twitter.

Taking up the #100DaysOfCode challenge too?

Are you also working on the #100DaysOfCode challenge?
Are you planning to take up the challenge in the future or did you already do it in the past?
What are your personal challenges on the way?