Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Arty-Guy committed Mar 12, 2022
2 parents 55b99d2 + 0bf1e71 commit 581a2ac
Show file tree
Hide file tree
Showing 234 changed files with 29,968 additions and 12 deletions.
22 changes: 22 additions & 0 deletions 4 Django/demo/n_plus_one/manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'n_plus_one_proj.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)


if __name__ == '__main__':
main()
Empty file.
5 changes: 5 additions & 0 deletions 4 Django/demo/n_plus_one/n_plus_one_app/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.contrib import admin

from .models import *

admin.site.register([BlogPost, Comment])
6 changes: 6 additions & 0 deletions 4 Django/demo/n_plus_one/n_plus_one_app/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class NPlusOneAppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'n_plus_one_app'
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from django.core.management.base import BaseCommand
import requests

from n_plus_one_app.models import *

def split_name(name):
'''Split the full name from the API JSON into a first and last name, handling two three-part names'''
match name:
case 'Mrs. Dennis Schulist':
split_name = name.split(' ')[1:]

case 'Nicholas Runolfsdottir V':
split_name = name.split(' ')[:2]

case default:
split_name = name.split(' ')

return split_name

class Command(BaseCommand):

def handle(self, *args, **options):

User.objects.filter(is_superuser=False).delete()
BlogPost.objects.all().delete()
Comment.objects.all().delete()

BASE_URL = "http://jsonplaceholder.typicode.com"

for x in range(10):
users = requests.get(BASE_URL + '/users').json()
user_ids = []
for user in users:
username = user['username']
email = user['email']
name = user['name']

first_name, last_name = split_name(name)

new_user = User.objects.create_user(
username=username + str(x),
email=email,
password='pass3412',
first_name=first_name,
last_name=last_name
)

user_ids.append(new_user.id)

# list of all the user ids
blogpost_ids = []

# create posts
posts = requests.get(BASE_URL + '/posts').json()
for post in posts:
# user_id is the value at the index of the userId from the API
user_id = user_ids[int(post['userId'])-1]
user = User.objects.get(id=user_id)

title = post['title']
body = post['body']

user = User.objects.get(id=user_id)

new_blogpost = BlogPost.objects.create(
user=user,
title=title,
body=body
)

blogpost_ids.append(new_blogpost.id)


# create comments
comments = requests.get(BASE_URL + '/comments').json()
for comment in comments:
name = comment['name']
body = comment['name']

# user_id is the value at the index of the userId from the API
blogpost_id = blogpost_ids[int(comment['postId'])-1]
blogpost = BlogPost.objects.get(id=blogpost_id)

new_comment = Comment.objects.create(
blogpost = blogpost,
name=name,
body=body
)

36 changes: 36 additions & 0 deletions 4 Django/demo/n_plus_one/n_plus_one_app/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 4.0.2 on 2022-02-10 21:35

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='BlogPost',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=100)),
('body', models.CharField(max_length=1000)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='blogposts', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Comment',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=500)),
('email', models.EmailField(max_length=100)),
('body', models.CharField(max_length=1000)),
('blogpost', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='blogposts', to='n_plus_one_app.blogpost')),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.0 on 2022-02-12 01:05

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('n_plus_one_app', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='comment',
name='blogpost',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='n_plus_one_app.blogpost'),
),
]
Empty file.
13 changes: 13 additions & 0 deletions 4 Django/demo/n_plus_one/n_plus_one_app/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.db import models
from django.contrib.auth.models import User

class BlogPost(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blogposts')
title = models.CharField(max_length=100)
body = models.CharField(max_length=1000)

class Comment(models.Model):
blogpost = models.ForeignKey(BlogPost, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=500)
email = models.EmailField(max_length=100)
body = models.CharField(max_length=1000)
28 changes: 28 additions & 0 deletions 4 Django/demo/n_plus_one/n_plus_one_app/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!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">
<title>Document</title>
</head>
<body>
<h1>{{query_count}} queries were made</h1>


{% for user in users %}
{{user.username}}
{% for blogpost in user.blogposts.all %}
{{blogpost.title}}

{% for comment in blogpost.comments.all %}
{{comment.name}}

{% endfor %}

{% endfor %}

{% endfor %}

</body>
</html>
3 changes: 3 additions & 0 deletions 4 Django/demo/n_plus_one/n_plus_one_app/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
8 changes: 8 additions & 0 deletions 4 Django/demo/n_plus_one/n_plus_one_app/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.urls import path
from . import views

app_name = 'n_plus_one'

urlpatterns = [
path('', views.index, name='index')
]
42 changes: 42 additions & 0 deletions 4 Django/demo/n_plus_one/n_plus_one_app/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from django.shortcuts import render

from django.db import connection, reset_queries

from .models import *


def index(request):

# retrieve only the user objects, not their blogposts or the blogposts' comments
# 1102 queries to get all the comments
# users = User.objects.all()

# retrieve the users and all of their blogposts, but not the comments
# 101 queries to get all the comments
# users = User.objects.all().prefetch_related('blogposts')

# retreive the users, their blogposts and the comments
# 3 queries to get all the comments
users = User.objects.all().prefetch_related('blogposts__comments')


# print(users.blogposts.first().comments.all())

# for user in users:
# # print(user)
# for blogpost in user.blogposts.all():
# x = blogpost
# print(blogpost)
# for comment in blogpost.comments.all():
# print(comment)
# x = comment # evaluate the comment into a variable


query_count = len(connection.queries)

context = {
'query_count': query_count,
'users': users
}

return render(request, 'index.html', context)
Empty file.
16 changes: 16 additions & 0 deletions 4 Django/demo/n_plus_one/n_plus_one_proj/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
ASGI config for n_plus_one_proj 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.0/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'n_plus_one_proj.settings')

application = get_asgi_application()
Loading

0 comments on commit 581a2ac

Please sign in to comment.