Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tut] How I Designed a Personal Portfolio Website with Django (Part 2)
1
How I Designed a Personal Portfolio Website with Django (Part 2)

5/5 – (1 vote)

We are designing a personal portfolio website using the Django web framework.

In the first part of this series, we learned how to create Django models for our database. We created an admin panel, and added ourselves as a superuser. I expect that by now you have used the admin panel to add your sample projects.

You are required to go through the first part of this series for you to follow along with us if you haven’t already done so. In this series, we will create a view function using the sample projects. By the end of this series, we will have created a fully functioning personal portfolio website.

The View Function

[Image: image-29.png]

We can choose to use class-based views or function-based views, or both to create our portfolio website.

If you use class-based views, you must subclass it with Django’s
Code:
ListView
class to list all your sample projects. For a full sample project description, you must create another class and subclass it with Django’s
Code:
DetailView
class.

For our portfolio website, we will use function-based views so that you can learn how to query our database. Open the
Code:
views.py
file and write the following code:

Code:
from django.shortcuts import render from .models import Project # Create your views here. def project_list(request): projects = Project.objects.all() context = { 'projects': projects } return render(request, 'index.html', context)

We import the
Code:
Projects
class and perform a query to retrieve all the objects in the table. This is a simple example of querying a database.

The
Code:
context
dictionary that contains the object is sent to the template file using the
Code:
render()
function. The function also renders the template,
Code:
index.html
. This tells us that all information available in the
Code:
context
dictionary will be displayed in the given template file.

This
Code:
view
function will only list all our sample projects. For a full description of the projects, we will have to create another view function.

Code:
def full_view(request, pk): project = Project.objects.get(pk=pk) context = { 'project': project } return render(request, 'full_view.html', context)

This
Code:
view
function looks similar to the previous one only that it comes with another parameter,
Code:
pk
. We perform another query to get an object based on its primary key. I will soon explain what is meant by primary key.

Template Files

[Image: image-28.png]

We have to create two template files for our view functions. Then, a
Code:
base.html
file with Bootstrap added to make it look nice. The template files will inherit everything in the
Code:
base.html
file. Copy the following code and save it inside the templates folder as
Code:
base.html
.

Code:
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container"> <a class="navbar-brand" href="{% url 'index' %}">Personal Portfolio</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <a class="nav-link" href="{% url 'index' %}">Home</a> </li> </ul> </div> </div> </nav> <div class="container"> {% block content %}{% endblock %} </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>

The
Code:
a
tag has a
Code:
{% ... %}
tag in its href attribute. This is Django’s way of linking to the
Code:
index.html
file. The
Code:
block content
and
Code:
endblock
tags inside the
Code:
div
tag is reserved for any template file inheriting from the
Code:
base.html
file.

As we will see, any template file inheriting from the
Code:
base.html
file must include such tags.

The Bootstrap files are beyond the scope of this article. Check the documentation to learn more.

Create the
Code:
index.html
file inside the template folder as indicated in the view function. Then, write the following script:

Code:
{% extends "base.html" %} {% load static %} {% block content %} <h1>Projects Completed</h1> <div class="row"> {% for project in projects %} <div class="col-md-4"> <div class="card mb-2"> <img class="card-img-top" src="{{ project.image.url }}"> <div class="card-body"> <h5 class="card-title">{{ project.title }}</h5> <p class="card-text">{{ project.description }}</p> <a href="{% url 'full_view' project.pk %}" class="btn btn-primary"> Read More </a> </div> </div> </div> {% endfor %} </div> {% endblock %}

The
Code:
index.html
file inherits the
Code:
base.html
as shown in the first line of the code. Imagine all the scripts we have to write to render hundreds or even thousands of sample projects! Once again, Django comes to the rescue with its template engine, for loops.

[Image: image-25.png]

Using the
Code:
for
loop, we loop through all the projects (no matter how many they are) passed by the context dictionary. Each iteration renders the image (using the
Code:
img
tag), the title, the description and a link to get the full description of the project.

Notice that the
Code:
a
tag is pointing to a given project represented as
Code:
project.pk
. This is the primary key passed as a parameter in the second view function. More on that soon.

Again, notice the
Code:
block content
and the
Code:
endblock
tags. Since the
Code:
index.html
extends the
Code:
base.html
file, it will only display all that is found in the file. Any addition must be written inside the
Code:
block content
and
Code:
endblock
tags. Otherwise, it won’t be displayed.

Finally, the
Code:
full_view.html
file:

Code:
{% extends "base.html" %} {% load static %} {% block content %} <h1>{{ project.title }}</h1> <div class="row"> <div class="col-md-8"> <img src="{% project.image.url %}" alt="" width="100%"> </div> <div class="col-md-4"> <h5>About the project:</h5> <p>{{ project.description }}</p> <br> <h5>Technology used:</h5> <p>{{ project.technology }}</p> </div> </div> {% endblock %}

That’s all about our template files. Notice how everything is linked to our database model as we learned in the first part of this series. We retrieve data from the database, pass them to the view function, and render them in the template files.

[Image: image-26.png]

We haven’t let Django know of an existing templates folder. Go to the
Code:
settings.py
file, under the
Code:
TEMPLATES
section. Register the
Code:
templates
folder there.

Code:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], #add these 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
Registering the URLs

[Image: image-27.png]

We need to hook up our view functions to URLs. First is the project-level URL. Open the
Code:
urls.py
in the project folder, and add these:

Code:
from django.contrib import admin from django.urls import path, include from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('', include('portfolio.urls')), ] if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

We register the file using the
Code:
include()
method. So, once we start the local server, and go to
Code:
http://127.0.0.1:8000
, we will see our home page which is the
Code:
index.html
file. Then, in the
Code:
if
statement, we tell Django where to find the user-uploaded images.

Next are the app-level URLs. Create a
Code:
urls.py
file in the
Code:
portfolio
folder.

Code:
from django.urls import path from .views import project_list, full_view urlpatterns = [ path('', project_list, name='index'), path('<int:pk>/', full_view, name='full_view'), ]

The
Code:
full_view
URL is hooked up with a primary key. It is the same primary key in the templates file and in the second view function. This is an integer representing the number of each project. For the first project you added in the previous series, the URL will be
Code:
http://127.0.0.1:8000/1

Hoping that everything is set, start the local server, and you will see everything displayed.

Conclusion

We have successfully come to the end of the second series of this project. The first series is here:

[Image: 1f4a1.png] First Part: How I Designed a Personal Portfolio Website with Django

If you encounter errors, be sure to check the full code on my GitHub page. Our app is now running in the local server. In the final series of this project, we will see how we can deploy this to a production server.
Reply

Users browsing this thread:
1 Guest(s)


Forum Jump: