From 8ba167823d838a7c6b299bfd28c535a0454fa2d8 Mon Sep 17 00:00:00 2001 From: Maximilian Friedersdorff Date: Mon, 4 Jul 2022 21:31:33 +0100 Subject: [PATCH 1/6] Make post titles and descriptions optional --- .../0002_alter_post_body_alter_post_title.py | 23 +++++++++++++++++++ flangr/posts/models.py | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 flangr/posts/migrations/0002_alter_post_body_alter_post_title.py diff --git a/flangr/posts/migrations/0002_alter_post_body_alter_post_title.py b/flangr/posts/migrations/0002_alter_post_body_alter_post_title.py new file mode 100644 index 0000000..7748aa9 --- /dev/null +++ b/flangr/posts/migrations/0002_alter_post_body_alter_post_title.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.5 on 2022-07-04 20:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("posts", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="post", + name="body", + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name="post", + name="title", + field=models.CharField(max_length=255, null=True), + ), + ] diff --git a/flangr/posts/models.py b/flangr/posts/models.py index 0c1c4fa..e2b24e2 100644 --- a/flangr/posts/models.py +++ b/flangr/posts/models.py @@ -8,8 +8,8 @@ class Post(models.Model): posted = models.DateTimeField(auto_now_add=True) public = models.BooleanField(default=False) - title = models.CharField(max_length=255) - body = models.TextField() + title = models.CharField(max_length=255, null=True) + body = models.TextField(null=True) def __str__(self): return f"Post: {self.title} at {self.posted.strftime('%Y-%m-%d %H:%S')}" From dc384710b22266e5f4941387af201904eb443b7f Mon Sep 17 00:00:00 2001 From: Maximilian Friedersdorff Date: Mon, 4 Jul 2022 21:47:59 +0100 Subject: [PATCH 2/6] Add collection model --- flangr/posts/migrations/0003_collection.py | 33 ++++++++++++++++++++++ flangr/posts/models.py | 10 +++++++ flangr/posts/tests.py | 29 +++++++++++-------- 3 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 flangr/posts/migrations/0003_collection.py diff --git a/flangr/posts/migrations/0003_collection.py b/flangr/posts/migrations/0003_collection.py new file mode 100644 index 0000000..4191259 --- /dev/null +++ b/flangr/posts/migrations/0003_collection.py @@ -0,0 +1,33 @@ +# Generated by Django 4.0.5 on 2022-07-04 20:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("posts", "0002_alter_post_body_alter_post_title"), + ] + + operations = [ + migrations.CreateModel( + name="Collection", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=255)), + ("description", models.TextField()), + ( + "posts", + models.ManyToManyField(related_name="collections", to="posts.post"), + ), + ], + ), + ] diff --git a/flangr/posts/models.py b/flangr/posts/models.py index e2b24e2..63c5e33 100644 --- a/flangr/posts/models.py +++ b/flangr/posts/models.py @@ -13,3 +13,13 @@ class Post(models.Model): def __str__(self): return f"Post: {self.title} at {self.posted.strftime('%Y-%m-%d %H:%S')}" + + +class Collection(models.Model): + title = models.CharField(max_length=255) + description = models.TextField() + + posts = models.ManyToManyField("Post", related_name="collections") + + def __str__(self): + return f"Collection: {self.title}" diff --git a/flangr/posts/tests.py b/flangr/posts/tests.py index d0d72fa..94ded9b 100644 --- a/flangr/posts/tests.py +++ b/flangr/posts/tests.py @@ -3,24 +3,29 @@ import os from django.test import TestCase from django.core.files import File -from .models import Post +from .models import Post, Collection # Create your tests here. -class TestPostModelTests(TestCase): - def test_can_create_model(self): +class TestModelTests(TestCase): + def setUp(self): with open( os.path.join(os.path.dirname(__file__), "test_data", "test_img.png"), mode="rb", ) as f: - try: - p = Post.objects.create( - img=File(f, "somefile.png"), - title="Foobar", - body="Some file", - ) + self.post = Post.objects.create( + img=File(f, "somefile.png"), + title="Foobar", + body="Some file", + ) - self.assertIn("Foobar", str(p)) - finally: - p.img.delete() + def tearDown(self): + self.post.img.delete() + + def test_post_has_sensible_str(self): + self.assertIn("Foobar", str(self.post)) + + def test_collection_has_sensible_str(self): + col = Collection.objects.create(title="A collection", description="foobar") + self.assertIn("A collection", str(col)) From 32636b15b65df0caf6c8093d348b2387d2fe0ea7 Mon Sep 17 00:00:00 2001 From: Maximilian Friedersdorff Date: Mon, 4 Jul 2022 22:08:57 +0100 Subject: [PATCH 3/6] Set up models, urls, admin for basic interface Models for Posts, Comments, Collections, with admin pages and a DetailView for Posts --- config/settings/base.py | 2 + flangr/posts/admin.py | 6 ++ flangr/posts/migrations/0001_initial.py | 73 ++++++++++++++++++- .../0002_alter_post_body_alter_post_title.py | 23 ------ flangr/posts/migrations/0003_collection.py | 33 --------- flangr/posts/models.py | 17 +++++ flangr/posts/urls.py | 7 ++ flangr/posts/views.py | 8 +- flangr/urls.py | 9 ++- 9 files changed, 117 insertions(+), 61 deletions(-) delete mode 100644 flangr/posts/migrations/0002_alter_post_body_alter_post_title.py delete mode 100644 flangr/posts/migrations/0003_collection.py create mode 100644 flangr/posts/urls.py diff --git a/config/settings/base.py b/config/settings/base.py index 16c6413..ef66e4f 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -111,3 +111,5 @@ STATIC_URL = "static/" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" MEDIA_URL = "media/" + +AUTH_USER_MODEL = "auth.User" diff --git a/flangr/posts/admin.py b/flangr/posts/admin.py index 8c38f3f..a0e1a5f 100644 --- a/flangr/posts/admin.py +++ b/flangr/posts/admin.py @@ -1,3 +1,9 @@ from django.contrib import admin +from .models import Post, Collection, Comment + # Register your models here. + +admin.site.register(Post) +admin.site.register(Collection) +admin.site.register(Comment) diff --git a/flangr/posts/migrations/0001_initial.py b/flangr/posts/migrations/0001_initial.py index 7dfef44..ff728d5 100644 --- a/flangr/posts/migrations/0001_initial.py +++ b/flangr/posts/migrations/0001_initial.py @@ -1,13 +1,17 @@ -# Generated by Django 4.0.5 on 2022-07-03 21:35 +# Generated by Django 4.0.5 on 2022-07-04 20:55 +from django.conf import settings from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): initial = True - dependencies = [] + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] operations = [ migrations.CreateModel( @@ -25,8 +29,71 @@ class Migration(migrations.Migration): ("img", models.ImageField(upload_to="posts/%Y/%m")), ("posted", models.DateTimeField(auto_now_add=True)), ("public", models.BooleanField(default=False)), + ("title", models.CharField(max_length=255, null=True)), + ("body", models.TextField(null=True)), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.CreateModel( + name="Comment", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("comment", models.CharField(max_length=255)), + ( + "post", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="posts.post" + ), + ), + ( + "user", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.CreateModel( + name="Collection", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), ("title", models.CharField(max_length=255)), - ("body", models.TextField()), + ("description", models.TextField()), + ( + "posts", + models.ManyToManyField(related_name="collections", to="posts.post"), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), ] diff --git a/flangr/posts/migrations/0002_alter_post_body_alter_post_title.py b/flangr/posts/migrations/0002_alter_post_body_alter_post_title.py deleted file mode 100644 index 7748aa9..0000000 --- a/flangr/posts/migrations/0002_alter_post_body_alter_post_title.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 4.0.5 on 2022-07-04 20:31 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("posts", "0001_initial"), - ] - - operations = [ - migrations.AlterField( - model_name="post", - name="body", - field=models.TextField(null=True), - ), - migrations.AlterField( - model_name="post", - name="title", - field=models.CharField(max_length=255, null=True), - ), - ] diff --git a/flangr/posts/migrations/0003_collection.py b/flangr/posts/migrations/0003_collection.py deleted file mode 100644 index 4191259..0000000 --- a/flangr/posts/migrations/0003_collection.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 4.0.5 on 2022-07-04 20:47 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("posts", "0002_alter_post_body_alter_post_title"), - ] - - operations = [ - migrations.CreateModel( - name="Collection", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("title", models.CharField(max_length=255)), - ("description", models.TextField()), - ( - "posts", - models.ManyToManyField(related_name="collections", to="posts.post"), - ), - ], - ), - ] diff --git a/flangr/posts/models.py b/flangr/posts/models.py index 63c5e33..8c33cf6 100644 --- a/flangr/posts/models.py +++ b/flangr/posts/models.py @@ -1,5 +1,7 @@ from django.db import models +from django.conf import settings + # Create your models here. @@ -11,6 +13,8 @@ class Post(models.Model): title = models.CharField(max_length=255, null=True) body = models.TextField(null=True) + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + def __str__(self): return f"Post: {self.title} at {self.posted.strftime('%Y-%m-%d %H:%S')}" @@ -20,6 +24,19 @@ class Collection(models.Model): description = models.TextField() posts = models.ManyToManyField("Post", related_name="collections") + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) def __str__(self): return f"Collection: {self.title}" + + +class Comment(models.Model): + post = models.ForeignKey("Post", on_delete=models.CASCADE) + comment = models.CharField(max_length=255) + + user = models.ForeignKey( + settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True + ) + + def __str__(self): + return f"Comment by {self.user} on {self.post}" diff --git a/flangr/posts/urls.py b/flangr/posts/urls.py new file mode 100644 index 0000000..604330b --- /dev/null +++ b/flangr/posts/urls.py @@ -0,0 +1,7 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path("post/", views.PostDetailView.as_view()), +] diff --git a/flangr/posts/views.py b/flangr/posts/views.py index 91ea44a..d90837f 100644 --- a/flangr/posts/views.py +++ b/flangr/posts/views.py @@ -1,3 +1,9 @@ -from django.shortcuts import render +from django.views.generic import DetailView # Create your views here. + +from .models import Post + + +class PostDetailView(DetailView): + model = Post diff --git a/flangr/urls.py b/flangr/urls.py index 27e300e..13f018a 100644 --- a/flangr/urls.py +++ b/flangr/urls.py @@ -14,8 +14,15 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path +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("posts/", include("flangr.posts.urls")), ] + +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) From 641ace957b0b277dd9ad3e159e26cc6771fe4e9a Mon Sep 17 00:00:00 2001 From: Maximilian Friedersdorff Date: Mon, 4 Jul 2022 22:19:21 +0100 Subject: [PATCH 4/6] Flesh out detail view for Posts --- config/settings/base.py | 2 +- flangr/posts/models.py | 2 +- flangr/templates/posts/post_detail.html | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 flangr/templates/posts/post_detail.html diff --git a/config/settings/base.py b/config/settings/base.py index ef66e4f..0439961 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -53,7 +53,7 @@ ROOT_URLCONF = "flangr.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [], + "DIRS": ["flangr/templates"], "APP_DIRS": True, "OPTIONS": { "context_processors": [ diff --git a/flangr/posts/models.py b/flangr/posts/models.py index 8c33cf6..fa3446b 100644 --- a/flangr/posts/models.py +++ b/flangr/posts/models.py @@ -31,7 +31,7 @@ class Collection(models.Model): class Comment(models.Model): - post = models.ForeignKey("Post", on_delete=models.CASCADE) + post = models.ForeignKey("Post", on_delete=models.CASCADE, related_name="comments") comment = models.CharField(max_length=255) user = models.ForeignKey( diff --git a/flangr/templates/posts/post_detail.html b/flangr/templates/posts/post_detail.html new file mode 100644 index 0000000..0ad7cae --- /dev/null +++ b/flangr/templates/posts/post_detail.html @@ -0,0 +1,14 @@ + + {% if object.title %} +

