Whole app
This commit is contained in:
		
						commit
						3a649df550
					
				
							
								
								
									
										259
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,259 @@ | ||||
| 
 | ||||
| # Byte-compiled / optimized / DLL files | ||||
| __pycache__/ | ||||
| *.py[cod] | ||||
| *$py.class | ||||
| 
 | ||||
| # C extensions | ||||
| *.so | ||||
| 
 | ||||
| # Distribution / packaging | ||||
| .Python | ||||
| build/ | ||||
| develop-eggs/ | ||||
| dist/ | ||||
| downloads/ | ||||
| eggs/ | ||||
| .eggs/ | ||||
| lib/ | ||||
| lib64/ | ||||
| parts/ | ||||
| sdist/ | ||||
| var/ | ||||
| wheels/ | ||||
| share/python-wheels/ | ||||
| *.egg-info/ | ||||
| .installed.cfg | ||||
| *.egg | ||||
| MANIFEST | ||||
| 
 | ||||
| # PyInstaller | ||||
| #  Usually these files are written by a python script from a template | ||||
| #  before PyInstaller builds the exe, so as to inject date/other infos into it. | ||||
| *.manifest | ||||
| *.spec | ||||
| 
 | ||||
| # Installer logs | ||||
| pip-log.txt | ||||
| pip-delete-this-directory.txt | ||||
| 
 | ||||
| # Unit test / coverage reports | ||||
| htmlcov/ | ||||
| .tox/ | ||||
| .nox/ | ||||
| .coverage | ||||
| .coverage.* | ||||
| .cache | ||||
| nosetests.xml | ||||
| coverage.xml | ||||
| *.cover | ||||
| *.py,cover | ||||
| .hypothesis/ | ||||
| .pytest_cache/ | ||||
| cover/ | ||||
| 
 | ||||
| # Translations | ||||
| *.mo | ||||
| *.pot | ||||
| 
 | ||||
| # Django stuff: | ||||
| *.log | ||||
| local_settings.py | ||||
| db.sqlite3 | ||||
| db.sqlite3-journal | ||||
| 
 | ||||
| # Flask stuff: | ||||
| instance/ | ||||
| .webassets-cache | ||||
| 
 | ||||
| # Scrapy stuff: | ||||
| .scrapy | ||||
| 
 | ||||
| # Sphinx documentation | ||||
| docs/_build/ | ||||
| 
 | ||||
| # PyBuilder | ||||
| .pybuilder/ | ||||
| target/ | ||||
| 
 | ||||
| # Jupyter Notebook | ||||
| .ipynb_checkpoints | ||||
| 
 | ||||
| # IPython | ||||
| profile_default/ | ||||
| ipython_config.py | ||||
| 
 | ||||
| # pyenv | ||||
| #   For a library or package, you might want to ignore these files since the code is | ||||
| #   intended to run in multiple environments; otherwise, check them in: | ||||
| # .python-version | ||||
| 
 | ||||
| # pipenv | ||||
| #   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||||
| #   However, in case of collaboration, if having platform-specific dependencies or dependencies | ||||
| #   having no cross-platform support, pipenv may install dependencies that don't work, or not | ||||
| #   install all needed dependencies. | ||||
| #Pipfile.lock | ||||
| 
 | ||||
| # PEP 582; used by e.g. github.com/David-OConnor/pyflow | ||||
| __pypackages__/ | ||||
| 
 | ||||
| # Celery stuff | ||||
| celerybeat-schedule | ||||
| celerybeat.pid | ||||
| 
 | ||||
| # SageMath parsed files | ||||
| *.sage.py | ||||
| 
 | ||||
| # Environments | ||||
| .env | ||||
| .venv | ||||
| env/ | ||||
| venv/ | ||||
| ENV/ | ||||
| env.bak/ | ||||
| venv.bak/ | ||||
| 
 | ||||
| # Spyder project settings | ||||
| .spyderproject | ||||
| .spyproject | ||||
| 
 | ||||
| # Rope project settings | ||||
| .ropeproject | ||||
| 
 | ||||
| # mkdocs documentation | ||||
| /site | ||||
| 
 | ||||
| # mypy | ||||
| .mypy_cache/ | ||||
| .dmypy.json | ||||
| dmypy.json | ||||
| 
 | ||||
| # Pyre type checker | ||||
| .pyre/ | ||||
| 
 | ||||
| # pytype static type analyzer | ||||
| .pytype/ | ||||
| 
 | ||||
| # Cython debug symbols | ||||
| cython_debug/ | ||||
| 
 | ||||
| # Logs | ||||
| logs | ||||
| *.log | ||||
| npm-debug.log* | ||||
| yarn-debug.log* | ||||
| yarn-error.log* | ||||
| lerna-debug.log* | ||||
| 
 | ||||
| # Diagnostic reports (https://nodejs.org/api/report.html) | ||||
| report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | ||||
| 
 | ||||
| # Runtime data | ||||
| pids | ||||
| *.pid | ||||
| *.seed | ||||
| *.pid.lock | ||||
| 
 | ||||
| # Directory for instrumented libs generated by jscoverage/JSCover | ||||
| lib-cov | ||||
| 
 | ||||
| # Coverage directory used by tools like istanbul | ||||
| coverage | ||||
| *.lcov | ||||
| 
 | ||||
| # nyc test coverage | ||||
| .nyc_output | ||||
| 
 | ||||
| # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | ||||
| .grunt | ||||
| 
 | ||||
| # Bower dependency directory (https://bower.io/) | ||||
| bower_components | ||||
| 
 | ||||
| # node-waf configuration | ||||
| .lock-wscript | ||||
| 
 | ||||
| # Compiled binary addons (https://nodejs.org/api/addons.html) | ||||
| build/Release | ||||
| 
 | ||||
| # Dependency directories | ||||
| node_modules/ | ||||
| jspm_packages/ | ||||
| 
 | ||||
| # Snowpack dependency directory (https://snowpack.dev/) | ||||
| web_modules/ | ||||
| 
 | ||||
| # TypeScript cache | ||||
| *.tsbuildinfo | ||||
| 
 | ||||
| # Optional npm cache directory | ||||
| .npm | ||||
| 
 | ||||
| # Optional eslint cache | ||||
| .eslintcache | ||||
| 
 | ||||
| # Microbundle cache | ||||
| .rpt2_cache/ | ||||
| .rts2_cache_cjs/ | ||||
| .rts2_cache_es/ | ||||
| .rts2_cache_umd/ | ||||
| 
 | ||||
| # Optional REPL history | ||||
| .node_repl_history | ||||
| 
 | ||||
| # Output of 'npm pack' | ||||
| *.tgz | ||||
| 
 | ||||
| # Yarn Integrity file | ||||
| .yarn-integrity | ||||
| 
 | ||||
