Skip to content

Commit 52d5c5d

Browse files
acsanymartin-martingahjelle
authored
Add Django + Vue Update (#508)
* Add old files * Add new materials * Add black formatting * Remove unused tests * Change port number * Rename folders * Update code formatting using "prettier" * Move "blog" app to the bottom of `INSTALLED_APPS * Fix final step folder name * Update Readme * Reformat settings files --------- Co-authored-by: Martin Breuss <[email protected]> Co-authored-by: Geir Arne Hjelle <[email protected]>
1 parent e1deb5b commit 52d5c5d

File tree

235 files changed

+11907
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

235 files changed

+11907
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Build a Blog Using Django, Vue, and GraphQL
2+
3+
This repository contains code related to the tutorial on [building a blog using Django, Vue, and GraphQL](https://realpython.com/python-django-blog/).
4+
5+
Navigate to the corresponding folder in this repository to compare your code with the code from the tutorial:
6+
7+
- [Step 1](source_code_step_1/)
8+
- [Step 2](source_code_step_2/)
9+
- [Step 3](source_code_step_3/)
10+
- [Step 4](source_code_step_4/)
11+
- [Step 5](source_code_step_5/)
12+
- [Step 6](source_code_step_6/)
13+
- [Step 7](source_code_step_7/)
14+
- [Step 8](source_code_step_8/)
15+
- [Step 9](source_code_final/)
16+
17+
If you want to install the project on your machine without following the tutorial, then you need to follow the steps outlined below.
18+
19+
## Setup
20+
21+
Navigate into the `source_code_final/` folder. In this folder, you'll find the folders `back_end/` and `front_end/`, which represent both projects of the tutorial.
22+
23+
### Back End
24+
25+
Create a new terminal window, navigate into `back_end/`, create, activate a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/), and install the necessary dependencies:
26+
27+
```sh
28+
$ python -m venv venv
29+
$ source venv/bin/activate
30+
(venv) $ python -m pip install -r requirements.txt
31+
```
32+
33+
Then, create the initial Django database by running migrations:
34+
35+
```sh
36+
$ python manage.py migrate
37+
```
38+
39+
Create a Django superuser:
40+
41+
```shell
42+
$ python manage.py createsuperuser
43+
```
44+
45+
Run the Django project:
46+
47+
```sh
48+
$ python manage.py runserver
49+
```
50+
51+
Before continuing, it's a good idea to create some users, profiles, and blog posts in the Django admin interface at `http://localhost:8000/admin`. You must use your superuser credentials to log in.
52+
53+
You can visit the GraphiQL platform `http://localhost:8000/graphql` to try out GraphQL queries.
54+
55+
### Front End
56+
57+
Open a new terminal and navigate into `front_end/`. Then, install the front-end requirements:
58+
59+
```sh
60+
$ npm install --include dev
61+
```
62+
63+
Run the Vite development server:
64+
65+
```sh
66+
$ npm run dev
67+
```
68+
69+
You must have the Django development server and the Vite server running at the same time.

django-vue-graphql-update/source_code_final/back_end/backend/__init__.py

Whitespace-only changes.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
ASGI config for backend project.
3+
4+
It exposes the ASGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.asgi import get_asgi_application
13+
14+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings")
15+
16+
application = get_asgi_application()
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
"""
2+
Django settings for backend project.
3+
4+
Generated by 'django-admin startproject' using Django 5.0.2.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/5.0/topics/settings/
8+
9+
For the full list of settings and their values, see
10+
https://docs.djangoproject.com/en/5.0/ref/settings/
11+
"""
12+
13+
from pathlib import Path
14+
15+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
16+
BASE_DIR = Path(__file__).resolve().parent.parent
17+
18+
19+
# Quick-start development settings - unsuitable for production
20+
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
21+
22+
# SECURITY WARNING: keep the secret key used in production secret!
23+
SECRET_KEY = (
24+
"django-insecure-nv&xe8r)*pw1b0n^n#hax!2i%k-!*ek(0h)2td))j-(5eomvda"
25+
)
26+
27+
# SECURITY WARNING: don't run with debug turned on in production!
28+
DEBUG = True
29+
30+
ALLOWED_HOSTS = []
31+
32+
33+
# Application definition
34+
35+
INSTALLED_APPS = [
36+
"blog.apps.BlogConfig",
37+
"django.contrib.admin",
38+
"django.contrib.auth",
39+
"django.contrib.contenttypes",
40+
"django.contrib.sessions",
41+
"django.contrib.messages",
42+
"django.contrib.staticfiles",
43+
"graphene_django",
44+
"corsheaders",
45+
]
46+
47+
MIDDLEWARE = [
48+
"corsheaders.middleware.CorsMiddleware",
49+
"django.middleware.security.SecurityMiddleware",
50+
"django.contrib.sessions.middleware.SessionMiddleware",
51+
"django.middleware.common.CommonMiddleware",
52+
"django.middleware.csrf.CsrfViewMiddleware",
53+
"django.contrib.auth.middleware.AuthenticationMiddleware",
54+
"django.contrib.messages.middleware.MessageMiddleware",
55+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
56+
]
57+
58+
ROOT_URLCONF = "backend.urls"
59+
60+
TEMPLATES = [
61+
{
62+
"BACKEND": "django.template.backends.django.DjangoTemplates",
63+
"DIRS": [],
64+
"APP_DIRS": True,
65+
"OPTIONS": {
66+
"context_processors": [
67+
"django.template.context_processors.debug",
68+
"django.template.context_processors.request",
69+
"django.contrib.auth.context_processors.auth",
70+
"django.contrib.messages.context_processors.messages",
71+
],
72+
},
73+
},
74+
]
75+
76+
WSGI_APPLICATION = "backend.wsgi.application"
77+
78+
79+
# Database
80+
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
81+
82+
DATABASES = {
83+
"default": {
84+
"ENGINE": "django.db.backends.sqlite3",
85+
"NAME": BASE_DIR / "db.sqlite3",
86+
}
87+
}
88+
89+
90+
# Password validation
91+
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
92+
93+
AUTH_PASSWORD_VALIDATORS = [
94+
{
95+
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
96+
},
97+
{
98+
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
99+
},
100+
{
101+
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
102+
},
103+
{
104+
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
105+
},
106+
]
107+
108+
109+
# Internationalization
110+
# https://docs.djangoproject.com/en/5.0/topics/i18n/
111+
112+
LANGUAGE_CODE = "en-us"
113+
114+
TIME_ZONE = "UTC"
115+
116+
USE_I18N = True
117+
118+
USE_TZ = True
119+
120+
121+
# Static files (CSS, JavaScript, Images)
122+
# https://docs.djangoproject.com/en/5.0/howto/static-files/
123+
124+
STATIC_URL = "static/"
125+
126+
# Default primary key field type
127+
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
128+
129+
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
130+
131+
GRAPHENE = {
132+
"SCHEMA": "blog.schema.schema",
133+
}
134+
135+
CORS_ALLOWED_ORIGINS = ("http://localhost:5173",)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from django.contrib import admin
2+
from django.urls import path
3+
from django.views.decorators.csrf import csrf_exempt
4+
from graphene_django.views import GraphQLView
5+
6+
urlpatterns = [
7+
path("admin/", admin.site.urls),
8+
path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True))),
9+
]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
WSGI config for backend project.
3+
4+
It exposes the WSGI callable as a module-level variable named ``application``.
5+
6+
For more information on this file, see
7+
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
8+
"""
9+
10+
import os
11+
12+
from django.core.wsgi import get_wsgi_application
13+
14+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings")
15+
16+
application = get_wsgi_application()

django-vue-graphql-update/source_code_final/back_end/blog/__init__.py

Whitespace-only changes.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from django.contrib import admin
2+
from blog.models import Profile, Post, Tag
3+
4+
5+
@admin.register(Profile)
6+
class ProfileAdmin(admin.ModelAdmin):
7+
model = Profile
8+
9+
10+
@admin.register(Tag)
11+
class TagAdmin(admin.ModelAdmin):
12+
model = Tag
13+
14+
15+
@admin.register(Post)
16+
class PostAdmin(admin.ModelAdmin):
17+
model = Post
18+
19+
list_display = (
20+
"id",
21+
"title",
22+
"subtitle",
23+
"slug",
24+
"publish_date",
25+
"published",
26+
)
27+
list_filter = (
28+
"published",
29+
"publish_date",
30+
)
31+
list_editable = (
32+
"title",
33+
"subtitle",
34+
"slug",
35+
"publish_date",
36+
"published",
37+
)
38+
search_fields = (
39+
"title",
40+
"subtitle",
41+
"slug",
42+
"body",
43+
)
44+
prepopulated_fields = {
45+
"slug": (
46+
"title",
47+
"subtitle",
48+
)
49+
}
50+
date_hierarchy = "publish_date"
51+
save_on_top = True
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class BlogConfig(AppConfig):
5+
default_auto_field = "django.db.models.BigAutoField"
6+
name = "blog"
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Generated by Django 5.0.2 on 2024-02-28 15:52
2+
3+
import django.db.models.deletion
4+
from django.conf import settings
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
initial = True
10+
11+
dependencies = [
12+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13+
]
14+
15+
operations = [
16+
migrations.CreateModel(
17+
name="Tag",
18+
fields=[
19+
(
20+
"id",
21+
models.BigAutoField(
22+
auto_created=True,
23+
primary_key=True,
24+
serialize=False,
25+
verbose_name="ID",
26+
),
27+
),
28+
("name", models.CharField(max_length=50, unique=True)),
29+
],
30+
),
31+
migrations.CreateModel(
32+
name="Profile",
33+
fields=[
34+
(
35+
"id",
36+
models.BigAutoField(
37+
auto_created=True,
38+
primary_key=True,
39+
serialize=False,
40+
verbose_name="ID",
41+
),
42+
),
43+
("website", models.URLField(blank=True)),
44+
("bio", models.CharField(blank=True, max_length=240)),
45+
(
46+
"user",
47+
models.OneToOneField(
48+
on_delete=django.db.models.deletion.PROTECT,
49+
to=settings.AUTH_USER_MODEL,
50+
),
51+
),
52+
],
53+
),
54+
migrations.CreateModel(
55+
name="Post",
56+
fields=[
57+
(
58+
"id",
59+
models.BigAutoField(
60+
auto_created=True,
61+
primary_key=True,
62+
serialize=False,
63+
verbose_name="ID",
64+
),
65+
),
66+
("title", models.CharField(max_length=255, unique=True)),
67+
("subtitle", models.CharField(blank=True, max_length=255)),
68+
("slug", models.SlugField(max_length=255, unique=True)),
69+
("body", models.TextField()),
70+
("meta_description", models.CharField(blank=True, max_length=150)),
71+
("date_created", models.DateTimeField(auto_now_add=True)),
72+
("date_modified", models.DateTimeField(auto_now=True)),
73+
("publish_date", models.DateTimeField(blank=True, null=True)),
74+
("published", models.BooleanField(default=False)),
75+
(
76+
"author",
77+
models.ForeignKey(
78+
on_delete=django.db.models.deletion.PROTECT, to="blog.profile"
79+
),
80+
),
81+
("tags", models.ManyToManyField(blank=True, to="blog.tag")),
82+
],
83+
options={
84+
"ordering": ["-publish_date"],
85+
},
86+
),
87+
]

0 commit comments

Comments
 (0)