From 5846bf026d16984977c8d3275d168620c2f6bc15 Mon Sep 17 00:00:00 2001 From: Daeyeon Kim Date: Sat, 11 Feb 2023 16:32:04 +0900 Subject: [PATCH] django course 35 commit --- .gitignore | 1 + .../__pycache__/decorators.cpython-310.pyc | Bin 0 -> 686 bytes articleapp/__pycache__/forms.cpython-310.pyc | Bin 0 -> 639 bytes articleapp/__pycache__/models.cpython-310.pyc | Bin 205 -> 753 bytes articleapp/__pycache__/urls.cpython-310.pyc | Bin 370 -> 704 bytes articleapp/__pycache__/views.cpython-310.pyc | Bin 0 -> 2379 bytes articleapp/decorators.py | 12 +++++ articleapp/forms.py | 9 ++++ articleapp/migrations/0001_initial.py | 28 ++++++++++ .../__pycache__/0001_initial.cpython-310.pyc | Bin 0 -> 1110 bytes articleapp/models.py | 10 ++++ articleapp/templates/articleapp/create.html | 16 ++++++ articleapp/templates/articleapp/delete.html | 15 ++++++ articleapp/templates/articleapp/detail.html | 26 ++++++++++ articleapp/templates/articleapp/list.html | 7 +++ articleapp/templates/articleapp/update.html | 16 ++++++ articleapp/urls.py | 11 +++- articleapp/views.py | 48 ++++++++++++++++++ .../migrations/0002_alter_profile_user.py | 21 ++++++++ .../0002_alter_profile_user.cpython-310.pyc | Bin 0 -> 813 bytes templates/header.html | 4 +- 21 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 articleapp/__pycache__/decorators.cpython-310.pyc create mode 100644 articleapp/__pycache__/forms.cpython-310.pyc create mode 100644 articleapp/__pycache__/views.cpython-310.pyc create mode 100644 articleapp/decorators.py create mode 100644 articleapp/forms.py create mode 100644 articleapp/migrations/0001_initial.py create mode 100644 articleapp/migrations/__pycache__/0001_initial.cpython-310.pyc create mode 100644 articleapp/templates/articleapp/create.html create mode 100644 articleapp/templates/articleapp/delete.html create mode 100644 articleapp/templates/articleapp/detail.html create mode 100644 articleapp/templates/articleapp/update.html create mode 100644 profileapp/migrations/0002_alter_profile_user.py create mode 100644 profileapp/migrations/__pycache__/0002_alter_profile_user.cpython-310.pyc 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 0000000000000000000000000000000000000000..c4a17754436af96441fe600a843f6a299ad81114 GIT binary patch literal 686 zcmZ`%v2N5r5Zzh(>;rs2P67!U8X6b)1EMH^kbokJqC_+&OOfN<`0TT9o!LE|f}Dzz zpn;D-H2I}%DGC;vE<8h` zK`N?jS*XEHTg-|kqYb4)nXGM7A#;V9QK*yl(%u?eDMD&Qj|rv_K>!co{j(wKRIQi9 zH!s^$*JX)PBzv{Wvs&*bH~DzaO~Uam9k}DbeZYwW_X_s$|H}n*uieHX@JBc$<1ilC wJKJfJIlX?rC%f}!j-*jS*1BJCpRuLuIeX|i$9ojEs^z}>LA0ZZSi~dmHS5PU=>4iKy$1E2;EVWeRY*7pBfLtuhR53J2#Ljy(jWNK7S( z8Gxx|0A@=TbIAegxxE$Q(kM~qRf*(3IQEM>*uW|1Z4Ss+8vBv~j6Waz0~?N2Eh6sx zI{r$Nyzs34>p^UwEzGB literal 0 HcmV?d00001 diff --git a/articleapp/__pycache__/models.cpython-310.pyc b/articleapp/__pycache__/models.cpython-310.pyc index 53705c24edab90cad1d940931e563852c6a235ad..d46daa5a381fba5bfd6625886c049eb4e15f794b 100644 GIT binary patch literal 753 zcmYjP&2H2%5VrH5G`k>#kmwuavZz;tP*I@;v8*a}%OQ$nx$$T>D<|1HUeVLcjJ9?b6@yZBn$5G4#}wTt~*e826ZbycBKtJTmgbp+}&q1 zKyoTb?$}b`qYVTVj&KiN9wLf_hsZxTd5kC#fe1x}=m=4YnfO5S3Hnp?9g$$>kvKvz zsR`dGU6m5@kPpr>b4}bf3^joUlPZv0gJ2D>!FbJ1%KM)vD056w^E)P?S?RS3G4wSW zOT0M8Y`ojbmJ6oaKAF+sa7@Z~x@DyTTec4_vd1Q3Jp*GVVGKL6lYoB8*zJx>%gvZ_ zk;EkDt%7RRe1yGnY#_RNw`7a!`P>9wRHZ?g_-xJ9c?D7!Usqa!Nj}tk1!JhPzKNG` zr-w*bwvC2HoA@ni>SK8_3S?aWAnG|1_2%#UvzLW^xUQIA6qoxFnd(c`ZlKg%AvU~O zwIeLHimz&p-7Utx@a?u39(%UkD?3E?jk^?0M4r;AGo>kg;`EtC7MSCq-ptBV)y)hW tx1J3JhF_1z55&#T8~>9XrT+eZ$%A){Bqn+_boMn4HR&vQN>cjF`v>Q0%u@gW delta 158 zcmey!dX}+1pO=@50SFlXJxI0z(vLwLWWWUEH~?|60FX#wNMX!j$YqRTWMoKT3TDt` zehCz1&}6*DmYbiFnp5nj$#jb|B`Yy6Jzp;+sR*QbB|{MlkOC9GJe;j!LW@(2ier4- fV*)CZC+jd-ir(U|0qQQzNws4HDl7(R5?}xTaoiz4 diff --git a/articleapp/__pycache__/urls.cpython-310.pyc b/articleapp/__pycache__/urls.cpython-310.pyc index 290bc689b78ce692a64246aa899e1471b1fb9435..f37bac5cb741d789299007e04ee48454f8423b76 100644 GIT binary patch literal 704 zcmZXR&x+eH5XL3{kK;7iHiy1KF3x>fmX?(6rIdwsdoYGYSVQ7eN{pm*S--kMPSd~DpOYi zRtg6AjNXA^wZOV(bkp$vs|57jY|8pxtZCX%)Y>fD`4KIVNo9_cUG1c_0F6(UoUOcgLZo844ou;fG5z_NumcI7nvRNE!(a4`9TS- z+?A4IK9Fy2R-Lb52db`=kEz*lfV@kqz+n|)h%m%1*u;(8PZBeIi*`2Dx@SG3cxtUqZ{ z{pz^b#-aZ~A}qm_#c8$`OKfg4;vMBAE_V&@s#;R#^`yZYW?fTW(&SCU*HtTN^LFBM zKk4vJvcgx4yrH^DkM|7ksnukSuNl6n){{Q(GfOt5Em{lP%o z3&!uDY(;cY)|LLk;TyQOSDxvK;!IDhqJC9&$}^kq*|R3ranHJ3Dfes%_S_ou|3>ev z(SYSED&3DK0m!3S3{s$^4ss$S4D7rC@>qhFxnDAY3g@S|rI*O;AQgd-Q3_#}!oba2 zJ0QbM{u0ZRy!DgJ!dMmji>au{l`Qt)E%!pm;z-FLJ(=J$2l2FO#`=$i)?6E>lcy;p zc&Jf|b7x;>xjRjD7LhO2&nXxB8)T%#nXtGm9q!5+uM5T-udO{MY~h@H+!L;-om;&5 z+Hx)4LTu{!YV~R3(R`z{HJnZ#N5;|NL6)eu-B+l?@SBJ-vfIpf^jsDHFguH$NafWkE&!#xF_7IBT zI8?D1ICw&;z1$@k_cNJHgVNLsmN$bSQlZvCaAEzsyYpoH0uBPBB@jmR17B@fvkrf zk}eKSw|bWAxXfj~-E)m5LgBTK0N%!-35javqG%EbzNFizhk?P59;iIJ1o2x`kXhFfgi-`Z zb32d^QCkJ_GC^cR;ExcsMg*}|NtDaxeG^1XdTi_l#Cf+;xGL7!Xwbaf(WQGev?gy? zs`S0Seuulh#-ZtF{;C)lkbH0#?&6d`D7x8@G7;jJ!*G@z46lBxG*Bkxy>gR2NFj@6 znFfc%?NW?gLYw{q#;(mvaTY6Gy^DHa-Y>O9i`!BmQgvH{?Ih~?h*MZ@}ml3P=9df2sn*2A%dNkY6= P^H`tt{9^W+9%}vv*g8b{ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..0df335fffd031f5204bf291a2a73ae7bc15a2c9a GIT binary patch literal 1110 zcmYjQOHbS|5RRQ}HpwoqJf&W^Zx2AP2vtyCMFolq92%`;g?I=_^VmAx!g6h|{DU6a zWB*BigRebQ`~?oB<0L#B*_v-W@qF`*T}(`P29C8?e?w{+#vcuy5A+%9ILlRBxWP$k zWW*;#+cc$_>6@A5TNO6bmT&JG+~Tco25*6xw7;5uo14c*-@e8FjXqIM2~x&+RQ9Rz zvN#ffjElTfc2;mm%fnE|Js*<@)^V2KaRI|8-0&$Uz6sWk7T8JqCy9vffR(tMaud9y z!wG)Kg4;LNIpuBibt|89LlL`(C%A{6PKCROC;0@Qydk(dg=h-*dKH>R)Z+xElbOUz zW|KKSqjU0EeR5>;xf_bv=lML=xS-sFhk{O2dqc=LOhM6@?#2?HK^_v5NAaREDthJUK7p&*{8xq5tNmW(p0r%EK|7sjh;%& z;EJV?NAf~w$y5u^j^Nq}Y8uO^y*nDFMZlRXR68tk3AyZ(I@-Pzu>_&oO?cm`{ce#n z>5rK1$k?lSgy6r?&BQ9I6KiM0w- z^PDR$gW)hZ!$1y0$T{TUSWvw+wQ+j#mYp7Ne_#jix3>3H_c0=dQgt>fArJJ$5&EL4 z?wdH;K#6xWALVW#-NxL!2t;jqds>&qeF9gqaqkoY;wXQIy|8%_!O=LxoY|2m5(s5EsLyQRU?_qp z!>b<-8o^P6!P9dXtgNiOVvSBq!?9>#5(j6wSQ!@eOzYliQ8Gt+q(>(4TO{<(`sdtN zv3*B%>WoX+>GN7oxAE|^O8Q!}7mv=R`Ux&QR4iWV%5>(Z8f$9>eacy@`}>+8DmA$- Ja&gFl`5!IsMjrqG literal 0 HcmV?d00001 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 @@ + + + {% 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 0000000000000000000000000000000000000000..1597784a8c3c5e1f264febf9a665b4682f9f9c46 GIT binary patch literal 813 zcmYjPxo+D)5Z!~MC|ZhL7=cqHy&AzzX&8Y8NpT8ah^>You%Njkg#@qcQV3ipt^Xk@ z^Gn;N2=WU7a?FzQF~AOH-VS%>&0{qj1_bTs;AfICLVnofsX3S&h?$^BS1NAO zs?^3SDhathPi);&^D#Nbqi5)VgjAA{0srcNn|a@;q$?Kou$M2H*V>?Bys%4r(T-Ro>zrTMV(lTw*I5)k`jd9i*)QFpY zRSKLE8ZZL|dE9^$Wn6$^O@-G%%b`P@7I&8^x#LYP1ZtXt=R@j!@=>o~Wy zLMV<5&9450lf*Z8FQJA~LYdqu)P|Vt$>RE*SX|BDi?fT_{L~B{DpJrUnB)zpx3;6Q zx|!ic3D*_67BimA;&N3PCU1=2(!kA|-gI&`oy_JYsA|}#@tvrb_(1D^%jsdXK>j*9 zJ&7)FlMk^fE>)F5(&(sra+5~2idO{+nqYLl)96v;2)FxM#CA%tDG+wE zciSM~j5>cEk5NYVsPo7F*H(;tv(>d6Csn!Z*3#b~@}}Kj$Nj|vIPU(e@jYX;XQ|nK bk0iV36=KFe>eP8dG1GRW0o$QIea`;_8-(Yx literal 0 HcmV?d00001 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 %}