| # dotenv environment variables file | ||||
| .env | ||||
| .env.test | ||||
| 
 | ||||
| # parcel-bundler cache (https://parceljs.org/) | ||||
| .cache | ||||
| .parcel-cache | ||||
| 
 | ||||
| # Next.js build output | ||||
| .next | ||||
| out | ||||
| 
 | ||||
| # Nuxt.js build / generate output | ||||
| .nuxt | ||||
| dist | ||||
| 
 | ||||
| # Gatsby files | ||||
| .cache/ | ||||
| # Comment in the public line in if your project uses Gatsby and not Next.js | ||||
| # https://nextjs.org/blog/next-9-1#public-directory-support | ||||
| # public | ||||
| 
 | ||||
| # vuepress build output | ||||
| .vuepress/dist | ||||
| 
 | ||||
| # Serverless directories | ||||
| .serverless/ | ||||
| 
 | ||||
| # FuseBox cache | ||||
| .fusebox/ | ||||
| 
 | ||||
| # DynamoDB Local files | ||||
| .dynamodb/ | ||||
| 
 | ||||
| # TernJS port file | ||||
| .tern-port | ||||
| 
 | ||||
| # Stores VSCode versions used for testing VSCode extensions | ||||
| .vscode-test | ||||
| 
 | ||||
| # yarn v2 | ||||
| .yarn/cache | ||||
| .yarn/unplugged | ||||
| .yarn/build-state.yml | ||||
| .yarn/install-state.gz | ||||
| .pnp.* | ||||
| 
 | ||||
| /media/ | ||||
| /static/ | ||||
							
								
								
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| { | ||||
|     "python.pythonPath": ".venv/bin/python" | ||||
| } | ||||
							
								
								
									
										0
									
								
								app/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										10
									
								
								app/admin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app/admin.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| from django.contrib import admin | ||||
| from .models import Photo, Album | ||||
| 
 | ||||
| @admin.register(Photo) | ||||
| class PhotoAdmin(admin.ModelAdmin): | ||||
|     list_display = ["title", "user", "created_at", "album"] | ||||
| 
 | ||||
| @admin.register(Album) | ||||
| class AlbumAdmin(admin.ModelAdmin): | ||||
|     list_display = ["title", "user", "created_at"] | ||||
							
								
								
									
										6
									
								
								app/apps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/apps.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| from django.apps import AppConfig | ||||
| 
 | ||||
| 
 | ||||
| class AppConfig(AppConfig): | ||||
|     name = "app" | ||||
|     verbose_name = "Galeria" | ||||
							
								
								
									
										17
									
								
								app/forms.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/forms.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| from django import forms | ||||
| from .models import Photo, Album | ||||
| 
 | ||||
| class PhotoForm(forms.ModelForm): | ||||
|     class Meta: | ||||
|         model = Photo | ||||
|         fields = ['title', 'photo', 'description', 'taken_on'] | ||||
| 
 | ||||
| class PhotoEditForm(forms.ModelForm): | ||||
|     class Meta: | ||||
|         model = Photo | ||||
|         fields = ['title', 'description', 'taken_on'] | ||||
| 
 | ||||
| class AlbumForm(forms.ModelForm): | ||||
|     class Meta: | ||||
|         model = Album | ||||
|         fields = ['title', 'description'] | ||||
							
								
								
									
										29
									
								
								app/migrations/0001_initial.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/migrations/0001_initial.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| # Generated by Django 3.0.7 on 2020-06-03 20:42 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     initial = True | ||||
| 
 | ||||
|     dependencies = [ | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.CreateModel( | ||||
|             name='Photo', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('created_at', models.DateTimeField(auto_now_add=True)), | ||||
|                 ('updated_at', models.DateTimeField(auto_now=True)), | ||||
|                 ('photo', models.ImageField(upload_to='gallery')), | ||||
|                 ('title', models.CharField(max_length=255)), | ||||
|                 ('description', models.TextField(null=True)), | ||||
|                 ('taken_on', models.DateField(null=True)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'abstract': False, | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
							
								
								
									
										46
									
								
								app/migrations/0002_auto_20200603_2116.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								app/migrations/0002_auto_20200603_2116.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| # Generated by Django 3.0.7 on 2020-06-03 21:16 | ||||
| 
 | ||||
| import app.models | ||||
| 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), | ||||
|         ('app', '0001_initial'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AlterModelOptions( | ||||
|             name='photo', | ||||
|             options={'verbose_name': 'photo', 'verbose_name_plural': 'photos'}, | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name='photo', | ||||
|             name='user', | ||||
|             field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='photo', | ||||
|             name='description', | ||||
|             field=models.TextField(blank=True, null=True, verbose_name='Description'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='photo', | ||||
|             name='photo', | ||||
|             field=models.ImageField(upload_to=app.models.user_directory_path, verbose_name='Photo'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='photo', | ||||
|             name='taken_on', | ||||
|             field=models.DateField(blank=True, null=True, verbose_name='Taken on'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='photo', | ||||
|             name='title', | ||||
|             field=models.CharField(max_length=255, verbose_name='Title'), | ||||
|         ), | ||||
|     ] | ||||
							
								
								
									
										49
									
								
								app/migrations/0003_auto_20200603_2131.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/migrations/0003_auto_20200603_2131.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| # Generated by Django 3.0.7 on 2020-06-03 21:31 | ||||
| 
 | ||||
| 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), | ||||
|         ('app', '0002_auto_20200603_2116'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.CreateModel( | ||||
|             name='Comment', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('created_at', models.DateTimeField(auto_now_add=True)), | ||||
|                 ('updated_at', models.DateTimeField(auto_now=True)), | ||||
|                 ('content', models.TextField(verbose_name='Content')), | ||||
|                 ('photo', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='app.Photo')), | ||||
|                 ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'abstract': False, | ||||
|             }, | ||||
|         ), | ||||
|         migrations.CreateModel( | ||||
|             name='Album', | ||||
|             fields=[ | ||||
|                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||
|                 ('created_at', models.DateTimeField(auto_now_add=True)), | ||||
|                 ('updated_at', models.DateTimeField(auto_now=True)), | ||||
|                 ('title', models.TextField(max_length=255, verbose_name='Title')), | ||||
|                 ('description', models.TextField(blank=True, null=True, verbose_name='Description')), | ||||
|                 ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), | ||||
|             ], | ||||
|             options={ | ||||
|                 'abstract': False, | ||||
|             }, | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name='photo', | ||||
|             name='album', | ||||
|             field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='app.Album'), | ||||
|         ), | ||||
|     ] | ||||
							
								
								
									
										0
									
								
								app/migrations/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/migrations/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										57
									
								
								app/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								app/models.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| from django.db import models | ||||
| 
 | ||||
| from imagekit.models import ImageSpecField | ||||
| from imagekit.processors import ResizeToFill | ||||
| from django.utils.translation import ugettext_lazy as _ | ||||
| from django.contrib.auth import get_user_model | ||||
| 
 | ||||
| def user_directory_path(instance, filename): | ||||
|     # file will be uploaded to MEDIA_ROOT/photos/<login>/<filename> | ||||
|     return 'photos/{0}/{1}'.format(instance.user.username, filename) | ||||
| 
 | ||||
| class TimestampMixin(models.Model): | ||||
|     created_at = models.DateTimeField(_("Created at"), auto_now_add=True) | ||||
|     updated_at = models.DateTimeField(_("Updated at"), auto_now=True) | ||||
| 
 | ||||
|     class Meta: | ||||
|         abstract = True | ||||
| 
 | ||||
| class UserMixin(models.Model): | ||||
|     user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, null=True, verbose_name=_("User")) | ||||
| 
 | ||||
|     def is_owned_by(self, user): | ||||
|         return self.user is not None and user is not None and self.user.id == user.id | ||||
| 
 | ||||
|     class Meta: | ||||
|         abstract = True | ||||
| 
 | ||||
| class Album(TimestampMixin, UserMixin): | ||||
|     title = models.CharField(_("Title"), max_length=255) | ||||
|     description = models.TextField(_("Description"), null=True, blank=True) | ||||
|      | ||||
|     def __str__(self): | ||||
|         return self.title | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _('album') | ||||
|         verbose_name_plural = _('albums') | ||||
| 
 | ||||
| class Photo(TimestampMixin, UserMixin): | ||||
|     photo = models.ImageField(_("Photo"), upload_to=user_directory_path) | ||||
|     thumbnail = ImageSpecField( | ||||
|         source='photo',  | ||||
|         format='JPEG',  | ||||
|         options={'quality': 80},  | ||||
|         processors=[ResizeToFill(300, 200, upscale=False)]) | ||||
| 
 | ||||
|     title = models.CharField(_("Title"), max_length=255) | ||||
|      | ||||
|     # some optional data | ||||
|     description = models.TextField(_("Description"), null=True, blank=True) | ||||
|     taken_on = models.DateField(_("Taken on"), null=True, blank=True) | ||||
| 
 | ||||
|     album = models.ForeignKey(Album, on_delete=models.CASCADE, null=True) | ||||
|      | ||||
|     class Meta: | ||||
|         verbose_name = _('photo') | ||||
|         verbose_name_plural = _('photos') | ||||
							
								
								
									
										18
									
								
								app/templates/album/add.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								app/templates/album/add.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| {% extends '../base.html' %} | ||||
| 
 | ||||
| {% load bootstrap4 %} | ||||
| 
 | ||||
