diff --git a/python-oop/README.md b/python-oop/README.md new file mode 100644 index 0000000000..5248955c1a --- /dev/null +++ b/python-oop/README.md @@ -0,0 +1,3 @@ +# Object-Oriented Programming (OOP) in Python 3 + +This folder provides the code examples for the Real Python tutorial [Object-Oriented Programming (OOP) in Python 3](https://realpython.com/object-oriented-programming-oop-in-python-3/). diff --git a/python-oop/cars.py b/python-oop/cars.py new file mode 100644 index 0000000000..62f75bbd5c --- /dev/null +++ b/python-oop/cars.py @@ -0,0 +1,14 @@ +class Car: + def __init__(self, color, mileage): + self.color = color + self.mileage = mileage + + def __str__(self): + return f"The {self.color} car has {self.mileage:,} miles" + + +blue_car = Car(color="blue", mileage=20_000) +red_car = Car(color="red", mileage=30_000) + +for car in (blue_car, red_car): + print(car) diff --git a/python-oop/dog.py b/python-oop/dog.py new file mode 100644 index 0000000000..e11a45a322 --- /dev/null +++ b/python-oop/dog.py @@ -0,0 +1,12 @@ +class Dog: + species = "Canis familiaris" + + def __init__(self, name, age): + self.name = name + self.age = age + + def __str__(self): + return f"{self.name} is {self.age} years old" + + def speak(self, sound): + return f"{self.name} says {sound}" diff --git a/python-oop/dogbreeds.py b/python-oop/dogbreeds.py new file mode 100644 index 0000000000..3ff89b47cb --- /dev/null +++ b/python-oop/dogbreeds.py @@ -0,0 +1,25 @@ +class Dog: + species = "Canis familiaris" + + def __init__(self, name, age): + self.name = name + self.age = age + + def __str__(self): + return f"{self.name} is {self.age} years old" + + def speak(self, sound): + return f"{self.name} barks: {sound}" + + +class JackRussellTerrier(Dog): + def speak(self, sound="Arf"): + return super().speak(sound) + + +class Dachshund(Dog): + pass + + +class Bulldog(Dog): + pass diff --git a/python-oop/retriever.py b/python-oop/retriever.py new file mode 100644 index 0000000000..1d08f677fa --- /dev/null +++ b/python-oop/retriever.py @@ -0,0 +1,17 @@ +class Dog: + species = "Canis familiaris" + + def __init__(self, name, age): + self.name = name + self.age = age + + def __str__(self): + return f"{self.name} is {self.age} years old" + + def speak(self, sound): + return f"{self.name} says {sound}" + + +class GoldenRetriever(Dog): + def speak(self, sound="Bark"): + return super().speak(sound) diff --git a/python-oop/starfleet_list.py b/python-oop/starfleet_list.py new file mode 100644 index 0000000000..a1fd78714a --- /dev/null +++ b/python-oop/starfleet_list.py @@ -0,0 +1,5 @@ +# Starfleet employees as a list + +kirk = ["James Kirk", 34, "Captain", 2265] +spock = ["Spock", 35, "Science Officer", 2254] +mccoy = ["Leonard McCoy", "Chief Medical Officer", 2266] diff --git a/python-oop/starfleet_objects.py b/python-oop/starfleet_objects.py new file mode 100644 index 0000000000..1fe1014a48 --- /dev/null +++ b/python-oop/starfleet_objects.py @@ -0,0 +1,14 @@ +# Starfleet employees as objects + + +class Employee: + def __init__(self, name, age, position, year_started): + self.name = name + self.age = age + self.position = position + self.year_started = year_started + + +kirk = Employee("James Kirk", 34, "Captain", 2265) +spock = Employee("Spock", 35, "Science Officer", 2254) +mccoy = Employee("Leonard McCoy", 137, "Chief Medical Officer", 2266) diff --git a/python-qr-code/README.md b/python-qr-code/README.md new file mode 100644 index 0000000000..3cdfe7624c --- /dev/null +++ b/python-qr-code/README.md @@ -0,0 +1,10 @@ +# Generate Beautiful QR Codes With Python + +Supporting code for the Real Python tutorial [Generate Beautiful QR Codes With Python](https://realpython.com/python-generate-qr-code/). + +To run the code in this tutorial, you should have `segno`, `pillow`, and `qrcode-artistic` installed in your environment. +You can install with the command below: + +```console +$ python -m pip install segno pillow qrcode-artistic +``` diff --git a/python-qr-code/scripts/animated_qrcode.py b/python-qr-code/scripts/animated_qrcode.py new file mode 100644 index 0000000000..d64acb6ba2 --- /dev/null +++ b/python-qr-code/scripts/animated_qrcode.py @@ -0,0 +1,11 @@ +import segno +from urllib.request import urlopen + +slts_qrcode = segno.make_qr("https://www.youtube.com/watch?v=hTWKbfoikeg") +nirvana_url = urlopen("https://media.giphy.com/media/LpwBqCorPvZC0/giphy.gif") +slts_qrcode.to_artistic( + background=nirvana_url, + target="animated_qrcode.gif", + light="blue", + scale=5, +) diff --git a/python-qr-code/scripts/basic_qrcode.py b/python-qr-code/scripts/basic_qrcode.py new file mode 100644 index 0000000000..900c21df42 --- /dev/null +++ b/python-qr-code/scripts/basic_qrcode.py @@ -0,0 +1,4 @@ +import segno + +qrcode = segno.make_qr("Hello, World") +qrcode.save("basic_qrcode.png") diff --git a/python-qr-code/scripts/borderless_qrcode.py b/python-qr-code/scripts/borderless_qrcode.py new file mode 100644 index 0000000000..b377bc560a --- /dev/null +++ b/python-qr-code/scripts/borderless_qrcode.py @@ -0,0 +1,4 @@ +import segno + +qrcode = segno.make_qr("Hello, World") +qrcode.save("borderless_qrcode.png", scale=5, border=0) diff --git a/python-qr-code/scripts/darkblue_qrcode.py b/python-qr-code/scripts/darkblue_qrcode.py new file mode 100644 index 0000000000..4fa5a5cdd1 --- /dev/null +++ b/python-qr-code/scripts/darkblue_qrcode.py @@ -0,0 +1,11 @@ +import segno + +qrcode = segno.make_qr("Hello, World") + +# Without changing the color of the quiet zone +qrcode.save("darkblue_qrcode.png", scale=5, dark="darkblue") + +# With quiet zone +qrcode.save( + "darkblue_qrcode.png", scale=5, dark="darkblue", quiet_zone="maroon" +) diff --git a/python-qr-code/scripts/formatted_rotated_qrcode.py b/python-qr-code/scripts/formatted_rotated_qrcode.py new file mode 100644 index 0000000000..c75c7ccc31 --- /dev/null +++ b/python-qr-code/scripts/formatted_rotated_qrcode.py @@ -0,0 +1,8 @@ +import segno + +qrcode = segno.make_qr("Hello, World") + +qrcode_rotated = qrcode.to_pil( + scale=5, light="lightblue", dark="green" +).rotate(45, expand=True) +qrcode_rotated.save("formatted_rotated_qrcode.png") diff --git a/python-qr-code/scripts/green_datamodules_qrcode.py b/python-qr-code/scripts/green_datamodules_qrcode.py new file mode 100644 index 0000000000..49ce58e140 --- /dev/null +++ b/python-qr-code/scripts/green_datamodules_qrcode.py @@ -0,0 +1,22 @@ +import segno + +qrcode = segno.make_qr("Hello, World") + +# Changing the color of only the dark data modules +qrcode.save( + "green_datadark_qrcode.png", + scale=5, + light="lightblue", + dark="darkblue", + data_dark="green", +) + +# Changing the color of the dark and light data modules +qrcode.save( + "green_datamodules_qrcode.png", + scale=5, + light="lightblue", + dark="darkblue", + data_dark="green", + data_light="lightgreen", +) diff --git a/python-qr-code/scripts/lightblue_qrcode.py b/python-qr-code/scripts/lightblue_qrcode.py new file mode 100644 index 0000000000..032336e148 --- /dev/null +++ b/python-qr-code/scripts/lightblue_qrcode.py @@ -0,0 +1,4 @@ +import segno + +qrcode = segno.make_qr("Hello, World") +qrcode.save("lightblue_qrcode.png", light="lightblue", scale=5) diff --git a/python-qr-code/scripts/rotated_qrcode.py b/python-qr-code/scripts/rotated_qrcode.py new file mode 100644 index 0000000000..4b9613a663 --- /dev/null +++ b/python-qr-code/scripts/rotated_qrcode.py @@ -0,0 +1,11 @@ +import segno + +qrcode = segno.make_qr("Hello, World") + +# Rotated QR code but truncated +qrcode_rotated = qrcode.to_pil().rotate(45) +qrcode_rotated.save("rotated_qrcode.png") + +# Setting expand to True +qrcode_rotated = qrcode.to_pil().rotate(45, expand=True) +qrcode_rotated.save("rotated_qrcode.png") diff --git a/python-qr-code/scripts/scaled_qrcode.py b/python-qr-code/scripts/scaled_qrcode.py new file mode 100644 index 0000000000..913b2597ba --- /dev/null +++ b/python-qr-code/scripts/scaled_qrcode.py @@ -0,0 +1,4 @@ +import segno + +qrcode = segno.make_qr("Hello, World") +qrcode.save("scaled_qrcode.png", scale=2) diff --git a/python-qr-code/scripts/wide_border_qrcode.py b/python-qr-code/scripts/wide_border_qrcode.py new file mode 100644 index 0000000000..e4333b99b3 --- /dev/null +++ b/python-qr-code/scripts/wide_border_qrcode.py @@ -0,0 +1,4 @@ +import segno + +qrcode = segno.make_qr("Hello, World") +qrcode.save("wide_border_qrcode.png", scale=5, border=10) diff --git a/rp-portfolio/README.md b/rp-portfolio/README.md new file mode 100644 index 0000000000..5fe29e8d7f --- /dev/null +++ b/rp-portfolio/README.md @@ -0,0 +1,44 @@ +# Get Started With Django: Build a Portfolio App + +Follow the [step-by-step instructions](https://realpython.com/get-started-with-django-1/) on Real Python to build your own portfolio project with Django. + +## Images + +You can find the example images for the projects in the [uploads/project_images](uploads/project_images) folder. + +## Setup + +You can run the provided example project on your local machine by following the steps outlined below. + +Create a new virtual environment: + +```bash +$ python3 -m venv venv +``` + +Activate the virtual environment: + +```bash +$ source venv/bin/activate +``` + +Install the dependencies for this project if you haven't installed them yet: + +```bash +(venv) $ python -m pip install -r requirements.txt +``` + +Make and apply the migrations for the project to build your local database: + +```bash +(venv) $ python manage.py makemigrations +(venv) $ python manage.py migrate +``` + +Run the Django development server: + +```bash +(venv) $ python manage.py runserver +``` + +Navigate to `http://localhost:8000/` or `http://localhost:8000/projects` to see your portfolio project in action. diff --git a/rp-portfolio/blog/admin.py b/rp-portfolio/blog/admin.py deleted file mode 100644 index ac64b86daa..0000000000 --- a/rp-portfolio/blog/admin.py +++ /dev/null @@ -1,14 +0,0 @@ -from django.contrib import admin -from blog.models import Post, Category - - -class PostAdmin(admin.ModelAdmin): - pass - - -class CategoryAdmin(admin.ModelAdmin): - pass - - -admin.site.register(Post, PostAdmin) -admin.site.register(Category, CategoryAdmin) diff --git a/rp-portfolio/blog/apps.py b/rp-portfolio/blog/apps.py deleted file mode 100644 index 10038974b1..0000000000 --- a/rp-portfolio/blog/apps.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.apps import AppConfig - - -class BlogConfig(AppConfig): - name = "blog" diff --git a/rp-portfolio/blog/forms.py b/rp-portfolio/blog/forms.py deleted file mode 100644 index 3fdf2c7e31..0000000000 --- a/rp-portfolio/blog/forms.py +++ /dev/null @@ -1,15 +0,0 @@ -from django import forms - - -class CommentForm(forms.Form): - author = forms.CharField( - max_length=60, - widget=forms.TextInput( - attrs={"class": "form-control", "placeholder": "Your Name"} - ), - ) - body = forms.CharField( - widget=forms.Textarea( - attrs={"class": "form-control", "placeholder": "Leave a comment!"} - ) - ) diff --git a/rp-portfolio/blog/migrations/0001_initial.py b/rp-portfolio/blog/migrations/0001_initial.py deleted file mode 100644 index a8b9d85f76..0000000000 --- a/rp-portfolio/blog/migrations/0001_initial.py +++ /dev/null @@ -1,54 +0,0 @@ -# Generated by Django 2.1.4 on 2018-12-16 19:11 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='Category', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, - serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=20)), - ], - ), - migrations.CreateModel( - name='Comment', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, - serialize=False, verbose_name='ID')), - ('author', models.CharField(max_length=60)), - ('body', models.TextField()), - ('created_on', models.DateTimeField(auto_now_add=True)), - ], - ), - migrations.CreateModel( - name='Post', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, - serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=255)), - ('body', models.TextField()), - ('created_on', models.DateTimeField(auto_now_add=True)), - ('last_modified', models.DateTimeField(auto_now=True)), - ('categories', models.ManyToManyField(related_name='posts', - to='blog.Category')), - ], - ), - migrations.AddField( - model_name='comment', - name='post', - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to='blog.Post' - ), - ), - ] diff --git a/rp-portfolio/blog/migrations/__init__.py b/rp-portfolio/blog/migrations/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/rp-portfolio/blog/models.py b/rp-portfolio/blog/models.py deleted file mode 100644 index a28ccd2734..0000000000 --- a/rp-portfolio/blog/models.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.db import models - - -class Category(models.Model): - name = models.CharField(max_length=20) - - -class Post(models.Model): - title = models.CharField(max_length=255) - body = models.TextField() - created_on = models.DateTimeField(auto_now_add=True) - last_modified = models.DateTimeField(auto_now=True) - categories = models.ManyToManyField("Category", related_name="posts") - - -class Comment(models.Model): - author = models.CharField(max_length=60) - body = models.TextField() - created_on = models.DateTimeField(auto_now_add=True) - post = models.ForeignKey("Post", on_delete=models.CASCADE) diff --git a/rp-portfolio/blog/templates/blog_category.html b/rp-portfolio/blog/templates/blog_category.html deleted file mode 100644 index 324c31eda5..0000000000 --- a/rp-portfolio/blog/templates/blog_category.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "base.html" %} -{% block page_content %} -
-

{{ category | title }}

-
- {% for post in posts %} -

{{ post.title }}

- - {{ post.created_on.date }} |  - Categories:  - {% for category in post.categories.all %} - - {{ category.name }} -   - {% endfor %} - -

{{ post.body | slice:":400" }}...

- {% endfor %} -
-{% endblock %} diff --git a/rp-portfolio/blog/templates/blog_detail.html b/rp-portfolio/blog/templates/blog_detail.html deleted file mode 100644 index a0791a3686..0000000000 --- a/rp-portfolio/blog/templates/blog_detail.html +++ /dev/null @@ -1,36 +0,0 @@ -{% extends "base.html" %} -{% block page_content %} -
-

{{ post.title }}

- - {{ post.created_on.date }} |  - Categories:  - {% for category in post.categories.all %} - - {{ category.name }} -   - {% endfor %} - -

{{ post.body | linebreaks }}

-

Leave a comment:

-
- {% csrf_token %} -
- {{ form.author }} -
-
- {{ form.body }} -
- -
-

Comments:

- {% for comment in comments %} -

- On {{comment.created_on.date }}  - {{ comment.author }} wrote: -

-

{{ comment.body }}

-
- {% endfor %} -
-{% endblock %} diff --git a/rp-portfolio/blog/templates/blog_index.html b/rp-portfolio/blog/templates/blog_index.html deleted file mode 100644 index 8b80d37760..0000000000 --- a/rp-portfolio/blog/templates/blog_index.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends "base.html" %} - -{% block page_content %} -
-

Blog Index

-
- {% for post in posts %} -

{{ post.title }}

- - {{ post.created_on.date }} |  - Categories:  - {% for category in post.categories.all %} - - {{ category.name }} -   - {% endfor %} - -

{{ post.body | slice:":400" }}...

- {% endfor %} -
-{% endblock %} diff --git a/rp-portfolio/blog/tests.py b/rp-portfolio/blog/tests.py deleted file mode 100644 index a79ca8be56..0000000000 --- a/rp-portfolio/blog/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -# from django.test import TestCase - -# Create your tests here. diff --git a/rp-portfolio/blog/urls.py b/rp-portfolio/blog/urls.py deleted file mode 100644 index afd1c42b27..0000000000 --- a/rp-portfolio/blog/urls.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.urls import path -from . import views - -urlpatterns = [ - path("", views.blog_index, name="blog_index"), - path("/", views.blog_detail, name="blog_detail"), - path("/", views.blog_category, name="blog_category"), -] diff --git a/rp-portfolio/blog/views.py b/rp-portfolio/blog/views.py deleted file mode 100644 index 75808bde6b..0000000000 --- a/rp-portfolio/blog/views.py +++ /dev/null @@ -1,37 +0,0 @@ -from django.shortcuts import render - -from blog.forms import CommentForm -from blog.models import Post, Comment - - -def blog_index(request): - posts = Post.objects.all().order_by("-created_on") - context = {"posts": posts} - return render(request, "blog_index.html", context) - - -def blog_category(request, category): - posts = Post.objects.filter(categories__name__contains=category).order_by( - "-created_on" - ) - context = {"category": category, "posts": posts} - return render(request, "blog_category.html", context) - - -def blog_detail(request, pk): - post = Post.objects.get(pk=pk) - comments = Comment.objects.filter(post=post) - - form = CommentForm() - if request.method == "POST": - form = CommentForm(request.POST) - if form.is_valid(): - comment = Comment( - author=form.cleaned_data["author"], - body=form.cleaned_data["body"], - post=post, - ) - comment.save() - - context = {"post": post, "comments": comments, "form": form} - return render(request, "blog_detail.html", context) diff --git a/rp-portfolio/manage.py b/rp-portfolio/manage.py index bd3c534b5b..ff792ca5eb 100755 --- a/rp-portfolio/manage.py +++ b/rp-portfolio/manage.py @@ -1,8 +1,11 @@ #!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" import os import sys -if __name__ == "__main__": + +def main(): + """Run administrative tasks.""" os.environ.setdefault( "DJANGO_SETTINGS_MODULE", "personal_portfolio.settings" ) @@ -15,3 +18,7 @@ "forget to activate a virtual environment?" ) from exc execute_from_command_line(sys.argv) + + +if __name__ == "__main__": + main() diff --git a/rp-portfolio/blog/__init__.py b/rp-portfolio/pages/__init__.py similarity index 100% rename from rp-portfolio/blog/__init__.py rename to rp-portfolio/pages/__init__.py diff --git a/rp-portfolio/pages/apps.py b/rp-portfolio/pages/apps.py new file mode 100644 index 0000000000..4b6237c55b --- /dev/null +++ b/rp-portfolio/pages/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PagesConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "pages" diff --git a/rp-portfolio/pages/templates/pages/home.html b/rp-portfolio/pages/templates/pages/home.html new file mode 100644 index 0000000000..846d734fb1 --- /dev/null +++ b/rp-portfolio/pages/templates/pages/home.html @@ -0,0 +1,5 @@ +{% extends "base.html" %} + +{% block page_content %} +

