From c66aea2a0ce1479d41627bf5bbf6bbe5c54d1cb2 Mon Sep 17 00:00:00 2001 From: tarpetos Date: Thu, 2 Feb 2023 18:26:35 +0200 Subject: [PATCH 1/2] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fed5aa9..e739e0c 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# First Django web application that is being developed by me \ No newline at end of file +# First Django web application
that is being developed by me \ No newline at end of file From 760536e8c7c7247cfce6d6dc27dc23f62fe5a97e Mon Sep 17 00:00:00 2001 From: tarpetos Date: Wed, 8 Feb 2023 18:02:06 +0200 Subject: [PATCH 2/2] Add migrations, change database from SQLite to PostreSQL --- .gitignore | 4 +- db.sqlite3 | Bin 131072 -> 0 bytes password_website/settings.py | 11 +++- password_website/urls.py | 5 +- requirements.txt | 9 +++ users/admin.py | 5 +- users/migrations/0001_initial.py | 27 ++++++++ users/migrations/0002_auto_20230207_1632.py | 32 +++++++++ users/migrations/0003_user_user_country.py | 19 ++++++ ...004_remove_country_users_country_number.py | 17 +++++ users/migrations/0005_auto_20230207_1703.py | 19 ++++++ users/models.py | 3 - users/models/__init__.py | 0 users/models/countries.py | 41 ++++++++++++ users/models/users.py | 61 ++++++++++++++++++ users/templates/users/pagination.html | 54 +++++++--------- users/templates/users/users_list.html | 56 ++++++++++++---- users/views/countries_views.py | 1 + users/views/users_views.py | 46 ++++++------- 19 files changed, 334 insertions(+), 76 deletions(-) delete mode 100644 db.sqlite3 create mode 100644 requirements.txt create mode 100644 users/migrations/0001_initial.py create mode 100644 users/migrations/0002_auto_20230207_1632.py create mode 100644 users/migrations/0003_user_user_country.py create mode 100644 users/migrations/0004_remove_country_users_country_number.py create mode 100644 users/migrations/0005_auto_20230207_1703.py delete mode 100644 users/models.py create mode 100644 users/models/__init__.py create mode 100644 users/models/countries.py create mode 100644 users/models/users.py diff --git a/.gitignore b/.gitignore index fed1b94..2e27876 100644 --- a/.gitignore +++ b/.gitignore @@ -159,4 +159,6 @@ dmypy.json # Cython debug symbols cython_debug/ -users/templates/templates/ \ No newline at end of file +media/ + +demo_data.json diff --git a/db.sqlite3 b/db.sqlite3 deleted file mode 100644 index f84873dea9f32fab1fe8c13007e5e74063618676..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 zcmeI5S&SpcdB@pglbnNO&AC01v>Faqv%AD-G`xqD;#i~Acs0>#*4o4J0x>#GvWMGi z9A3=$9+EE zBlLgvul3ocH?kF=|4NSg<8B}EJ@xkQ1er1UA7-PN{~TwIcn|;q5C8!X009sH0T2KI z5C8!X0D)gUfyMbKbvir!F(3H{@=;PHE3t3KJ`{T{`itlnqj#dY$QzN@BJYaKPJf-6 z-~$3600JNY0w4eaAOHd&@RkwC&IWy_SGPKPr(?95om487R*k07HMDvrmC3HB((9Q* zJe7Jnm3=ywdMcgIWYfiGXM(=Pi(A@3_a?PZs|Wj4t*fj1?bh9U>b~A?7^b(O9TR{wZXN8aO|7A;4ehR4*PFHO&7n@xxm3D%F-DzS7fw5g`Y#MZcsk0c1P8! zRaI}dTWz&LfonCrGpux}bhebqZcS5XJC?J8+SYF$7;Rmxw3=PL+3nuj*E=e$ugrjp zZ0V^|F`rEpo|~dBUbI}~o#oaCj5RGSC&!MbKX3h7ch_v|F~Vbygi=k(EM)7tM2 z7KC}o<_ek8g$e4xs_RtN=|OL3MtxLWGbgDcE#nJe>f{xxC>i0zZfg&$Z0f04%op;7 z7eYbb>cuT5Mn;kHZL|*icvZ%iI~|6%m`|6An>)dvPobKs4Wmh2WL3(O)=c{zuV<~& zr9DdBt7|p2a z8`Fnw7W1iWcEeAZ(j2@SkLdR-!)7j3%4|v$-KrPe=qKe0`C=|g{=yd`hd%Oe5tt7J)+9E&cdW@RMWcb02_DH; z+ai&`vKeHnITX*l2aysCWTomYtyybXOHX`lBs3ogtWSspzHY(REEc7}hGpF_YHf|J zfpli4sM8Rg@{^yEuaNJO*U2X_|Mzf45ClK~1V8`;KmY_l00ck)1V8`;ew73kR+4?nY1jOp?f);u zmVM-Bboc-7$!E#O$*ZJ6ULhArj;xRwBE^0d`$6ohu`k3v5qmY(jQw8hVk|>5-~$36 z00JNY0w4eaAOHd&00JN|P6Xy;X;lgx8u}eo%uJUSWGN|ys(M|ge^^39DrRKmCOwSa zk32OiOJ}4I`^yT#Z1I#VtxG}f&M}W&Sdyi*6cjEU3G-%xaO+5zTa=|WDac$qVrPjg zElV9yM)72`4;i zia$BPyzuZO*XQSM?CJM}B1;>RU-+`)!)Cm2Xvc>*RX_7;M+WEQ$#W9-Z0+I83-aWe zB-~n&0UjxQT9N)4d2*E=0I2r=iUHgIr+@Sx9}oZm5C8!X009sH0T2KI5C8!X0D&~?EL={Iq;GHB|j(sNq$1!AU`7CBi|xlC;v#kOkO8nAb(9hO+H0lBY#f* zjC`1Ufb_`wXa;;h00ck)1V8`;KmY_l00ck)1V8`;MiU4IBq_ASuL{4O;@3rX4KDEO zJipHI>nyvUHO8+|b`3=Mb(&wN_;r$9{S*8e=GPFv2Iat{B(qC^UHpN-!3m00ck)1V8`;KmY_l00cl_90=g=|BXW}q6{Da0w4eaAOHd&00JNY0w4ea zATXK$=KrJlAQc2a00ck)1V8`;KmY_l00ck)1jc~?=KteRizovKfB*=900@8p2!H?x zfB*=900@jGfcgJuK1c-t5C8!X009sH0T2KI5C8!X0D*BJfcgJ8)FR3N0w4eaAOHd& z00JNY0w4eaAOHfR2}HyH<(rZ};v-MQ{$=u8p)W=6L_Qc=2)-hJWcugUfBs+iFH3*w z`-bmr9$(Wx4ZZ4#LJ$N%00e$10=>7-g_ZZNOTCWKtm=2QgYHfBprg0dTDx_y-!bov zsu@)2O(~bnrz)w6deAg(d(G!BT-n~bwjIB|yYuq(?fA~_^V{!^C%jef6{FJFuAUcYoH z{?02qFKu195r1*}Mttk~waYuZ)X_`ZyVq#FTTNgv*Ol#eY+u>ly|8`N@hFCzHIn%A zEcFT(va`E$ZD;G!r5hr0`*~-3I)P&j&?uEmCN)Eo3@8|$DrAN85Xp3Mz0pj-cfX6$f!OlzhgLem@)d+*qQ9zA`?n4 zP?C<$*qR2Kp8d|ZE0MiCQXXN2Y<-vb70PxKf^p#~hVqM4DjNe;Bp z`ArO@KU9rq`}>Lbq1LY4)Y|7W`Fyhf-GpLgT8~eqS?h*QhsLVb)w@PR z?`KV7|NqSnov;T15C8!X009sH0T2KI5C8!X0D=F11fqe9zIo}akKBswM?W9=@zfhr zzdiYv6F-=k3;jDi2ha%oUEojre-pSNz3xAxX1}4I-a;{~Tun;75?`7W3pyR0@8hZZ z-F>62t88&a)$)}>rclVbP2yrfNNnD@6NlzE*B0G|Y}v^1EV@xwD1?<{QaU>4T$mEF z+cc_$Qe zF*!;5#hkluWb+~A;>vMFv=ymo`+hl{4Jq5pBQx=ZSu+p2oqm5Z6IPa&r9WJ;X|M$D zmEBAYVZq`b3dO$G>D+0x=~AM#5}D2v?KVPdzOHq;YQ0r6n$G1$x`Rs7jE>qlpo`n) zB6mf#j7m3$$mm$ib|;4x7w_g9eP z^Sfa8%~;XdIL$WNlfCoHVMV2z$S*rvO5b*{H|NR~y{MPH(jI+)G-rjeaj_!&952z6 zBawXnA3V+v34LJ0*%JCvy^2l`Z3BJthid@zwbE*;Z2QgmW)$a(XrpbFZ|RjTBP+g6 znJ-Nd-PZT%E8BYOW;`95ZVEPQy4s-MNVOXE@BKdJ1!50A>}-?s{DnZ_%pi*U;DN_# z8Mb%p^px`n{ck2G_RHSL6y083t0m%{hE}iB<5}^8X2+<}mvR3)MEt@F+ZSGBV}aBD zcit9HC6m41Rp_X;CG~FG?=&u#U+kgXdnhlxS1#xGGL^n)v!gjOJmPM>#~XSM=UJW| zZ?mC-7$y60X2&a@3M&;_m>Ul&jHnS+E9G^qns%Jy@Rs|xPFxJH&yy5Dd7>qsUkEEN z)6p{TDL9|IbnFu+rOkZ4l+WetmSkF-IT!+R#7Gp009sH0T2KI5C8!X009sH0T6H#!2I9M10fIq z0T2KI5C8!X009sH0T2KI5Ew@SnE#Jst)fgI00JNY0w4eaAOHd&00JNY0wCZffcd|h z2SOkK0w4eaAOHd&00JNY0w4eaATW*uqO4Fe<5)732?Rg@1V8`;KmY_l00ck)1V8`; zK)@ov=Ko8P-}jO4lh2YrB4zS4iNt;w`&{g!v36`X_Ec;x`XAA+MgJ=LYV=z4Oys{K z-;8`Fa-U|v2LwO>1V8`;KmY_l00ck)1Uv*1OF^Hsx*j?-^gF8f&FBkSGtR zn`Amfe@axRKcVfgGGqF7r%XHXV}}kqGsd!uFH*ZRYay*#bvmO#%VKSTTC8sdxhnBf zhwN8(`^rRIoJDTTQ{(hAK_Sm$E+o1#%$XU4PEQ7*)tMnVOEawHgG{i;nu&IrJ~l&5 zm(R&uIr}BMzGN1N6PkKvO%_tEbfJ-3#7qmJ&9V@pSn!c3wK%;hGci^&Q^D>ZkI=N0 zWPm@N|A<`w@jR56rs=Ee0rC94g%DucOqn)9LElD5;Niz6sm=1a0MpPnU?OZIUk@_Yk48mX(wdbmVRz2L^>^n#J*)hqL!;0 zOrX<@$?MzT{J&?wLJ$N%00ck)1V8`;KmY_l00ck)1jdj6=Ko_@sVEW%fB*=900@8p R2!H?xfB*=900?*p{2%&{-6;S7 diff --git a/password_website/settings.py b/password_website/settings.py index 68116f0..2c50e57 100644 --- a/password_website/settings.py +++ b/password_website/settings.py @@ -77,8 +77,12 @@ DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': os.environ.get('DATABASE_NAME'), + 'USER': os.environ.get('DATABASE_USER'), + 'PASSWORD': os.environ.get('DATABASE_PASSWORD'), + 'HOST': os.environ.get('DATABASE_HOST'), + 'PORT': os.environ.get('DATABASE_PORT'), } } @@ -120,3 +124,6 @@ # https://docs.djangoproject.com/en/2.2/howto/static-files/ STATIC_URL = '/static/' + +MEDIA_URL = '/media/' +MEDIA_ROOT = os.path.join(BASE_DIR, 'media') diff --git a/password_website/urls.py b/password_website/urls.py index 291462e..ca6dffc 100644 --- a/password_website/urls.py +++ b/password_website/urls.py @@ -13,10 +13,11 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ +from django.conf import settings +from django.conf.urls.static import static from django.contrib import admin from django.urls import path -# from users import views as user_views from users.views import users_views from users.views import usage_views from users.views import countries_views @@ -37,4 +38,4 @@ path('countries//delete', countries_views.countries_delete, name='countries_delete'), path('admin/', admin.site.urls), -] +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0473017 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,9 @@ +Django==2.2.28 +MarkupSafe==2.1.2 +Pillow==9.4.0 +pip==23.0 +pytz==2022.7.1 +setuptools==65.5.1 +sqlparse==0.4.3 +wheel==0.38.4 +psycopg2-binary>=2.8,<2.9 \ No newline at end of file diff --git a/users/admin.py b/users/admin.py index 8c38f3f..1035dc0 100644 --- a/users/admin.py +++ b/users/admin.py @@ -1,3 +1,6 @@ from django.contrib import admin +from .models.users import User +from .models.countries import Country -# Register your models here. +admin.site.register(User) +admin.site.register(Country) diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py new file mode 100644 index 0000000..b51694c --- /dev/null +++ b/users/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# Generated by Django 2.2.28 on 2023-02-03 19:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('first_name', models.CharField(max_length=256, verbose_name='First name')), + ('last_name', models.CharField(max_length=256, verbose_name='Last name')), + ('patronymic', models.CharField(blank=True, default='', max_length=256, verbose_name='Patronymic')), + ('birthday', models.DateField(null=True, verbose_name='Date of birth')), + ('photo', models.ImageField(blank=True, null=True, upload_to='', verbose_name='Photo')), + ('telegram_id', models.CharField(max_length=20, verbose_name='Telegram ID')), + ('notes', models.TextField(blank=True, verbose_name='Additional notes')), + ], + ), + ] diff --git a/users/migrations/0002_auto_20230207_1632.py b/users/migrations/0002_auto_20230207_1632.py new file mode 100644 index 0000000..98365f9 --- /dev/null +++ b/users/migrations/0002_auto_20230207_1632.py @@ -0,0 +1,32 @@ +# Generated by Django 2.2.28 on 2023-02-07 16:32 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='user', + options={'verbose_name': 'User', 'verbose_name_plural': 'Users'}, + ), + migrations.CreateModel( + name='Country', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('country_name', models.CharField(max_length=256, verbose_name='Country name')), + ('users_country_number', models.IntegerField(default=1, verbose_name='Country users')), + ('notes', models.TextField(blank=True, verbose_name='Additional notes')), + ('most_active', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.User', verbose_name='Capital')), + ], + options={ + 'verbose_name': 'Country', + 'verbose_name_plural': 'Countries', + }, + ), + ] diff --git a/users/migrations/0003_user_user_country.py b/users/migrations/0003_user_user_country.py new file mode 100644 index 0000000..330d1dd --- /dev/null +++ b/users/migrations/0003_user_user_country.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.28 on 2023-02-07 16:58 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0002_auto_20230207_1632'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='user_country', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='users.Country', verbose_name='Country'), + ), + ] diff --git a/users/migrations/0004_remove_country_users_country_number.py b/users/migrations/0004_remove_country_users_country_number.py new file mode 100644 index 0000000..5f19c2b --- /dev/null +++ b/users/migrations/0004_remove_country_users_country_number.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.28 on 2023-02-07 17:03 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0003_user_user_country'), + ] + + operations = [ + migrations.RemoveField( + model_name='country', + name='users_country_number', + ), + ] diff --git a/users/migrations/0005_auto_20230207_1703.py b/users/migrations/0005_auto_20230207_1703.py new file mode 100644 index 0000000..599811b --- /dev/null +++ b/users/migrations/0005_auto_20230207_1703.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.28 on 2023-02-07 17:03 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0004_remove_country_users_country_number'), + ] + + operations = [ + migrations.AlterField( + model_name='country', + name='most_active', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='users.User', verbose_name='Most active user'), + ), + ] diff --git a/users/models.py b/users/models.py deleted file mode 100644 index 71a8362..0000000 --- a/users/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/users/models/__init__.py b/users/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/users/models/countries.py b/users/models/countries.py new file mode 100644 index 0000000..253d7c4 --- /dev/null +++ b/users/models/countries.py @@ -0,0 +1,41 @@ +from django.db import models + +class Country(models.Model): + country_name = models.CharField( + max_length=256, + verbose_name='Country name', + ) + + most_active = models.OneToOneField( + 'User', + blank=True, + null=True, + on_delete=models.SET_NULL, + verbose_name='Most active user', + ) + + # users_country_number = models.IntegerField( + # blank=False, + # default = 1, + # verbose_name = 'Country users' + # ) + + + notes = models.TextField( + blank=True, + verbose_name='Additional notes' + ) + + class Meta: + verbose_name = 'Country' + verbose_name_plural = 'Countries' + + def __str__(self): + if self.most_active: + return '%s (%s %s)' % ( + self.country_name, + self.most_active.first_name, + self.most_active.last_name, + ) + else: + return '%s' % (self.country_name) diff --git a/users/models/users.py b/users/models/users.py new file mode 100644 index 0000000..41a2a2d --- /dev/null +++ b/users/models/users.py @@ -0,0 +1,61 @@ +from django.db import models + +class User(models.Model): + first_name = models.CharField( + max_length=256, + blank=False, + verbose_name='First name' + ) + + last_name = models.CharField( + max_length=256, + blank=False, + verbose_name='Last name' + ) + + patronymic = models.CharField( + max_length=256, + blank=True, + verbose_name='Patronymic', + default='' + ) + + birthday = models.DateField( + blank=False, + verbose_name='Date of birth', + null=True + ) + + photo = models.ImageField( + blank=True, + verbose_name='Photo', + null=True + ) + + telegram_id = models.CharField( + max_length=20, + blank=False, + verbose_name='Telegram ID' + ) + + user_country = models.ForeignKey( + 'Country', + verbose_name='Country', + blank=False, + null=True, + on_delete=models.PROTECT + ) + + notes = models.TextField( + blank=True, + verbose_name='Additional notes' + ) + + class Meta: + verbose_name = 'User' + verbose_name_plural = 'Users' + + def __str__(self): + full_name = '%s %s' % (self.first_name, self.last_name) + + return full_name.strip() diff --git a/users/templates/users/pagination.html b/users/templates/users/pagination.html index 48dc9cb..9178728 100644 --- a/users/templates/users/pagination.html +++ b/users/templates/users/pagination.html @@ -1,31 +1,27 @@ {% load static %} - \ No newline at end of file +{% if users.has_other_pages %} + {% with users_order=request.GET.order_by|default:'last_name' reverse=request.GET.reverse %} + + {% endwith %} +{% endif %} \ No newline at end of file diff --git a/users/templates/users/users_list.html b/users/templates/users/users_list.html index 26abba9..2033f5c 100644 --- a/users/templates/users/users_list.html +++ b/users/templates/users/users_list.html @@ -10,22 +10,54 @@ {% block content %} - - - - - - - - - - + {% with users_order=request.GET.order_by|default:'last_name' reverse=request.GET.reverse %} + + + + + + + + + + + {% endwith %} {% for user in users %} - + + {% if user.photo %} + + {% else %} + + {% endif %} + @@ -52,5 +84,3 @@ {% block pagination %} {% include "users/pagination.html" %} {% endblock pagination %} - -{#{% block footer %} {% endblock footer %}#} \ No newline at end of file diff --git a/users/views/countries_views.py b/users/views/countries_views.py index 62a3274..55c1d6e 100644 --- a/users/views/countries_views.py +++ b/users/views/countries_views.py @@ -1,5 +1,6 @@ from django.http import HttpResponse from django.shortcuts import render +from users.models.countries import Country def countries_list(request): diff --git a/users/views/users_views.py b/users/views/users_views.py index a2d6ea2..4db31a5 100644 --- a/users/views/users_views.py +++ b/users/views/users_views.py @@ -1,33 +1,29 @@ +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.shortcuts import render from django.http import HttpResponse +from users.models.users import User def users_list(request): - users = ( - { - 'id': 1, - 'first_name': 'Taras', - 'last_name': 'Hevlich', - 'telegram_id': 441547155, - 'image': '/img/taras_hevlich.png' - }, - - { - 'id': 2, - 'first_name': 'Polak', - 'last_name': 'Clever', - 'telegram_id': 321453123, - 'image': '/img/default.png' - }, - - { - 'id': 3, - 'first_name': 'Mateusz', - 'last_name': 'Kieliszkowski', - 'telegram_id': 435123555, - 'image': '/img/mateusz_kieliszkowski.png' - }, - ) + users = User.objects.all() + + users_order = request.GET.get('order_by', 'last_name') + + if users_order in ('last_name', 'first_name', 'telegram_id'): + users = users.order_by(users_order) + if request.GET.get('reverse', '') == '1': + users = users.reverse() + + paginator = Paginator(users, 4) + current_page = request.GET.get('page') + + try: + users = paginator.page(current_page) + except PageNotAnInteger: + users = paginator.page(1) + except EmptyPage: + users = paginator.page(paginator.num_pages) + return render(request, 'users/users_list.html', {'users': users})
PhotoLast Name ↑First NameTelegram IDActions
Photo + + Last Name + {% if users_order == 'last_name' and reverse != '1' %}↑ + {% elif users_order == 'last_name' and reverse == '1' %}↓ + {% endif %} + + + + First Name + {% if users_order == 'first_name' and reverse != '1' %}↑ + {% elif users_order == 'first_name' and reverse == '1' %}↓ + {% endif %} + + + + Telegram ID + {% if users_order == 'telegram_id' and reverse != '1' %}↑ + {% elif users_order == 'telegram_id' and reverse == '1' %}↓ + {% endif %} + + Actions
{{ forloop.counter }}{{ user.last_name }} {{ user.first_name }} {{ user.telegram_id }}