diff --git a/.gitignore b/.gitignore index 146e9c8..c16a5d9 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,4 @@ venv/ db.sqlite3 .idea/ +media/ diff --git a/articleapp/__pycache__/decorators.cpython-310.pyc b/articleapp/__pycache__/decorators.cpython-310.pyc new file mode 100644 index 0000000..c4a1775 Binary files /dev/null and b/articleapp/__pycache__/decorators.cpython-310.pyc differ diff --git a/articleapp/__pycache__/forms.cpython-310.pyc b/articleapp/__pycache__/forms.cpython-310.pyc new file mode 100644 index 0000000..40065d9 Binary files /dev/null and b/articleapp/__pycache__/forms.cpython-310.pyc differ diff --git a/articleapp/__pycache__/models.cpython-310.pyc b/articleapp/__pycache__/models.cpython-310.pyc index 53705c2..d46daa5 100644 Binary files a/articleapp/__pycache__/models.cpython-310.pyc and b/articleapp/__pycache__/models.cpython-310.pyc differ diff --git a/articleapp/__pycache__/urls.cpython-310.pyc b/articleapp/__pycache__/urls.cpython-310.pyc index 290bc68..f37bac5 100644 Binary files a/articleapp/__pycache__/urls.cpython-310.pyc and b/articleapp/__pycache__/urls.cpython-310.pyc differ diff --git a/articleapp/__pycache__/views.cpython-310.pyc b/articleapp/__pycache__/views.cpython-310.pyc new file mode 100644 index 0000000..adcb6a8 Binary files /dev/null and b/articleapp/__pycache__/views.cpython-310.pyc differ diff --git a/articleapp/decorators.py b/articleapp/decorators.py new file mode 100644 index 0000000..5bc3362 --- /dev/null +++ b/articleapp/decorators.py @@ -0,0 +1,12 @@ +from django.http import HttpResponseForbidden + +from articleapp.models import Article + + +def article_ownership_required(func): + def decorated(request,*args,**kwargs): + article = Article.objects.get(pk=kwargs['pk']) + if not article.writer == request.user: + return HttpResponseForbidden() + return func(request,*args,**kwargs) + return decorated \ No newline at end of file diff --git a/articleapp/forms.py b/articleapp/forms.py new file mode 100644 index 0000000..4f15eca --- /dev/null +++ b/articleapp/forms.py @@ -0,0 +1,9 @@ +from django.forms import ModelForm + +from articleapp.models import Article + + +class ArticleCreationForm(ModelForm): + class Meta: + model=Article + fields = ['title', 'image', 'content'] \ No newline at end of file diff --git a/articleapp/migrations/0001_initial.py b/articleapp/migrations/0001_initial.py new file mode 100644 index 0000000..3ce5d7e --- /dev/null +++ b/articleapp/migrations/0001_initial.py @@ -0,0 +1,28 @@ +# Generated by Django 4.1.4 on 2023-02-11 06:10 + +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='Article', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateField(auto_created=True, null=True)), + ('title', models.CharField(max_length=200, null=True)), + ('image', models.ImageField(upload_to='article/')), + ('content', models.TextField(null=True)), + ('writer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='article', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/articleapp/migrations/__pycache__/0001_initial.cpython-310.pyc b/articleapp/migrations/__pycache__/0001_initial.cpython-310.pyc new file mode 100644 index 0000000..0df335f Binary files /dev/null and b/articleapp/migrations/__pycache__/0001_initial.cpython-310.pyc differ diff --git a/articleapp/models.py b/articleapp/models.py index 71a8362..91fd297 100644 --- a/articleapp/models.py +++ b/articleapp/models.py @@ -1,3 +1,13 @@ +from django.contrib.auth.models import User from django.db import models # Create your models here. + +class Article(models.Model): + writer = models.ForeignKey(User, on_delete = models.SET_NULL, related_name='article', null=True) + + title = models.CharField(max_length=200, null=True) + image = models.ImageField(upload_to='article/', null=False) + content = models.TextField(null=True) + + created_at = models.DateField(auto_created=True,null=True) \ No newline at end of file diff --git a/articleapp/templates/articleapp/create.html b/articleapp/templates/articleapp/create.html new file mode 100644 index 0000000..2f62870 --- /dev/null +++ b/articleapp/templates/articleapp/create.html @@ -0,0 +1,16 @@ +{% extends 'base.html' %} +{% load bootstrap4 %} + +{% block content %} + +
+
{# margin bottom #} +

Article Create

+
+
+ {% csrf_token %} + {% bootstrap_form form %} + +
+
+{% endblock %} diff --git a/articleapp/templates/articleapp/delete.html b/articleapp/templates/articleapp/delete.html new file mode 100644 index 0000000..87905ad --- /dev/null +++ b/articleapp/templates/articleapp/delete.html @@ -0,0 +1,15 @@ +{% extends 'base.html'%} +{% load bootstrap4 %} + +{% block content %} + +
+
{# margin bottom #} +

Delete Article : {{ target_article.title }}

+
+
+ {% csrf_token %} + +
+
+{% endblock %} diff --git a/articleapp/templates/articleapp/detail.html b/articleapp/templates/articleapp/detail.html new file mode 100644 index 0000000..bddcb24 --- /dev/null +++ b/articleapp/templates/articleapp/detail.html @@ -0,0 +1,26 @@ +{% extends 'base.html' %} + +{% block content %} + +
+
+ +

+ {{ target_article.title }} +

+ + +

+ {{ target_article.content }} +

+ + +

Update Article

+
+ +

Delete Article

+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/articleapp/templates/articleapp/list.html b/articleapp/templates/articleapp/list.html index c6e7dc4..1fa9255 100644 --- a/articleapp/templates/articleapp/list.html +++ b/articleapp/templates/articleapp/list.html @@ -57,5 +57,12 @@ + +
+ + Create Article + +
+ {% endblock %} \ No newline at end of file diff --git a/articleapp/templates/articleapp/update.html b/articleapp/templates/articleapp/update.html new file mode 100644 index 0000000..1a42836 --- /dev/null +++ b/articleapp/templates/articleapp/update.html @@ -0,0 +1,16 @@ +{% extends 'base.html' %} +{% load bootstrap4 %} + +{% block content %} + +
+
{# margin bottom #} +

Article Update

+
+
+ {% csrf_token %} + {% bootstrap_form form %} + +
+
+{% endblock %} diff --git a/articleapp/urls.py b/articleapp/urls.py index 54b03b6..dde5e4a 100644 --- a/articleapp/urls.py +++ b/articleapp/urls.py @@ -1,6 +1,15 @@ from django.urls import path from django.views.generic import TemplateView +from articleapp.views import ArticleCreateView, ArticleDetailView, ArticleUpdateView, ArticleDeleteView + +app_name='articleapp' + urlpatterns = [ - path('list/', TemplateView.as_view(template_name='articleapp/list.html'), name='list') + path('list/', TemplateView.as_view(template_name='articleapp/list.html'), name='list'), + + path('create/', ArticleCreateView.as_view(), name='create'), + path('detail/', ArticleDetailView.as_view(), name='detail'), + path('update/', ArticleUpdateView.as_view(), name='update'), + path('delete/', ArticleDeleteView.as_view(), name='delete') ] \ No newline at end of file diff --git a/articleapp/views.py b/articleapp/views.py index 91ea44a..3f2b81a 100644 --- a/articleapp/views.py +++ b/articleapp/views.py @@ -1,3 +1,51 @@ +import form as form +from django.contrib.auth.decorators import login_required from django.shortcuts import render +from django.urls import reverse, reverse_lazy +from django.utils.decorators import method_decorator +from django.views.generic import CreateView, DetailView, UpdateView, DeleteView + +from articleapp.decorators import article_ownership_required +from articleapp.forms import ArticleCreationForm +from articleapp.models import Article + # Create your views here. + +@method_decorator(login_required, 'get') +@method_decorator(login_required, 'post') +class ArticleCreateView(CreateView): + model = Article + form_class = ArticleCreationForm + template_name = 'articleapp/create.html' + + def form_valid(self,form): + temp_article = form.save(commit=False) + temp_article.writer = self.request.user + return super().form_valid(form) + def get_success_url(self): + return reverse('articleapp:detail', kwargs={'pk':self.object.pk}) + +class ArticleDetailView(DetailView): + model = Article + context_object_name = 'target_article' + template_name = 'articleapp/detail.html' + +@method_decorator(article_ownership_required, 'get') +@method_decorator(article_ownership_required, 'post') +class ArticleUpdateView(UpdateView): + model = Article + form_class = ArticleCreationForm + context_object_name = 'target_article' + template_name = 'articleapp/update.html' + + def get_success_url(self): + return reverse('articleapp:detail', kwargs={'pk':self.object.pk}) + +@method_decorator(article_ownership_required, 'get') +@method_decorator(article_ownership_required, 'post') +class ArticleDeleteView(DeleteView): + model = Article + context_object_name = 'target_article' + template_name = 'articleapp/delete.html' + success_url = reverse_lazy('articleapp:list') \ No newline at end of file diff --git a/profileapp/migrations/0002_alter_profile_user.py b/profileapp/migrations/0002_alter_profile_user.py new file mode 100644 index 0000000..cc25dff --- /dev/null +++ b/profileapp/migrations/0002_alter_profile_user.py @@ -0,0 +1,21 @@ +# Generated by Django 4.1.4 on 2023-02-11 06:10 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('profileapp', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='profile', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/profileapp/migrations/__pycache__/0002_alter_profile_user.cpython-310.pyc b/profileapp/migrations/__pycache__/0002_alter_profile_user.cpython-310.pyc new file mode 100644 index 0000000..1597784 Binary files /dev/null and b/profileapp/migrations/__pycache__/0002_alter_profile_user.cpython-310.pyc differ diff --git a/templates/header.html b/templates/header.html index 5706315..a12c6d0 100644 --- a/templates/header.html +++ b/templates/header.html @@ -4,7 +4,9 @@

Pragmatic

- nav1 + + Articles + nav2 nav3 {% if not user.is_authenticated %}