Hello, World!

+{% endblock page_content %} diff --git a/rp-portfolio/pages/urls.py b/rp-portfolio/pages/urls.py new file mode 100644 index 0000000000..56268a2247 --- /dev/null +++ b/rp-portfolio/pages/urls.py @@ -0,0 +1,6 @@ +from django.urls import path +from pages import views + +urlpatterns = [ + path("", views.home, name="home"), +] diff --git a/rp-portfolio/pages/views.py b/rp-portfolio/pages/views.py new file mode 100644 index 0000000000..35737bc4df --- /dev/null +++ b/rp-portfolio/pages/views.py @@ -0,0 +1,5 @@ +from django.shortcuts import render + + +def home(request): + return render(request, "pages/home.html", {}) diff --git a/rp-portfolio/personal_portfolio/asgi.py b/rp-portfolio/personal_portfolio/asgi.py new file mode 100644 index 0000000000..a274c9bcf6 --- /dev/null +++ b/rp-portfolio/personal_portfolio/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for personal_portfolio project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "personal_portfolio.settings") + +application = get_asgi_application() diff --git a/rp-portfolio/personal_portfolio/settings.py b/rp-portfolio/personal_portfolio/settings.py index 3f1a01e8e5..311a542347 100644 --- a/rp-portfolio/personal_portfolio/settings.py +++ b/rp-portfolio/personal_portfolio/settings.py @@ -1,26 +1,28 @@ """ Django settings for personal_portfolio project. -Generated by 'django-admin startproject' using Django 2.1.4. +Generated by 'django-admin startproject' using Django 4.2.4. For more information on this file, see -https://docs.djangoproject.com/en/2.1/topics/settings/ +https://docs.djangoproject.com/en/4.2/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/2.1/ref/settings/ +https://docs.djangoproject.com/en/4.2/ref/settings/ """ -import os +from pathlib import Path -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "!^_6%0so9$a@u-w22nc56xcp0^spoo4k^3q!j016o5hll+#c#o" +SECRET_KEY = ( + "django-insecure-31@!bxz-__i#0_lt_oy4*$e0q$a5h9e32-^yso51gydj^a!v#9" +) # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -31,14 +33,14 @@ # Application definition INSTALLED_APPS = [ + "pages.apps.PagesConfig", + "projects.apps.ProjectsConfig", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", - "projects", - "blog", ] MIDDLEWARE = [ @@ -56,7 +58,9 @@ TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": ["personal_portfolio/templates/"], + "DIRS": [ + BASE_DIR / "templates/", + ], "APP_DIRS": True, "OPTIONS": { "context_processors": [ @@ -64,50 +68,46 @@ "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", - ] + ], }, - } + }, ] WSGI_APPLICATION = "personal_portfolio.wsgi.application" # Database -# https://docs.djangoproject.com/en/2.1/ref/settings/#databases +# https://docs.djangoproject.com/en/4.2/ref/settings/#databases DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", - "NAME": os.path.join(BASE_DIR, "db.sqlite3"), + "NAME": BASE_DIR / "db.sqlite3", } } # Password validation -# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { - "NAME": "django.contrib.auth.password_validation" - + ".UserAttributeSimilarityValidator" + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { - "NAME": "django.contrib.auth.password_validation" - + ".MinimumLengthValidator" + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { - "NAME": "django.contrib.auth.password_validation" - + ".CommonPasswordValidator" + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { - "NAME": "django.contrib.auth.password_validation" - + ".NumericPasswordValidator" + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] # Internationalization -# https://docs.djangoproject.com/en/2.1/topics/i18n/ +# https://docs.djangoproject.com/en/4.2/topics/i18n/ LANGUAGE_CODE = "en-us" @@ -115,12 +115,18 @@ USE_I18N = True -USE_L10N = True - USE_TZ = True # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/2.1/howto/static-files/ +# https://docs.djangoproject.com/en/4.2/howto/static-files/ + +STATIC_URL = "static/" + +# Default primary key field type +# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" -STATIC_URL = "/static/" +MEDIA_ROOT = BASE_DIR / "uploads/" +MEDIA_URL = "media/" diff --git a/rp-portfolio/personal_portfolio/templates/base.html b/rp-portfolio/personal_portfolio/templates/base.html deleted file mode 100644 index df3a7d0cbc..0000000000 --- a/rp-portfolio/personal_portfolio/templates/base.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - -
- {% block page_content %}{% endblock %} -
- - - - diff --git a/rp-portfolio/personal_portfolio/urls.py b/rp-portfolio/personal_portfolio/urls.py index 2c2022ed03..6fd49c525f 100644 --- a/rp-portfolio/personal_portfolio/urls.py +++ b/rp-portfolio/personal_portfolio/urls.py @@ -1,23 +1,10 @@ -"""personal_portfolio URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/2.1/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" 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("pages.urls")), path("projects/", include("projects.urls")), - path("blog/", include("blog.urls")), -] +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/rp-portfolio/personal_portfolio/wsgi.py b/rp-portfolio/personal_portfolio/wsgi.py index 8255492c15..32e0bfdc04 100644 --- a/rp-portfolio/personal_portfolio/wsgi.py +++ b/rp-portfolio/personal_portfolio/wsgi.py @@ -4,7 +4,7 @@ It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ """ import os diff --git a/rp-portfolio/projects/admin.py b/rp-portfolio/projects/admin.py index 4185d360e9..0afa67bf68 100644 --- a/rp-portfolio/projects/admin.py +++ b/rp-portfolio/projects/admin.py @@ -1,3 +1,9 @@ -# from django.contrib import admin +from django.contrib import admin +from projects.models import Project -# Register your models here. + +class ProjectAdmin(admin.ModelAdmin): + pass + + +admin.site.register(Project, ProjectAdmin) diff --git a/rp-portfolio/projects/apps.py b/rp-portfolio/projects/apps.py index 20f1a5a832..c992f4a7a4 100644 --- a/rp-portfolio/projects/apps.py +++ b/rp-portfolio/projects/apps.py @@ -2,4 +2,5 @@ class ProjectsConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" name = "projects" diff --git a/rp-portfolio/projects/migrations/0001_initial.py b/rp-portfolio/projects/migrations/0001_initial.py index 9f99ce9ca3..8e3fd37a42 100644 --- a/rp-portfolio/projects/migrations/0001_initial.py +++ b/rp-portfolio/projects/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.1.4 on 2018-12-16 13:45 +# Generated by Django 4.2.4 on 2023-08-25 10:09 from django.db import migrations, models @@ -14,12 +14,11 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Project', fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, - serialize=False, verbose_name='ID')), + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('title', models.CharField(max_length=100)), ('description', models.TextField()), ('technology', models.CharField(max_length=20)), - ('image', models.FilePathField(path='/img')), + ('image', models.FileField(blank=True, upload_to='project_images/')), ], ), ] diff --git a/rp-portfolio/projects/models.py b/rp-portfolio/projects/models.py index 1a1edde1bc..27b26eaec2 100644 --- a/rp-portfolio/projects/models.py +++ b/rp-portfolio/projects/models.py @@ -5,4 +5,4 @@ class Project(models.Model): title = models.CharField(max_length=100) description = models.TextField() technology = models.CharField(max_length=20) - image = models.FilePathField(path="/img") + image = models.FileField(upload_to="project_images/", blank=True) diff --git a/rp-portfolio/projects/templates/project_detail.html b/rp-portfolio/projects/templates/projects/project_detail.html similarity index 71% rename from rp-portfolio/projects/templates/project_detail.html rename to rp-portfolio/projects/templates/projects/project_detail.html index 2c92be07f4..2acff4ed56 100644 --- a/rp-portfolio/projects/templates/project_detail.html +++ b/rp-portfolio/projects/templates/projects/project_detail.html @@ -1,11 +1,12 @@ {% extends "base.html" %} -{% load static %} {% block page_content %}

