Purpose: The purpose of this project is to provide a platform for displaying algorithms using a programming language. This instance of the project is called "Howpy" and it displays Python algorithms.
Target Audience: Developers, engineers, students.
Features
- Algorithm Page
- Tags (Algorithm Categories)
- Tag Page
- Admin Page
- Search Bar
Front-end: Bootstrap, HTMX
Back-end framework: Django
RDBMS: SQLite
Testing Framework: pytest
Windows
- Go to the official Python website: Python
- Download the latest version of Python for Windows by clicking on the "Download Python" button. Choose the version that is appropriate for your system (32-bit or 64-bit).
- Open the downloaded installer and follow the installation wizard. Make sure to select the option "Add Python to PATH" during the installation process.
MacOS
- Go to the official Python website: Python
- Download the latest version of Python for Windows by clicking on the "Download Python" button. Choose the version that is appropriate for your system (32-bit or 64-bit).
- Open the downloaded installer and follow the installation wizard. Make sure to select the option "Install for all users" and "Add Python to PATH" during the installation process.
Linux
- Open a terminal window.
- Use the package manager for your Linux distribution to install Python. For
example, on Ubuntu and Debian, you can use the command
sudo apt-get install python3
to install Python 3. - Verify that Python is installed by running the command
python3 --version
in the terminal. If Python is installed correctly, you should see the version number of Python that you installed.
Depending on how you want to use this project, you may want to run it locally on your machine. If so follow the steps on this section:
- Install virtualenv: Once you have installed Python, you can install virtualenv using pip. Open your terminal (Command Prompt for Windows) and type:
pip install virtualenv
MacOS & Linux
- Create a virtual environment: To create a virtual environment, go to the directory where you want to create it and run the following command:
virtualenv myenv
Here, myenv is the name of the virtual environment. You can choose any name you want.
- Activate the virtual environment: To activate the virtual environment, run the following command:
source myenv/bin/activate
Windows
On Windows, the command is slightly different:
myenv\Scripts\activate.bat
- Open the command prompt
- Navigate to the directory that contains the requirements.txt file.
- Run the following command:
pip install -r requirements.txt
You can store the SECRET_KEY by creating a .env
file. For security reason,
it is important to secure the SECRET_KEY, that's why this project does not
provide you one.
You may create a SECRET_KEY manually by following the steps:
- Open a Python shell in your Django project's root directory.
python manage.py shell
- Once in the Python shell, run the following command to import the
get_random_secret_key
function:
from django.core.management.utils import get_random_secret_key
- Then, run the following command to generate a new SECRET KEY:
get_random_secret_key()
This will return a new SECRET KEY.
- Finally, copy the new SECRET KEY and paste it into your Django project's
settings file (e.g.
settings.py
) as the value of theSECRET_KEY
variable.
For example:
SECRET_KEY = 'your_new_secret_key_here'
Save the changes to your settings.py file and exit the Python shell.
Run inside the directory containing manage.py
file:
python manage.py runserver
Prepare:
python manage.py makemigrations
Run:
python manage.py migrate
urls.py
When a user requests a particular URL from a Django web application, the web server sends the request to the Django application. The urls.py file then maps the requested URL to the appropriate view function that will handle the request and generate a response.
The urls.py file consists of a series of URL patterns. Each pattern defines a particular URL that the application should handle and maps it to a view function that generates a response for that URL.
templates/
In a Django application, views are responsible for generating dynamic content, while templates define how that content should be presented to the user. Templates allow developers to separate the presentation logic from the application logic, making it easier to maintain and update the web application.
When a view function is called, it typically renders a template to generate an HTML response. The template may include placeholders for dynamic content, such as variables or loops, which are replaced with actual values at runtime.
For a clean structure, the boilerplate .html files are separated from the app
specific components. base/
directory has the boilerplate code, whereas how/
directory contains the app code. Important notes for the base/
directory:
base.html
: in a Django project is a template file that serves as a base or parent template for other templates in the project. It typically contains the common structure and layout of the web pages, such as the HTML boilerplate, CSS and JavaScript files, and navigation menu.
When you create a new template for a specific page in your Django application, you can inherit the structure and layout from the base.html file by including the {% extends "base.html" %} template tag at the top of the file. This tells Django to use the base.html file as the parent template and to insert the content of the child template in the appropriate place in the parent template.
3-col-template.html
: adds a specific layout for a three-column web page. The
three columns are defined using Bootstrap's grid system. The layout is as
follows:
The how/
directory:
components/
: self-explanatory directory, where the small parts of the webpage
is stored, such as, the search-bar.html
, tag-cloud.html
that displays the
tags. Additionally, the splash.html
for the homepage. post-list-elements...
are used for listing posts according to the need (for search, for tag, for main page).
single.html
: is used for a single post page.
static/
directory only has a single .css
file called main.css
inside the
css/
directory. The images are also stored in here.
settings/
directory contains the base settings config and 2 extra files
called: local.py
and production.py
. You can add and alter settings as you
wish during development with local
and make your changes ready for production with
production
.
tests/
are discussed in Section 5.
templatetags/
directory there are 2 files:
tag_cloud.py
: defines a custom template tag for a Django app called "How". The purpose of this tag is to generate a tag cloud for the app using the Tag model from the third-party Django package django-taggit. The how/components/tag-cloud.html template can then be customized to display the tag cloud in the desired format.markdown_processing.py
: is another custom template tag for the same app. The purpose of this filter is to process Markdown-formatted text and convert it into HTML. The resulting HTML can then be used in the template to display the formatted text. This custom filter can be used to render user-generated content in a Django app, such as blog posts or comments, in a formatted and visually appealing way.
apps.py
file inside a Django app folder is a Python module that contains the
configuration for the app. The purpose of this file is to define the
configuration options for the app, such as the name and the default auto field
for the models in the app.
forms.py
file in the app folder defines a PostSearchForm class that inherits
from forms.Form, which means it is a regular form that is not tied to any model.
The purpose of this form is to provide a search functionality for posts. The
PostSearchForm class has a single field called q, which is a CharField that
represents the search query.
In the init method of the form, the q field is updated to include the class attribute "form-control". This attribute specifies the Bootstrap CSS class that is used to style the search box.
The PostSearchForm can be used in a Django view to handle user input when performing a search for posts. The form data can be accessed and processed in the view using the request.POST object.
models.py
file in a Django app folder defines the data models used in the app.
The purpose of this file is to define the structure and behavior of the app's data. In other words, it defines how the data is stored, retrieved, and manipulated in the app.
The models.py file defines a Post model that inherits from models.Model. The Post model represents a post that is going to display each algorithm and has fields for the post's title, subtitle, author, content, creation date, and update date.
The Post model also has a tags field that uses the TaggableManager from the django-taggit package to manage tags associated with the post.
urls.py
defines the app's URL patterns:
The first path matches the root URL. If you decided to name your website "howpy.com", this path will show that url.
path("", views.HomeView.as_view(), name="homepage"),
This path matches the post search functionality. For instance, "howpy.com/search/".
path("search/", views.PostSearchView.as_view(), name="post_search"),
This is the URL for a single algorithm post. This is the only Function-based view. Example: "howpy.com/binary-search/".
path("<slug:post>/", views.post_single, name="post_single"),
This path will give you algorithms with a specific tag. Example: "howpy.com/tag/search/".
path("tag/<slug:tag>/", views.TagListView.as_view(), name="post_by_tag"),
views.py
file:
-
HomeView: This is a class-based view that inherits from ListView. It retrieves all Post objects from the database and paginates them. The get_template_names method determines the template to be used based on whether the request is an Htmx request or not.
-
post_single: This is a function-based view that retrieves a single Post object based on the slug parameter in the URL. If the Post object is found and its status is "published", it is rendered using the "how/single.html" template along with a list of related Post objects from the same author.
-
TagListView: This is a class-based view that inherits from ListView. It retrieves all Post objects that have a particular tag specified in the URL and paginates them. The get_template_names method determines the template to be used based on whether the request is an Htmx request or not. The get_context_data method adds the tag to the context so that it can be used in the template.
-
PostSearchView: This is a class-based view that inherits from ListView. It retrieves all Post objects that have a title containing the search query specified in the URL and paginates them. The get_template_names method determines the template to be used based on whether the request is an Htmx request or not. The form_class attribute specifies the form used to process the search query.
admin.py
is used to register models with the Django admin site.
Pagination is available on every page that may reveal set of items, such as: the homepage, tagpage, searchpage.
Made using ZenFlowchart
The webpage automatically adjusts when the page shrinks, which means the layout and elements will adapt to fit smaller screen sizes. This functionality is made possible by Bootstrap's responsive design features.
Now the very cool part of this feature is that, the user has a main "code" field inside that database and that codebox is auto highlighted by "highlight.js" which is revealed at the start of the page with its own styling. If the user decided to show more code after some text explanation, they can easily do that by using the markdown code block. The same style will also be applied to that code block!
Admins and users can edit using the admin page:
To get to the admin page, first you need to create a user:
python manage.py createsuperuser
Then head to: localhost/admin
Here is all the algorithms connected to the "Search" tag:
For this project Pytest Framework is used to write tests.
Install pytest-django:
pip install pytest-django
Fake data prep using: factory_boy
How to install into your venv:
pip install factory-boy
Run:
$ pytest --cov
For more details run:
$ coverage html
To run the tests:
pytest
Note: pytestmark = pytest.mark.django_db
is a pytest marker that tells pytest
to execute the test in a Django database transaction.
test_homepage_url
: checks if the homepage URL is working correctly. It uses the Django test client to make a GET request to the homepage URL, and checks if the response status code is 200 (OK).test_post_htmx_fragment
: checks if a specific template is used for rendering a part of the homepage. It sets a header to simulate an HX-Request, then makes a GET request to the homepage URL, and checks if the expected template is used for rendering the response.
test_str_return
: checks if the str method of the HowModel returns the correct value. It uses a factory to create a HowModel instance with a specific title, then checks if the str method of the instance returns the same title.test_add_tag
: checks if adding a tag to a HowModel instance works correctly. It uses a factory to create a HowModel instance with a specific title and a tag, then checks if the number of tags associated with the instance is 1.
test_search_url
: Similar url check from 5.3.1 - test_homepage_url
Note: No need to create a new post. This check is only for making sure the correct template is returned:
test_search_htmx_fragment
: checks if a specific template is used for rendering a part of the search results. It sets a header to simulate an HX-Request, then makes a GET request to the search URL, and checks if the expected template is used for rendering the response.test_search_filter
: checks if the search functionality returns the expected results. It uses a factory to create a HowModel instance with a specific title, then searches for that title using the search URL. It checks if the instance's title is in the first result returned by the search.
test_post_single_url
: Similar url check from 5.3.1 - test_homepage_url
test_tag_url
: Similar url check from 5.3.1 - test_homepage_urltest_tag_htmx_fragment
: checks if the list of posts by tag page returns an HTMX fragment. It uses a factory to create a post instance with a tag, sets the HTTP header HTTP_HX-Request to "true", generates the URL for the list of posts by tag page using the reverse function, makes a GET request to the URL using the Django test client with the headers, and checks if the post-list-elements-tags.html template is used to render the response.test_tag_filter
: checks if the list of posts by tag page filters posts correctly. It uses a factory to create a post instance with a tag, generates the URL for the list of posts by tag page using the reverse function, makes a GET request to the URL using the Django test client, and checks if the tag in the context of the response matches the tag used in the post instance.
This version of the project has passed all the test:
- Connect the project to a PostgreSQL database.
- Deployment.
If you would like to add any extra features to the optimisation simulation, feel free to fork and create a pull request. Thank you!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
Erol Gelbul - Website
Project Link: Howpy