{{ object.title }}

+ {% else %} +

{{ object.user.username }}

+ {% endif %} + +

Comments

+
    + {% for comment in object.comments.all %} +
  • {{ comment.user }} - {{ comment.comment }}
  • + {% endfor %} +
+ From 343e8b8834ce0cf5b5428293bfd31641e5ee7879 Mon Sep 17 00:00:00 2001 From: Maximilian Friedersdorff Date: Mon, 4 Jul 2022 22:27:21 +0100 Subject: [PATCH 5/6] Make img name unpredictable --- .../0002_alter_comment_post_alter_post_img.py | 29 +++++++++++++++++++ flangr/posts/models.py | 9 +++++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 flangr/posts/migrations/0002_alter_comment_post_alter_post_img.py diff --git a/flangr/posts/migrations/0002_alter_comment_post_alter_post_img.py b/flangr/posts/migrations/0002_alter_comment_post_alter_post_img.py new file mode 100644 index 0000000..3548356 --- /dev/null +++ b/flangr/posts/migrations/0002_alter_comment_post_alter_post_img.py @@ -0,0 +1,29 @@ +# Generated by Django 4.0.5 on 2022-07-04 21:26 + +from django.db import migrations, models +import django.db.models.deletion +import flangr.posts.models + + +class Migration(migrations.Migration): + + dependencies = [ + ("posts", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="comment", + name="post", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="comments", + to="posts.post", + ), + ), + migrations.AlterField( + model_name="post", + name="img", + field=models.ImageField(upload_to=flangr.posts.models.get_img_location), + ), + ] diff --git a/flangr/posts/models.py b/flangr/posts/models.py index fa3446b..5799270 100644 --- a/flangr/posts/models.py +++ b/flangr/posts/models.py @@ -1,3 +1,5 @@ +import uuid + from django.db import models from django.conf import settings @@ -5,8 +7,13 @@ from django.conf import settings # Create your models here. +def get_img_location(instance, filename): + uid = uuid.uuid4() + return f"{uid[0:2]}/{uid[2:]}".replace("-", "") + + class Post(models.Model): - img = models.ImageField(upload_to="posts/%Y/%m") + img = models.ImageField(upload_to=get_img_location) posted = models.DateTimeField(auto_now_add=True) public = models.BooleanField(default=False) From f267d9d2e789da0f4d86bf326bd104b432ba7ac1 Mon Sep 17 00:00:00 2001 From: Maximilian Friedersdorff Date: Mon, 4 Jul 2022 22:42:20 +0100 Subject: [PATCH 6/6] Moar work --- flangr/posts/forms.py | 3 +++ flangr/posts/models.py | 4 ++-- flangr/posts/urls.py | 1 + flangr/posts/views.py | 10 +++++++++- flangr/templates/posts/post_detail.html | 6 ++++++ 5 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 flangr/posts/forms.py diff --git a/flangr/posts/forms.py b/flangr/posts/forms.py new file mode 100644 index 0000000..726a1c4 --- /dev/null +++ b/flangr/posts/forms.py @@ -0,0 +1,3 @@ +from django.forms import ModelForm + +from .models import Comment diff --git a/flangr/posts/models.py b/flangr/posts/models.py index 5799270..fa22ba2 100644 --- a/flangr/posts/models.py +++ b/flangr/posts/models.py @@ -8,8 +8,8 @@ from django.conf import settings def get_img_location(instance, filename): - uid = uuid.uuid4() - return f"{uid[0:2]}/{uid[2:]}".replace("-", "") + uid = uuid.uuid4().hex + return f"{uid[0:2]}/{uid[2:]}" class Post(models.Model): diff --git a/flangr/posts/urls.py b/flangr/posts/urls.py index 604330b..6bd7575 100644 --- a/flangr/posts/urls.py +++ b/flangr/posts/urls.py @@ -4,4 +4,5 @@ from . import views urlpatterns = [ path("post/", views.PostDetailView.as_view()), + path("post//comments", views.AddCommentView.as_view()), ] diff --git a/flangr/posts/views.py b/flangr/posts/views.py index d90837f..5fa1d08 100644 --- a/flangr/posts/views.py +++ b/flangr/posts/views.py @@ -1,9 +1,17 @@ from django.views.generic import DetailView +from django.forms import modelform_factory # Create your views here. -from .models import Post +from .models import Post, Comment class PostDetailView(DetailView): model = Post + + def get_context_data(self, **kwargs): + context = { + "add_comment_form": modelform_factory(Comment, fields=("comment",)), + **kwargs, + } + return super().get_context_data(**context) diff --git a/flangr/templates/posts/post_detail.html b/flangr/templates/posts/post_detail.html index 0ad7cae..d44eb00 100644 --- a/flangr/templates/posts/post_detail.html +++ b/flangr/templates/posts/post_detail.html @@ -11,4 +11,10 @@
  • {{ comment.user }} - {{ comment.comment }}
  • {% endfor %} +
    + {% csrf_token %} + {{ add_comment_form }} + +