| {% block breadcrumbs %} | ||||
|     <li class="breadcrumb-item"><a href="{% url 'index' %}">Galeria Zdjęć</a></li> | ||||
|     <li class="breadcrumb-item">Dodaj album</li> | ||||
| {% endblock breadcrumbs %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     <form method="post" action="{% url 'add_album' %}" enctype="multipart/form-data"> | ||||
|         {% csrf_token %} | ||||
|         {% bootstrap_form form %} | ||||
| 
 | ||||
|         <input type="submit" value="dodaj"> | ||||
|         <input type="hidden" name="next" value="{{ next }}"> | ||||
|     </form> | ||||
| {% endblock content %} | ||||
							
								
								
									
										19
									
								
								app/templates/album/add_photo.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app/templates/album/add_photo.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| {% extends '../base.html' %} | ||||
| 
 | ||||
| {% load bootstrap4 %} | ||||
| 
 | ||||
| {% block breadcrumbs %} | ||||
|     <li class="breadcrumb-item"><a href="{% url 'index' %}">Galeria Zdjęć</a></li> | ||||
|     <li class="breadcrumb-item"><a href="{% url 'album' album.id %}">Album: {{ album.title }}</a></li> | ||||
|     <li class="breadcrumb-item">Dodaj zdjęcie</li> | ||||
| {% endblock breadcrumbs %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     <form method="post" action="{% url 'add_photo' album.id %}" enctype="multipart/form-data"> | ||||
|         {% csrf_token %} | ||||
|         {% bootstrap_form form %} | ||||
| 
 | ||||
|         <input type="submit" value="dodaj"> | ||||
|         <input type="hidden" name="next" value="{{ next }}"> | ||||
|     </form> | ||||
| {% endblock content %} | ||||
							
								
								
									
										19
									
								
								app/templates/album/edit.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app/templates/album/edit.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| {% extends '../base.html' %} | ||||
| 
 | ||||
| {% load bootstrap4 %} | ||||
| 
 | ||||
| {% block breadcrumbs %} | ||||
|     <li class="breadcrumb-item"><a href="{% url 'index' %}">Galeria Zdjęć</a></li> | ||||
|     <li class="breadcrumb-item"><a href="{% url 'album' album.id %}">Album: {{ album.title }}</a></li> | ||||
|     <li class="breadcrumb-item">Zaktualizuj</li> | ||||
| {% endblock breadcrumbs %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     <form method="post" action="{% url 'edit_album' %}" enctype="multipart/form-data"> | ||||
|         {% csrf_token %} | ||||
|         {% bootstrap_form form %} | ||||
| 
 | ||||
|         <input type="submit" value="zaktualizuj"> | ||||
|         <input type="hidden" name="next" value="{{ next }}"> | ||||
|     </form> | ||||
| {% endblock content %} | ||||
							
								
								
									
										20
									
								
								app/templates/album/edit_photo.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/templates/album/edit_photo.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| {% extends '../base.html' %} | ||||
| 
 | ||||
| {% load bootstrap4 %} | ||||
| 
 | ||||
| {% block breadcrumbs %} | ||||
|     <li class="breadcrumb-item"><a href="{% url 'index' %}">Galeria Zdjęć</a></li> | ||||
|     <li class="breadcrumb-item"><a href="{% url 'album' photo.album.id %}">Album: {{ album.title }}</a></li> | ||||
|     <li class="breadcrumb-item"><a href="{% url 'photo' photo.album.id photo.id %}">Zdjęcie: {{ photo.title }}</a></li> | ||||
|     <li class="breadcrumb-item">Zaktualizuj</li> | ||||
| {% endblock breadcrumbs %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     <form method="post" action="{% url 'edit_photo' photo.album.id photo.id %}" enctype="multipart/form-data"> | ||||
|         {% csrf_token %} | ||||
|         {% bootstrap_form form %} | ||||
| 
 | ||||
|         <input type="submit" value="zaktualizuj"> | ||||
|         <input type="hidden" name="next" value="{{ next }}"> | ||||
|     </form> | ||||
| {% endblock content %} | ||||
							
								
								
									
										21
									
								
								app/templates/album/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/templates/album/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| {% extends 'base.html' %} | ||||
| 
 | ||||
| {% block breadcrumbs %} | ||||
|     <li class="breadcrumb-item">Galeria Zdjęć</li> | ||||
| {% endblock breadcrumbs %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     <ul class="gallery"> | ||||
|         {% for album in albums %} | ||||
|             <li class="gallery__entry album"> | ||||
|                 <img src="{{ album.photo_set.first.thumbnail.url }}" class="album__thumbnail" /> | ||||
|                 <div class="album__header"> | ||||
|                     <a class="album__title" href="{% url 'album' album.id %}">{{ album.title }}</a> | ||||
|                 </div> | ||||
|             </li> | ||||
|         {% endfor %} | ||||
|         <li class="gallery__entry gallery__entry--action"> | ||||
|             <a href="{% url 'add_album' %}" class="stretched-link">dodaj +</a> | ||||
|         </li> | ||||
|     </ul> | ||||
| {% endblock content %} | ||||
							
								
								
									
										35
									
								
								app/templates/album/photo.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/templates/album/photo.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| {% extends '../base.html' %} | ||||
| 
 | ||||
| {% block breadcrumbs %} | ||||
|     <li class="breadcrumb-item"><a href="{% url 'index' %}">Galeria Zdjęć</a></li> | ||||
|     <li class="breadcrumb-item"><a href="{% url 'album' photo.album.id %}">Album: {{ photo.album.title }}</a></li> | ||||
|     <li class="breadcrumb-item">Zdjęcie: {{ photo.title }}</li> | ||||
| {% endblock breadcrumbs %} | ||||
| 
 | ||||
| {% block subtitle %}<h2>{{ photo.album.title }}</h2>{% endblock %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     <div class="photo"> | ||||
|         <div class="photo__title h1">{{ photo.title }}</div> | ||||
|         <ul class="actions my-2"> | ||||
|             <li class="actions__action"> | ||||
|                 <a href="{% url 'edit_photo' photo.album.id photo.id %}" class="btn btn-sm btn-warning">Aktualizuj</a> | ||||
|             </li> | ||||
|             <li class="actions__action"> | ||||
|                 <form action="{% url 'delete_photo' photo.album.id photo.id %}" method="post"> | ||||
|                     {% csrf_token %} | ||||
|                     <button class="btn btn-sm btn-outline-danger">Usuń</button> | ||||
|                 </form> | ||||
|             </li> | ||||
|         </ul> | ||||
|         <img class="photo__photo" src="{{ photo.photo.url }}" /> | ||||
|         <aside class="photo__meta"> | ||||
|             <p class="photo__description my-2">{{ photo.description }}</p> | ||||
|             <div class="photo__author small"> | ||||
|                 autor: {{ photo.user.username }}{% if photo.taken_on %} | ||||
|                 , {{ photo.taken_on }} | ||||
|                 {% endif %} | ||||
|             </div> | ||||
|         </aside> | ||||
|     </div> | ||||
| {% endblock content %} | ||||
							
								
								
									
										38
									
								
								app/templates/album/photos.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/templates/album/photos.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| {% extends '../base.html' %} | ||||
| 
 | ||||
| {% block breadcrumbs %} | ||||
|     <li class="breadcrumb-item"><a href="{% url 'index' %}">Galeria Zdjęć</a></li> | ||||
|     <li class="breadcrumb-item">Album: {{ album.title }}</li> | ||||
| {% endblock breadcrumbs %} | ||||
| 
 | ||||
| {% block subtitle %}<h2>{{ album.title }}</h2>{% endblock %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     {% if is_my %} | ||||
|         <ul class="actions my-2"> | ||||
|             <li class="actions__action"> | ||||
|                 <a href="{% url 'edit_album' album.id %}" class="btn btn-sm btn-warning">Aktualizuj</a> | ||||
|             </li> | ||||
|             <li class="actions__action"> | ||||
|                 <form action="{% url 'delete_album' album.id %}" method="post"> | ||||
|                     {% csrf_token %} | ||||
|                     <button class="btn btn-sm btn-outline-danger">Usuń</button> | ||||
|                 </form> | ||||
|             </li> | ||||
|         </ul> | ||||
|     {% endif %} | ||||
|     <ul class="gallery"> | ||||
|         {% for photo in photos %} | ||||
|             <li class="gallery__entry photo"> | ||||
|                 <a href="{% url 'photo' album.id photo.id %}"> | ||||
|                     <img src="{{ photo.thumbnail.url }}" class="photo__thumbnail" /> | ||||
|                 </a> | ||||
|             </li> | ||||
|         {% endfor %} | ||||
|         {% if is_my %} | ||||
|             <li class="gallery__entry gallery__entry--action"> | ||||
|                 <a href="{% url 'add_photo' album.id %}" class="stretched-link">dodaj + </a> | ||||
|             </li> | ||||
|         {% endif %} | ||||
|     </ul> | ||||
| {% endblock content %} | ||||
							
								
								
									
										38
									
								
								app/templates/base.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/templates/base.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| <!doctype html> | ||||
| <html lang="pl"> | ||||
|     {% load static bootstrap4 %} | ||||
|     <head> | ||||
|         <!-- Required meta tags --> | ||||
|         <meta charset="utf-8"> | ||||
|         <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||||
| 
 | ||||
|         <!-- Bootstrap CSS --> | ||||
|         <title>Galeria Zdjęć</title> | ||||
|         <script src="{% static 'dist/bundle.js' %}"></script> | ||||
|     </head> | ||||
| 
 | ||||
|     <body> | ||||
|         <header class="container d-flex align-items-center justify-content-end py-2"> | ||||
|             {% if user.is_authenticated %} | ||||
|                 <span>Zalogowany jako: <span>{{ user.username }}</span></span> <a href="{% url 'logout' %}" class="btn btn-link">Wyloguj się</a> | ||||
|             {% else %} | ||||
|                 <a href="{% url 'login' %}" class="btn btn-link">Zaloguj się</a> lub <a href="{% url 'register' %}" class="btn btn-link">zarejestruj</a> | ||||
|             {% endif %} | ||||
|         </header> | ||||
|         <main class="app container"> | ||||
|             <header class="app__header">  | ||||
|                 <h1>Galeria Zdjęć</h1> | ||||
|                 {% block subtitle %}{% endblock %} | ||||
|             </header> | ||||
| 
 | ||||
|             <nav aria-label="Okruszki"> | ||||
|                 <ol class="breadcrumb"> | ||||
|                     {% block breadcrumbs %}{% endblock breadcrumbs %} | ||||
|                 </ol> | ||||
|             </nav> | ||||
|              | ||||
|             {% block content %} | ||||
|             {% endblock content %} | ||||
|         </main> | ||||
|     </body> | ||||
| </html> | ||||
							
								
								
									
										17
									
								
								app/templates/registration/login.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/templates/registration/login.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| {% extends "base.html" %} | ||||
| {% load bootstrap4 %} | ||||
| 
 | ||||
| {% block breadcrumbs %} | ||||
|     <li class="breadcrumb-item"><a href="{% url 'index' %}">Galeria Zdjęć</a></li> | ||||
|     <li class="breadcrumb-item">Zaloguj się</li> | ||||
| {% endblock breadcrumbs %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     <form method="post" action="{% url 'login' %}"> | ||||
|         {% csrf_token %} | ||||
|         {% bootstrap_form form %} | ||||
| 
 | ||||
|         <input type="submit" value="zaloguj"> | ||||
|         <input type="hidden" name="next" value="{{ next }}"> | ||||
|     </form> | ||||
| {% endblock %} | ||||
							
								
								
									
										17
									
								
								app/templates/registration/register.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/templates/registration/register.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| {% extends "base.html" %} | ||||
| {% load bootstrap4 %} | ||||
| 
 | ||||
| {% block breadcrumbs %} | ||||
|     <li class="breadcrumb-item"><a href="{% url 'index' %}">Galeria Zdjęć</a></li> | ||||
|     <li class="breadcrumb-item">Zarejestruj się</li> | ||||
| {% endblock breadcrumbs %} | ||||
| 
 | ||||
| {% block content %} | ||||
|     <form method="post" action="{% url 'login' %}"> | ||||
|         {% csrf_token %} | ||||
|         {% bootstrap_form form %} | ||||
| 
 | ||||
|         <input type="submit" value="zarejestruj się"> | ||||
|         <input type="hidden" name="next" value="{{ next }}"> | ||||
|     </form> | ||||
| {% endblock %} | ||||
							
								
								
									
										3
									
								
								app/tests.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/tests.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| from django.test import TestCase | ||||
| 
 | ||||
| # Create your tests here. | ||||
							
								
								
									
										16
									
								
								app/urls.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/urls.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| from django.urls import path | ||||
| 
 | ||||
| from . import views | ||||
| 
 | ||||
| urlpatterns = [ | ||||
|     path('', views.albums, name='index'), | ||||
|     path('register', views.register, name='register'), | ||||
|     path('add', views.add_album, name='add_album'), | ||||
|     path('album/<int:album_id>', views.photos, name='album'), | ||||
|     path('album/<int:album_id>/edit', views.edit_album, name='edit_album'), | ||||
|     path('album/<int:album_id>/delete', views.delete_album, name='delete_album'), | ||||
|     path('album/<int:album_id>/photo/<int:photo_id>', views.photo, name='photo'), | ||||
|     path('album/<int:album_id>/photo/<int:photo_id>/edit', views.edit_photo, name='edit_photo'), | ||||
|     path('album/<int:album_id>/photo/<int:photo_id>/delete', views.delete_photo, name='delete_photo'), | ||||
|     path('album/<int:album_id>/add', views.add_photo, name='add_photo'), | ||||
| ] | ||||
							
								
								
									
										121
									
								
								app/views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								app/views.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | ||||
| from django.shortcuts import render, get_object_or_404, redirect, reverse | ||||
| from .models import Album, Photo | ||||
| from .forms import PhotoForm, AlbumForm | ||||
| from django.contrib.auth.forms import UserCreationForm as RegisterForm | ||||
| from django.core.exceptions import PermissionDenied | ||||
| from django.views.decorators.http import require_http_methods | ||||
| from django.views.decorators.csrf import csrf_exempt | ||||
| from app.forms import PhotoEditForm | ||||
| 
 | ||||
| def register(request): | ||||
|     if request.method == "POST": | ||||
|         form = RegisterForm(request.POST) | ||||
|         if form.is_valid(): | ||||
|             form.save() | ||||
| 
 | ||||
|         return redirect("/") | ||||
|     else: | ||||
|         form = RegisterForm() | ||||
| 
 | ||||
|     return render(request, "registration/register.html", {"form":form}) | ||||
| 
 | ||||
| # Create your views here. | ||||
| def albums(request): | ||||
|     albums = Album.objects.order_by('created_at').prefetch_related('photo_set') | ||||
| 
 | ||||
|     return render(request, "album/index.html", locals()) | ||||
| 
 | ||||
| def photos(request, album_id): | ||||
|     album = get_object_or_404(Album, pk=album_id) | ||||
|     photos = album.photo_set.all() | ||||
|     is_my = album.is_owned_by(request.user) | ||||
| 
 | ||||
|     return render(request, "album/photos.html", locals()) | ||||
| 
 | ||||
| def photo(request, photo_id, album_id): | ||||
|     photo = get_object_or_404(Photo, pk=photo_id) | ||||
|     is_my = photo.is_owned_by(request.user) | ||||
| 
 | ||||
|     return render(request, "album/photo.html", locals()) | ||||
| 
 | ||||
| def add_album(request): | ||||
|     if request.method == 'POST': | ||||
|         form = AlbumForm(request.POST, request.FILES) | ||||
| 
 | ||||
|         if form.is_valid(): | ||||
|             form.instance.user = request.user | ||||
|             form.save() | ||||
|             return redirect(reverse('album', args=[form.instance.id])) | ||||
|     else: | ||||
|         form = AlbumForm() | ||||
| 
 | ||||
| 
 | ||||
|     return render(request, "album/add.html", locals()) | ||||
| 
 | ||||
| def add_photo(request, album_id): | ||||
|     album = get_object_or_404(Album, pk=album_id) | ||||
| 
 | ||||
|     if request.method == 'POST': | ||||
|         form = PhotoForm(request.POST, request.FILES) | ||||
| 
 | ||||
|         photo = form.instance | ||||
|         photo.album = album | ||||
|         photo.user = request.user | ||||
| 
 | ||||
|         if form.is_valid(): | ||||
|             form.save() | ||||
|             return redirect(reverse('album', args=[album.id])) | ||||
|     else: | ||||
|         form = PhotoForm() | ||||
| 
 | ||||
|     return render(request, "album/add_photo.html", locals()) | ||||
| 
 | ||||
| def edit_album(request, album_id): | ||||
|     album = get_object_or_404(Album, pk=album_id) | ||||
| 
 | ||||
|     if not album.is_owned_by(request.user): | ||||
|         raise PermissionDenied() | ||||
| 
 | ||||
|     form = AlbumForm(request.POST or None, instance=album) | ||||
| 
 | ||||
|     if request.method == 'POST' and form.is_valid(): | ||||
|         form.save() | ||||
|         return redirect(reverse('album', args=[album.id])) | ||||
| 
 | ||||
|     return render(request, "album/edit_album.html", locals()) | ||||
| 
 | ||||
| @require_http_methods(["POST"]) | ||||
| def delete_album(request, album_id): | ||||
|     album = get_object_or_404(Album, pk=album_id) | ||||
| 
 | ||||
|     if not album.is_owned_by(request.user): | ||||
|         raise PermissionDenied() | ||||
| 
 | ||||
|     album.delete() | ||||
| 
 | ||||
|     return redirect(reverse('index')) | ||||
| 
 | ||||
| def edit_photo(request, album_id, photo_id): | ||||
|     photo = get_object_or_404(Photo, pk=photo_id) | ||||
| 
 | ||||
|     if not photo.is_owned_by(request.user): | ||||
|         raise PermissionDenied() | ||||
| 
 | ||||
|     form = PhotoEditForm(request.POST or None, request.FILES or None, instance=photo) | ||||
|      | ||||
|     if request.method == 'POST' and form.is_valid(): | ||||
|         form.save() | ||||
|         return redirect(reverse('photo', args=[photo.album.id, photo.id])) | ||||
| 
 | ||||
|     return render(request, "album/edit_photo.html", locals()) | ||||
| 
 | ||||
| @require_http_methods(["POST"]) | ||||
| def delete_photo(request, album_id, photo_id): | ||||
|     photo = get_object_or_404(Photo, pk=photo_id) | ||||
| 
 | ||||
|     if not photo.is_owned_by(request.user): | ||||
|         raise PermissionDenied() | ||||
| 
 | ||||
|     photo.delete() | ||||
| 
 | ||||
|     return redirect(reverse('album', args=[album_id])) | ||||
							
								
								
									
										1
									
								
								assets/app.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/app.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| import './style.scss' | ||||
							
								
								
									
										129
									
								
								assets/style.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								assets/style.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,129 @@ | ||||
| @import "../node_modules/bootstrap/scss/bootstrap.scss"; | ||||
| 
 | ||||
| body { | ||||
|     margin: 0; | ||||
|     font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", | ||||
|         "Droid Sans", "Helvetica Neue", sans-serif; | ||||
|     -webkit-font-smoothing: antialiased; | ||||
|     -moz-osx-font-smoothing: grayscale; | ||||
| } | ||||
| 
 | ||||
| code { | ||||
|     font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; | ||||
| } | ||||
| 
 | ||||
| a { | ||||
|     color: black; | ||||
| } | ||||
| 
 | ||||
| %link-extended { | ||||
|     &::after { | ||||
|         position: absolute; | ||||
|         top: 0; | ||||
|         bottom: 0; | ||||
|         right: 0; | ||||
|         left: 0; | ||||
|         content: ""; | ||||
| 
 | ||||
|         z-index: 10; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| .app { | ||||
|     margin: 100px auto; | ||||
| } | ||||
| 
 | ||||
| .app__header { | ||||
|     margin-bottom: 5rem; | ||||
|     text-align: center; | ||||
| } | ||||
| 
 | ||||
| .gallery { | ||||
|     list-style: none; | ||||
|     padding: 0; | ||||
|     margin: 0 auto; | ||||
|     display: flex; | ||||
|     margin-left: -1rem; | ||||
|     flex-wrap: wrap; | ||||
| } | ||||
| 
 | ||||
| .gallery__entry { | ||||
|     &::after { | ||||
|         padding-bottom: 56.25%; | ||||
|         content: ""; | ||||
|     } | ||||
| 
 | ||||
|     width: calc(33.33% - 1rem); | ||||
|     margin-left: 1rem; | ||||
|     margin-bottom: 1rem; | ||||
|     position: relative; | ||||
| 
 | ||||
|     transform: scale(1) rotate(0); | ||||
|     transition: 150ms ease-in-out transform; | ||||
| 
 | ||||
|     &:hover { | ||||
|         transform: scale(1.02) rotate(0.3deg); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| .gallery__entry--action { | ||||
|     background-color: #ddd; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     font-weight: bold; | ||||
| } | ||||
| 
 | ||||
| .album { | ||||
|     position: relative; | ||||
|     display: flex; | ||||
|     flex-direction: column-reverse; | ||||
| } | ||||
| 
 | ||||
| .album__thumbnail, .photo__thumbnail { | ||||
|     position: absolute; | ||||
|     z-index: -1; | ||||
|     width: 100%; | ||||
|     background-color: #ddd; | ||||
| } | ||||
| 
 | ||||
| .album__header { | ||||
|     bottom: 0; | ||||
|     background-color: rgba(black, 0.5); | ||||
|     padding: 1rem; | ||||
|     text-align: center; | ||||
|     z-index: 1; | ||||
| } | ||||
| 
 | ||||
| .album__title { | ||||
|     font-weight: bold; | ||||
|     color: white; | ||||
|     text-shadow: 0 0 2px rgba(black, 0.5); | ||||
| 
 | ||||
|     @extend %link-extended; | ||||
| 
 | ||||
|     &:hover { | ||||
|         color: white; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| .photo__photo { | ||||
|     max-width: 100%; | ||||
| } | ||||
| 
 | ||||
| .actions { | ||||
|     list-style: none; | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
| } | ||||
| 
 | ||||
| .actions__action { | ||||
|     margin-right: .5rem; | ||||
|     display: inline-block; | ||||
| } | ||||
| 
 | ||||
| @include media-breakpoint-down(sm) { | ||||
|     .gallery__entry { | ||||
|         width: 100% | ||||
|     } | ||||
| } | ||||
							
								
								
									
										0
									
								
								gallery/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								gallery/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										16
									
								
								gallery/asgi.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								gallery/asgi.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| """ | ||||
| ASGI config for gallery project. | ||||
| 
 | ||||
| It exposes the ASGI callable as a module-level variable named ``application``. | ||||
| 
 | ||||
| For more information on this file, see | ||||
| https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ | ||||
| """ | ||||
| 
 | ||||
| import os | ||||
| 
 | ||||
| from django.core.asgi import get_asgi_application | ||||
| 
 | ||||
| os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gallery.settings') | ||||
| 
 | ||||
| application = get_asgi_application() | ||||
							
								
								
									
										153
									
								
								gallery/settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								gallery/settings.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,153 @@ | ||||
| """ | ||||
| Django settings for gallery project. | ||||
| 
 | ||||
| Generated by 'django-admin startproject' using Django 3.0.6. | ||||
| 
 | ||||
| For more information on this file, see | ||||
| https://docs.djangoproject.com/en/3.0/topics/settings/ | ||||
| 
 | ||||
| For the full list of settings and their values, see | ||||
| https://docs.djangoproject.com/en/3.0/ref/settings/ | ||||
| """ | ||||
| 
 | ||||
| import os | ||||
| 
 | ||||
| # Build paths inside the project like this: os.path.join(BASE_DIR, ...) | ||||
| BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||||
| 
 | ||||
| 
 | ||||
| # Quick-start development settings - unsuitable for production | ||||
| # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ | ||||
| 
 | ||||
| # SECURITY WARNING: keep the secret key used in production secret! | ||||
| SECRET_KEY = '$t2(9!*g*ncmt@o7l3cxqtfm=a348(q7$ax1hp2z!fddrxjqh-' | ||||
| 
 | ||||
| # SECURITY WARNING: don't run with debug turned on in production! | ||||
| DEBUG = True | ||||
| 
 | ||||
| ALLOWED_HOSTS = ['gallery.localhost', 'gallery.kadet.net'] | ||||
| 
 | ||||
| 
 | ||||
| # Application definition | ||||
| 
 | ||||
| INSTALLED_APPS = [ | ||||
|     'django.contrib.admin', | ||||
|     'django.contrib.auth', | ||||
|     'django.contrib.contenttypes', | ||||
|     'django.contrib.sessions', | ||||
|     'django.contrib.messages', | ||||
|     'django.contrib.staticfiles', | ||||
|     'app.apps.AppConfig', | ||||
|     'bootstrap4' | ||||
| ] | ||||
| 
 | ||||
| MIDDLEWARE = [ | ||||
|     'django.middleware.security.SecurityMiddleware', | ||||
|     'django.contrib.sessions.middleware.SessionMiddleware', | ||||
|     'django.middleware.common.CommonMiddleware', | ||||
|     'django.middleware.csrf.CsrfViewMiddleware', | ||||
|     'django.contrib.auth.middleware.AuthenticationMiddleware', | ||||
|     'django.contrib.messages.middleware.MessageMiddleware', | ||||
|     'django.middleware.clickjacking.XFrameOptionsMiddleware', | ||||
| ] | ||||
| 
 | ||||
| ROOT_URLCONF = 'gallery.urls' | ||||
| 
 | ||||
| TEMPLATES = [ | ||||
|     { | ||||
|         'BACKEND': 'django.template.backends.django.DjangoTemplates', | ||||
|         'DIRS': [], | ||||
|         'APP_DIRS': True, | ||||
|         'OPTIONS': { | ||||
|             'context_processors': [ | ||||
|                 'django.template.context_processors.debug', | ||||
|                 'django.template.context_processors.request', | ||||
|                 'django.contrib.auth.context_processors.auth', | ||||
|                 'django.contrib.messages.context_processors.messages', | ||||
|             ], | ||||
|         }, | ||||
|     }, | ||||
| ] | ||||
| 
 | ||||
| WSGI_APPLICATION = 'gallery.wsgi.application' | ||||
| 
 | ||||
| 
 | ||||
| # Database | ||||
| # https://docs.djangoproject.com/en/3.0/ref/settings/#databases | ||||
| 
 | ||||
| DATABASES = { | ||||
|     'default': { | ||||
|         'ENGINE': 'django.db.backends.sqlite3', | ||||
|         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # Password validation | ||||
| # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators | ||||
| 
 | ||||
| AUTH_PASSWORD_VALIDATORS = [ | ||||
|     { | ||||
|         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', | ||||
|     }, | ||||
|     { | ||||
|         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', | ||||
|     }, | ||||
|     { | ||||
|         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', | ||||
|     }, | ||||
|     { | ||||
|         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', | ||||
|     }, | ||||
| ] | ||||
| 
 | ||||
| 
 | ||||
| # Internationalization | ||||
| # https://docs.djangoproject.com/en/3.0/topics/i18n/ | ||||
| 
 | ||||
| LANGUAGE_CODE = 'pl-pl' | ||||
| TIME_ZONE = 'UTC' | ||||
| USE_I18N = True | ||||
| USE_L10N = True | ||||
| USE_TZ = True | ||||
| 
 | ||||
| LOCALE_PATHS = [ os.path.join('locale/') ]  | ||||
| 
 | ||||
| 
 | ||||
| # Static files (CSS, JavaScript, Images) | ||||
| # https://docs.djangoproject.com/en/3.0/howto/static-files/ | ||||
| 
 | ||||
| STATIC_URL = '/static/' | ||||
| STATIC_ROOT = '' | ||||
| STATICFILES_DIRS = [ os.path.join('static') ] | ||||
| 
 | ||||
| MEDIA_URL = '/media/' | ||||
| MEDIA_ROOT = os.path.join('media/') | ||||
| 
 | ||||
| PHOTOS_URL  = '/photos/' | ||||
| PHOTOS_ROOT = os.path.join('photos/') | ||||
| 
 | ||||
| LOGIN_REDIRECT_URL = "index" | ||||
| LOGOUT_REDIRECT_URL = "index" | ||||
| 
 | ||||
| LOGGING = { | ||||
|     'version': 1, | ||||
|     'filters': { | ||||
|         'require_debug_true': { | ||||
|             '()': 'django.utils.log.RequireDebugTrue', | ||||
|         } | ||||
|     }, | ||||
|     'handlers': { | ||||
|         'console': { | ||||
|             'level': 'DEBUG', | ||||
|             'filters': ['require_debug_true'], | ||||
|             'class': 'logging.StreamHandler', | ||||
|         } | ||||
|     }, | ||||
|     'loggers': { | ||||
|         'django.db.backends': { | ||||
|             'level': 'DEBUG', | ||||
|             'handlers': ['console'], | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								gallery/urls.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								gallery/urls.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| """gallery URL Configuration | ||||
| 
 | ||||
| The `urlpatterns` list routes URLs to views. For more information please see: | ||||
|     https://docs.djangoproject.com/en/3.0/topics/http/urls/ | ||||
| Examples: | ||||
| Function views | ||||
|     1. Add an import:  from my_app import views | ||||
|     2. Add a URL to urlpatterns:  path('', views.home, name='home') | ||||
| Class-based views | ||||
|     1. Add an import:  from other_app.views import Home | ||||
|     2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home') | ||||
| Including another URLconf | ||||
|     1. Import the include() function: from django.urls import include, path | ||||
|     2. Add a URL to urlpatterns:  path('blog/', include('blog.urls')) | ||||
| """ | ||||
| from django.contrib import admin | ||||
| from django.urls import path, include | ||||
| from django.conf.urls.static import static | ||||
| from django.conf import settings | ||||
| 
 | ||||
| urlpatterns = [ | ||||
|     path('accounts/', include('django.contrib.auth.urls')), | ||||
|     path('admin/', admin.site.urls), | ||||
|     path('', include('app.urls')), | ||||
| ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \ | ||||
|   + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)  | ||||
							
								
								
									
										16
									
								
								gallery/wsgi.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								gallery/wsgi.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| """ | ||||
| WSGI config for gallery project. | ||||
| 
 | ||||
| It exposes the WSGI callable as a module-level variable named ``application``. | ||||
| 
 | ||||
| For more information on this file, see | ||||
| https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ | ||||
| """ | ||||
| 
 | ||||
| import os | ||||
| 
 | ||||
| from django.core.wsgi import get_wsgi_application | ||||
| 
 | ||||
| os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gallery.settings') | ||||
| 
 | ||||
| application = get_wsgi_application() | ||||
							
								
								
									
										67
									
								
								locale/pl/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								locale/pl/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| # SOME DESCRIPTIVE TITLE. | ||||
| # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | ||||
| # This file is distributed under the same license as the PACKAGE package. | ||||
| # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | ||||
| # | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2020-06-08 20:39+0000\n" | ||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | ||||
| "Language: \n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" | ||||
| "%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" | ||||
| "%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" | ||||
| 
 | ||||
| #: app/models.py:13 | ||||
| msgid "Created at" | ||||
| msgstr "Data utworzenia" | ||||
| 
 | ||||
| #: app/models.py:14 | ||||
| msgid "Updated at" | ||||
| msgstr "Data aktualizacji" | ||||
| 
 | ||||
| #: app/models.py:20 | ||||
| msgid "User" | ||||
| msgstr "Użytkownik" | ||||
| 
 | ||||
| #: app/models.py:29 app/models.py:44 | ||||
| msgid "Title" | ||||
| msgstr "Tytuł" | ||||
| 
 | ||||
| #: app/models.py:30 app/models.py:47 | ||||
| msgid "Description" | ||||
| msgstr "Opis" | ||||
| 
 | ||||
| #: app/models.py:33 | ||||
| msgid "album" | ||||
| msgstr "album" | ||||
| 
 | ||||
| #: app/models.py:34 | ||||
| msgid "albums" | ||||
| msgstr "albumy" | ||||
| 
 | ||||
| #: app/models.py:37 | ||||
| msgid "Photo" | ||||
| msgstr "Zdjęcie" | ||||
| 
 | ||||
| #: app/models.py:48 | ||||
| msgid "Taken on" | ||||
| msgstr "Data wykonania" | ||||
| 
 | ||||
| #: app/models.py:53 | ||||
| msgid "photo" | ||||
| msgstr "zdjęcie" | ||||
| 
 | ||||
| #: app/models.py:54 | ||||
| msgid "photos" | ||||
| msgstr "zdjęcia" | ||||
| 
 | ||||
| #~ msgid "Content" | ||||
| #~ msgstr "Treść" | ||||
							
								
								
									
										21
									
								
								manage.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										21
									
								
								manage.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,21 @@ | ||||
| #!/usr/bin/env python | ||||
| """Django's command-line utility for administrative tasks.""" | ||||
| import os | ||||
| import sys | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gallery.settings') | ||||
|     try: | ||||
|         from django.core.management import execute_from_command_line | ||||
|     except ImportError as exc: | ||||
|         raise ImportError( | ||||
|             "Couldn't import Django. Are you sure it's installed and " | ||||
|             "available on your PYTHONPATH environment variable? Did you " | ||||
|             "forget to activate a virtual environment?" | ||||
|         ) from exc | ||||
|     execute_from_command_line(sys.argv) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
							
								
								
									
										22
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| { | ||||
|   "name": "P04", | ||||
|   "version": "1.0.0", | ||||
|   "main": "index.js", | ||||
|   "author": "Kacper Donat", | ||||
|   "license": "MIT", | ||||
|   "private": true, | ||||
|   "devDependencies": { | ||||
|     "bootstrap": "^4.5.0", | ||||
|     "copy-webpack-plugin": "^6.0.2", | ||||
|     "css-loader": "^3.5.3", | ||||
|     "file-loader": "^6.0.0", | ||||
|     "imagemin-webpack-plugin": "^2.4.2", | ||||
|     "node-sass": "^4.14.1", | ||||
|     "sass-loader": "^8.0.2", | ||||
|     "style-loader": "^1.2.1", | ||||
|     "ts-loader": "^7.0.5", | ||||
|     "typescript": "^3.9.3", | ||||
|     "webpack": "^4.43.0", | ||||
|     "webpack-cli": "^3.3.11" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										16
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| { | ||||
|     "compilerOptions": { | ||||
|         "module": "commonjs", | ||||
|         "noImplicitAny": true, | ||||
|         "removeComments": true, | ||||
|         "preserveConstEnums": true, | ||||
|         "sourceMap": true | ||||
|     }, | ||||
|     "include": [ | ||||
|         "assets/**/*.ts" | ||||
|     ], | ||||
|     "exclude": [ | ||||
|         "node_modules", | ||||
|         "**/*.spec.ts" | ||||
|     ] | ||||
| } | ||||
							
								
								
									
										49
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| const path = require('path'); | ||||
| const CopyWebpackPlugin = require('copy-webpack-plugin') | ||||
| const ImageminPlugin = require('imagemin-webpack-plugin').default; | ||||
| 
 | ||||
| const config = { | ||||
|     entry: { | ||||
|         main: ['./assets/app.ts'], | ||||
|     }, | ||||
|     output: { | ||||
|         path: path.resolve('./static/dist/'), | ||||
|         publicPath: "/dist/", | ||||
|         filename: "bundle.js", | ||||
|         chunkFilename: 'bundle.[chunkhash:8].js' | ||||
|     }, | ||||
|     resolve: { | ||||
|         extensions: ['.tsx', '.ts', '.js'], | ||||
|     }, | ||||
|     module: { | ||||
|         rules: [{ | ||||
|             test: /\.s[ac]ss$/, | ||||
|             use: ["style-loader", "css-loader?sourceMap", "sass-loader?sourceMap"] | ||||
|         }, { | ||||
|             test: /\.css$/, | ||||
|             use: ["style-loader", "css-loader"] | ||||
|         }, { | ||||
|             test: /\.tsx?$/, | ||||
|             use: 'ts-loader', | ||||
|             exclude: /node_modules/ | ||||
|         }, { | ||||
|             test: /\.(png|svg|jpg|gif)$/, | ||||
|             use: 'file-loader', | ||||
|         }, { | ||||
|             test: /\.(woff|woff2|eot|ttf|otf)$/, | ||||
|             use: 'file-loader' | ||||
|         }] | ||||
|     }, | ||||
|     plugins: [ | ||||
|         new CopyWebpackPlugin({ patterns: [{ from: './assets/images/', to: '../images/' }] }), | ||||
|         new ImageminPlugin({ test: /\.(jpe?g|png|gif|svg)$/i }), | ||||
|     ] | ||||
| }; | ||||
| 
 | ||||
| module.exports = (env, argv) => { | ||||
|     if (argv.mode === 'development') { | ||||
|         config.devtool = 'inline-source-map'; | ||||
|     } | ||||
| 
 | ||||
|     return config; | ||||
| }; | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user