{{ project.title }}

- + {% if project.image %} + + {% endif %}
About the project:
@@ -15,5 +16,4 @@
Technology used:

{{ project.technology }}

- -{% endblock %} +{% endblock page_content %} diff --git a/rp-portfolio/projects/templates/project_index.html b/rp-portfolio/projects/templates/projects/project_index.html similarity index 76% rename from rp-portfolio/projects/templates/project_index.html rename to rp-portfolio/projects/templates/projects/project_index.html index 3811b74b8f..a43519acfb 100644 --- a/rp-portfolio/projects/templates/project_index.html +++ b/rp-portfolio/projects/templates/projects/project_index.html @@ -1,12 +1,14 @@ {% extends "base.html" %} -{% load static %} + {% block page_content %}

Projects

{% for project in projects %}
- + {% if project.image %} + + {% endif %}
{{ project.title }}

{{ project.description }}

@@ -17,6 +19,6 @@
{{ project.title }}
- {% endfor %} +{% endfor %}
-{% endblock %} +{% endblock page_content %} diff --git a/rp-portfolio/projects/tests.py b/rp-portfolio/projects/tests.py deleted file mode 100644 index a79ca8be56..0000000000 --- a/rp-portfolio/projects/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -# from django.test import TestCase - -# Create your tests here. diff --git a/rp-portfolio/projects/urls.py b/rp-portfolio/projects/urls.py index 231abb5839..3bce1cbefb 100644 --- a/rp-portfolio/projects/urls.py +++ b/rp-portfolio/projects/urls.py @@ -1,5 +1,5 @@ from django.urls import path -from . import views +from projects import views urlpatterns = [ path("", views.project_index, name="project_index"), diff --git a/rp-portfolio/projects/views.py b/rp-portfolio/projects/views.py index 51a2ed42da..eb05a040b7 100644 --- a/rp-portfolio/projects/views.py +++ b/rp-portfolio/projects/views.py @@ -5,10 +5,10 @@ def project_index(request): projects = Project.objects.all() context = {"projects": projects} - return render(request, "project_index.html", context) + return render(request, "projects/project_index.html", context) def project_detail(request, pk): project = Project.objects.get(pk=pk) context = {"project": project} - return render(request, "project_detail.html", context) + return render(request, "projects/project_detail.html", context) diff --git a/rp-portfolio/requirements.txt b/rp-portfolio/requirements.txt new file mode 100644 index 0000000000..57104a52a0 --- /dev/null +++ b/rp-portfolio/requirements.txt @@ -0,0 +1,3 @@ +asgiref==3.7.2 +Django==4.2.4 +sqlparse==0.4.4 diff --git a/rp-portfolio/templates/base.html b/rp-portfolio/templates/base.html new file mode 100644 index 0000000000..4704d566c5 --- /dev/null +++ b/rp-portfolio/templates/base.html @@ -0,0 +1,14 @@ + + + + + {% block title %}My Personal Portfolio{% endblock title %} + + + +{% block page_content %}{% endblock page_content %} + + diff --git a/rp-portfolio/projects/static/img/project1.png b/rp-portfolio/uploads/project_images/project1.png similarity index 100% rename from rp-portfolio/projects/static/img/project1.png rename to rp-portfolio/uploads/project_images/project1.png diff --git a/rp-portfolio/projects/static/img/project2.png b/rp-portfolio/uploads/project_images/project2.png similarity index 100% rename from rp-portfolio/projects/static/img/project2.png rename to rp-portfolio/uploads/project_images/project2.png diff --git a/rp-portfolio/projects/static/img/project3.png b/rp-portfolio/uploads/project_images/project3.png similarity index 100% rename from rp-portfolio/projects/static/img/project3.png rename to rp-portfolio/uploads/project_images/project3.png