diff --git a/imageuploader/pictures/__init__.py b/imageuploader/pictures/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/imageuploader/pictures/__pycache__/__init__.cpython-313.pyc b/imageuploader/pictures/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9bbe52a22f064f48c1b82cc0ada72dc3d8bb83f3 Binary files /dev/null and b/imageuploader/pictures/__pycache__/__init__.cpython-313.pyc differ diff --git a/imageuploader/pictures/__pycache__/admin.cpython-313.pyc b/imageuploader/pictures/__pycache__/admin.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4917768c6fb9e9c5917537201cbce6fb0337ebbc Binary files /dev/null and b/imageuploader/pictures/__pycache__/admin.cpython-313.pyc differ diff --git a/imageuploader/pictures/__pycache__/apps.cpython-313.pyc b/imageuploader/pictures/__pycache__/apps.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf2f236a9f67da466e76327eca0189bf5928d727 Binary files /dev/null and b/imageuploader/pictures/__pycache__/apps.cpython-313.pyc differ diff --git a/imageuploader/pictures/__pycache__/forms.cpython-313.pyc b/imageuploader/pictures/__pycache__/forms.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43537214a77a2d0b4d53cbb7ebc03278f7ad8ee7 Binary files /dev/null and b/imageuploader/pictures/__pycache__/forms.cpython-313.pyc differ diff --git a/imageuploader/pictures/__pycache__/models.cpython-313.pyc b/imageuploader/pictures/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f6c0a46293e668f1281cb5cd0f1d5840ba5f9c86 Binary files /dev/null and b/imageuploader/pictures/__pycache__/models.cpython-313.pyc differ diff --git a/imageuploader/pictures/__pycache__/urls.cpython-313.pyc b/imageuploader/pictures/__pycache__/urls.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c3110390a56b093c75efa8d3646973991d44ac3 Binary files /dev/null and b/imageuploader/pictures/__pycache__/urls.cpython-313.pyc differ diff --git a/imageuploader/pictures/__pycache__/views.cpython-313.pyc b/imageuploader/pictures/__pycache__/views.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..588b26383ed22003960d4cea1036e80d4e9e7d9c Binary files /dev/null and b/imageuploader/pictures/__pycache__/views.cpython-313.pyc differ diff --git a/imageuploader/pictures/admin.py b/imageuploader/pictures/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..112f607b0ae6b041b368f0d7e6c71a308219c824 --- /dev/null +++ b/imageuploader/pictures/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from .models import Post + +admin.site.register(Post) \ No newline at end of file diff --git a/imageuploader/pictures/apps.py b/imageuploader/pictures/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..b38c60c813aa6e2c1f0c3e49db1b96f87c90f09b --- /dev/null +++ b/imageuploader/pictures/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PostsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'pictures' diff --git a/imageuploader/pictures/forms.py b/imageuploader/pictures/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..37e0e85d4c55a4a592f1557af488cef781b2f46d --- /dev/null +++ b/imageuploader/pictures/forms.py @@ -0,0 +1,7 @@ +from django import forms +from . import models + +class CreatePost(forms.ModelForm): + class Meta: + model = models.Post + fields = ['title','body','slug','banner'] \ No newline at end of file diff --git a/imageuploader/pictures/migrations/0001_initial.py b/imageuploader/pictures/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..6297b539a90c5d786f688fdc538491aa1e384958 --- /dev/null +++ b/imageuploader/pictures/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# Generated by Django 5.2 on 2025-04-05 09:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Post', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=75)), + ('body', models.TextField()), + ('slug', models.SlugField()), + ('date', models.DateTimeField(auto_now_add=True)), + ], + ), + ] diff --git a/imageuploader/pictures/migrations/0002_post_banner.py b/imageuploader/pictures/migrations/0002_post_banner.py new file mode 100644 index 0000000000000000000000000000000000000000..912685a8f0ec9ff4ab54e864ea57f2d459890616 --- /dev/null +++ b/imageuploader/pictures/migrations/0002_post_banner.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2 on 2025-04-05 12:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('posts', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='post', + name='banner', + field=models.ImageField(blank=True, default='fallback.png', upload_to=''), + ), + ] diff --git a/imageuploader/pictures/migrations/0003_post_author.py b/imageuploader/pictures/migrations/0003_post_author.py new file mode 100644 index 0000000000000000000000000000000000000000..3413a526c9c3ee972ca62992e6c722b630896e28 --- /dev/null +++ b/imageuploader/pictures/migrations/0003_post_author.py @@ -0,0 +1,21 @@ +# Generated by Django 5.2 on 2025-04-05 15:06 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('posts', '0002_post_banner'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name='post', + name='author', + field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/imageuploader/pictures/migrations/0004_alter_post_author.py b/imageuploader/pictures/migrations/0004_alter_post_author.py new file mode 100644 index 0000000000000000000000000000000000000000..d89258f9cc15fa456494da64026398ba84dc873f --- /dev/null +++ b/imageuploader/pictures/migrations/0004_alter_post_author.py @@ -0,0 +1,21 @@ +# Generated by Django 5.2 on 2025-04-05 15:14 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('posts', '0003_post_author'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AlterField( + model_name='post', + name='author', + field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/imageuploader/pictures/migrations/__init__.py b/imageuploader/pictures/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/imageuploader/pictures/migrations/__pycache__/0001_initial.cpython-313.pyc b/imageuploader/pictures/migrations/__pycache__/0001_initial.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e977a8357823b3158c2349cd2b0c73a5dd205bd Binary files /dev/null and b/imageuploader/pictures/migrations/__pycache__/0001_initial.cpython-313.pyc differ diff --git a/imageuploader/pictures/migrations/__pycache__/0002_post_banner.cpython-313.pyc b/imageuploader/pictures/migrations/__pycache__/0002_post_banner.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5a736588e1ecc08fe2868920dae4005e0a30e248 Binary files /dev/null and b/imageuploader/pictures/migrations/__pycache__/0002_post_banner.cpython-313.pyc differ diff --git a/imageuploader/pictures/migrations/__pycache__/0003_post_author.cpython-313.pyc b/imageuploader/pictures/migrations/__pycache__/0003_post_author.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61d358c9351fe2644f2a6c4bba479d6161439646 Binary files /dev/null and b/imageuploader/pictures/migrations/__pycache__/0003_post_author.cpython-313.pyc differ diff --git a/imageuploader/pictures/migrations/__pycache__/0004_alter_post_author.cpython-313.pyc b/imageuploader/pictures/migrations/__pycache__/0004_alter_post_author.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7592ef74e81f97843e50507d3a713fe836433b0 Binary files /dev/null and b/imageuploader/pictures/migrations/__pycache__/0004_alter_post_author.cpython-313.pyc differ diff --git a/imageuploader/pictures/migrations/__pycache__/__init__.cpython-313.pyc b/imageuploader/pictures/migrations/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bcc84e21da6819ac225362e4b4645aa14d92499e Binary files /dev/null and b/imageuploader/pictures/migrations/__pycache__/__init__.cpython-313.pyc differ diff --git a/imageuploader/pictures/models.py b/imageuploader/pictures/models.py new file mode 100644 index 0000000000000000000000000000000000000000..e255e6f858177ec3fc9efdef274bb82c85d22a9c --- /dev/null +++ b/imageuploader/pictures/models.py @@ -0,0 +1,13 @@ +from django.db import models +from django.contrib.auth.models import User + +class Picture(models.Model): + title = models.CharField(max_length=75) + body = models.TextField() + slug = models.SlugField() + date = models.DateTimeField(auto_now_add=True) + banner = models.ImageField(default='fallback.png', blank=True) + author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, default=None) + + def __str__(self): + return self.title \ No newline at end of file diff --git a/imageuploader/pictures/templates/posts/picture_new.html b/imageuploader/pictures/templates/posts/picture_new.html new file mode 100644 index 0000000000000000000000000000000000000000..11741b0d2db1fb602ce6fd4cf321ea96888b2efd --- /dev/null +++ b/imageuploader/pictures/templates/posts/picture_new.html @@ -0,0 +1,16 @@ +{% extends 'layout.html' %} + +{% block title %} + New Picture +{% endblock %} + +{% block content %} + <section> + <h1>New Picture</h1> + <form class="form-with-validation" action="{% url 'posts:new-picture' %}" method="post" enctype="multipart/form-data"> + {% csrf_token %} + {{ form }} + <button class="form-submit">Add Picture</button> + </form> + </section> +{% endblock %} \ No newline at end of file diff --git a/imageuploader/pictures/templates/posts/picture_page.html b/imageuploader/pictures/templates/posts/picture_page.html new file mode 100644 index 0000000000000000000000000000000000000000..d828673b8fa8a2a9e5789470771bbf21e93f5c15 --- /dev/null +++ b/imageuploader/pictures/templates/posts/picture_page.html @@ -0,0 +1,21 @@ +{% extends 'layout.html' %} + +{% block title %} + {{ picture.title }} +{% endblock %} + +{% block content %} + <section> + <img + class="banner" + src="{{ picture.banner.url }}" + alt="{{ picture.title }}" + /> + <h1> + {{ picture.title }} + </h1> + <p>{{ picture.date }}</p> + <p>{{ picture.body }}</p> + + </section> +{% endblock %} \ No newline at end of file diff --git a/imageuploader/pictures/templates/posts/pictures_list.html b/imageuploader/pictures/templates/posts/pictures_list.html new file mode 100644 index 0000000000000000000000000000000000000000..b17308ecfbbea10327bcb6a3a427e83ffeab20b5 --- /dev/null +++ b/imageuploader/pictures/templates/posts/pictures_list.html @@ -0,0 +1,23 @@ +{% extends 'layout.html' %} + +{% block title %} + Pictures +{% endblock %} + +{% block content %} + <section> + <h1>Pictures</h1> + + {% for picture in pictures %} + <article class="post"> + <h2> + <a href="{% url 'pictures:page' slug=picture.slug %}"> + {{ picture.title }} + </a> + </h2> + <p>{{ picture.date }} by {{ picture.author }}</p> + <p>{{ picture.body }}</p> + </article> + {% endfor %} +</section> +{% endblock %} \ No newline at end of file diff --git a/imageuploader/pictures/tests.py b/imageuploader/pictures/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/imageuploader/pictures/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/imageuploader/pictures/urls.py b/imageuploader/pictures/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..2ea0e738b620b5a5f3af7ddb3268e2b8e9292aba --- /dev/null +++ b/imageuploader/pictures/urls.py @@ -0,0 +1,11 @@ +from django.contrib import admin +from django.urls import path +from . import views + +app_name = "pictures" + +urlpatterns = [ + path("", views.pictures_list, name="list"), + path('new-picture/', views.picture_new, name="new-picture"), + path("<slug:slug>", views.picture_page, name="page") +] \ No newline at end of file diff --git a/imageuploader/pictures/views.py b/imageuploader/pictures/views.py new file mode 100644 index 0000000000000000000000000000000000000000..e5818e1fabf516795b7640dbee9e7d7eb598ce83 --- /dev/null +++ b/imageuploader/pictures/views.py @@ -0,0 +1,28 @@ +from django.shortcuts import render, redirect +from .models import Post +from django.contrib.auth.decorators import login_required +from . import forms + + + +def pictures_list(request): + pictures = Post.objects.all().order_by('-date') + return render(request, 'posts/posts_list.html', {'pictures': pictures}) + + +def picture_page(request, slug): + picture = Post.objects.get(slug=slug) + return render(request, 'pictures/picture_page.html', {'picture': picture}) + +@login_required(login_url="/users/login/") +def picture_new(request): + if request.method == 'POST': + form = forms.CreatePost(request.POST, request.FILES) + if form.is_valid(): + newpicture = form.save(commit=False) + newpicture.author = request.user + newpicture.save() + return redirect('pictures:list') + else: + form = forms.CreatePost() + return render(request, 'pictures/picture_new.html', { 'form': form }) \ No newline at end of file