Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
6e6f4ced7b | |||
b806f7f9e3 | |||
98c5ddad65 | |||
654cd87006 | |||
533efb328c | |||
5b1b23d3e6 | |||
bcd003a685 | |||
c4adc3f434 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -94,4 +94,7 @@ env.bak/
|
|||||||
venv.bak/
|
venv.bak/
|
||||||
|
|
||||||
# Editors
|
# Editors
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
# twine / pypi
|
||||||
|
.pypirc
|
@@ -1,5 +1,5 @@
|
|||||||
include LICENSE
|
include LICENSE
|
||||||
include README.rst
|
include Readme.rst
|
||||||
include Pipfile
|
include Pipfile
|
||||||
recursive-include lostplaces_app/static *
|
recursive-include lostplaces_app/static *
|
||||||
recursive-include lostplaces_app/templates *
|
recursive-include lostplaces_app/templates *
|
3
Pipfile
3
Pipfile
@@ -8,6 +8,9 @@ pylint = "*"
|
|||||||
coverage = "*"
|
coverage = "*"
|
||||||
autopep8 = "*"
|
autopep8 = "*"
|
||||||
pipenv = "*"
|
pipenv = "*"
|
||||||
|
wheel = "*"
|
||||||
|
twine = "*"
|
||||||
|
pandoc ="*"
|
||||||
|
|
||||||
[packages]
|
[packages]
|
||||||
django = "*"
|
django = "*"
|
||||||
|
69
Readme.md
69
Readme.md
@@ -4,18 +4,21 @@ lostplaces-backend is a django (3.x) based webproject. It once wants to become a
|
|||||||
|
|
||||||
The software is currently in early development status, neither scope, datalmodel(s) nor features are finalized yet. Therefore we would not recommend to download or install this piece of software anywhere - except your local django dev server.
|
The software is currently in early development status, neither scope, datalmodel(s) nor features are finalized yet. Therefore we would not recommend to download or install this piece of software anywhere - except your local django dev server.
|
||||||
|
|
||||||
|
We value privacy as a whole, all ressources the frontend requires will be shipped with lostplace's distribution. We also try to minimze the use of JavaScript as far as we can and try to offer JS-less alternatives where we can.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- manage lost places with lots of usefull information
|
- Manage lost places with lots of usefull information.
|
||||||
- sensitive information is not accesiable for anonymous (not logged in) users
|
- OSM-Maps
|
||||||
- user self registration using a voucher system, only people you invite can join your instance
|
- Sensitive information is not accesiable for anonymous (not logged in) users.
|
||||||
- collaboration, every user can add informations like tags, photos and external links to your place
|
- User self registration using a voucher system, only people you invite can join your instance.
|
||||||
|
- Collaboration, every user can add informations like tags, photos and external links to your place.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
Right now it depends on the following non-core Python 3 libraries. These can be installed using the package manager of your distribution or into the venv locally.
|
Right now it depends on the following non-core Python 3 libraries. These can be installed using the package manager of your distribution or into the venv locally.
|
||||||
|
|
||||||
* [django](https://www.djangoproject.com/) django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.
|
* [django](https://www.djangoproject.com/) is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.
|
||||||
* [easy-thumbnails](https://github.com/SmileyChris/easy-thumbnails) A powerful, yet easy to implement thumbnailing application for Django 1.11+
|
* [easy-thumbnails](https://github.com/SmileyChris/easy-thumbnails) A powerful, yet easy to implement thumbnailing application for Django 1.11+.
|
||||||
* [image](https://github.com/francescortiz/image) Image cropping for django
|
* [image](https://github.com/francescortiz/image) Image cropping for django.
|
||||||
* [django-widget-tweaks](https://github.com/jazzband/django-widget-tweaks) Tweak the form field rendering in templates, not in python-level form definitions.
|
* [django-widget-tweaks](https://github.com/jazzband/django-widget-tweaks) Tweak the form field rendering in templates, not in python-level form definitions.
|
||||||
* [django-taggit](https://github.com/jazzband/django-taggit) A simpler approach to tagging with Django.
|
* [django-taggit](https://github.com/jazzband/django-taggit) A simpler approach to tagging with Django.
|
||||||
|
|
||||||
@@ -48,42 +51,44 @@ $ pipenv shell
|
|||||||
```
|
```
|
||||||
|
|
||||||
Visit: [admin](http://localhost:8000/admin) for administrative backend or
|
Visit: [admin](http://localhost:8000/admin) for administrative backend or
|
||||||
[frontend](http://localhost:8000/)
|
[frontend](http://localhost:8000/).
|
||||||
|
|
||||||
|
Happy developing ;-)
|
||||||
|
|
||||||
# Installing a productive instance
|
# Installing a productive instance
|
||||||
|
|
||||||
Currently there are two ways to deploy the lostplaces project:
|
Currently there are two ways to deploy the lostplaces project:
|
||||||
1. Cloning this repository, including the configured django instance
|
1. Cloning this repository, including the configured django instance.
|
||||||
2. Install the package and setup the django instance your self
|
2. Install the package and setup the django instance yourself.
|
||||||
|
|
||||||
## Cloning the repository
|
## Cloning the repository
|
||||||
|
|
||||||
Essently, this is the same as installing an development instance, but without the development server (manage.py runserver) and something powerfull (Apache, NGINX) instead. You have to configure the webserve to work with the *SGI Api respectivly, reference [django's guide for deployment](https://docs.djangoproject.com/en/3.1/howto/deployment/) for further information.
|
Essentially, this is the same as installing a development instance, but without the development server (manage.py runserver) and something powerfull (Apache, NGINX) instead. You have to configure the webserve to work with the *SGI Api respectivly, reference [django's guide for deployment](https://docs.djangoproject.com/en/3.1/howto/deployment/) for further information.
|
||||||
|
|
||||||
You also should setup an dedicated database server, the build in SQLite file is not recommened for production use. Reference [django's guide for databases](https://docs.djangoproject.com/en/3.1/ref/databases/) for further information.
|
You also should setup a dedicated database server, the built-in SQLite file is not recommened for production use. Reference [django's guide for databases](https://docs.djangoproject.com/en/3.1/ref/databases/) for further information.
|
||||||
|
|
||||||
Before making the django instance public, you should tweak the config `settings.py`:
|
Before making the django instance public, you should tweak the config `settings.py`:
|
||||||
1. Change the secret key, the one found in the config is already public. Choose something secure (i.e. [this](https://duckduckgo.com/?q=password+generator+64))
|
1. Change the secret key, the one found in the config is already public. Choose something secure (i.e. [this](https://duckduckgo.com/?q=password+generator+64)).
|
||||||
2. Turn off debug mode by setting `DEBUG = False`
|
2. Turn off debug mode by setting `DEBUG = False`.
|
||||||
3. Tune the localization settings, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/i18n/)
|
3. Tune the localization settings, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/i18n/).
|
||||||
|
|
||||||
Run `lostplaces/managy.py collectstatic` you should be ready to go.
|
Run `lostplaces/managy.py collectstatic` and you should be ready to go.
|
||||||
|
|
||||||
|
|
||||||
## Installing the lostplaces_app to an existing django instance
|
## Installing the lostplaces_app to an existing django instance
|
||||||
|
|
||||||
### Installing django and the lostplaces app
|
### Installing django and the lostplaces app
|
||||||
|
|
||||||
If you haven't already setup an django instance, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/install/).
|
If you haven't already setup a django instance, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/install/).
|
||||||
|
|
||||||
After that, download the desired release (probably the latest one) [from the realeases page](https://git.mowoe.com/reverend/lostplaces-backend/releases) and install it using `pip install --user name-of-the-file.tar.gz`.
|
After that, download the desired release (probably the latest one) [from the realeases page](https://git.mowoe.com/reverend/lostplaces-backend/releases) and install it using `pip install --user name-of-the-file.tar.gz`
|
||||||
|
|
||||||
*Note: You can run pip install without the --user flag, which will require root privileges and introduces potential security issues*
|
*Note: You can run pip install without the --user flag, which will require root privileges and introduces potential security issues.*
|
||||||
|
|
||||||
### Configuring the django instance
|
### Configuring the django instance
|
||||||
|
|
||||||
Now configure your `settings.py` as follows:
|
Now configure your `settings.py` as follows:
|
||||||
1. Add the following apps to the django project
|
1. Add the following apps to the django project.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
@@ -95,7 +100,7 @@ INSTALLED_APPS = [
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Set the URL's and Root-directories for file handling, for example
|
2. Set the URL's and Root-directories for file handling, for example:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
@@ -105,13 +110,13 @@ MEDIA_URL = '/uploads/'
|
|||||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Set the user model (this will be changed in the next release)
|
3. Set the user model (this will be changed in the next release):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
AUTH_USER_MODEL = 'lostplaces_app.Explorer'
|
AUTH_USER_MODEL = 'lostplaces_app.Explorer'
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Set the URL's for login, for example
|
4. Set the URL's for login, for example:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
LOGIN_URL = reverse_lazy('login')
|
LOGIN_URL = reverse_lazy('login')
|
||||||
@@ -120,21 +125,19 @@ LOGOUT_REDIRECT_URL = reverse_lazy('lostplaces_home')
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Configuring the URL's
|
### Configuring the URL's
|
||||||
In the `urls.py` configure the `urlpatter` like this
|
In the `urls.py` configure the `urlpatter` like this:
|
||||||
```python
|
```python
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
path('signup/', SignUpView.as_view(), name='signup'), # If you want to use lostplaces sign up view
|
path('signup/', SignUpView.as_view(), name='signup'), # If you want to use lostplaces' sign up view.
|
||||||
path('explorers/', include('django.contrib.auth.urls')), # You can change the 'explorers/' to whatever you desire
|
path('explorers/', include('django.contrib.auth.urls')), # You can change the 'explorers/' to whatever you desire.
|
||||||
path('', include('lostplaces_app.urls')), # In this configuration lostplaces will be at the top level of you website, change '' to 'lostplaces/', if you don't want this
|
path('', include('lostplaces_app.urls')), # In this configuration lostplaces will be at the top level of you website, change '' to 'lostplaces/', if you don't want this.
|
||||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # So django can deliver user uploaded files
|
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # So django can deliver user uploaded files.
|
||||||
```
|
```
|
||||||
|
|
||||||
Before making the django instance public, you should tweak the config `settings.py`:
|
Before making the django instance public, you should tweak the config `settings.py`:
|
||||||
1. Change the secret key, the one found in the config is already public. Choose something secure (i.e. [this](https://duckduckgo.com/?q=password+generator+64))
|
1. Change the secret key, the one found in the config is already public. Choose something secure (i.e. [this](https://duckduckgo.com/?q=password+generator+64)).
|
||||||
2. Turn off debug mode by setting `DEBUG = False`
|
2. Turn off debug mode by setting `DEBUG = False`.
|
||||||
3. Tune the localization settings, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/i18n/)
|
3. Tune the localization settings, see [django's documentation](https://docs.djangoproject.com/en/3.1/topics/i18n/).
|
||||||
|
|
||||||
Run `lostplaces/managy.py collectstatic` you should be ready to go.
|
Run `lostplaces/managy.py collectstatic` you should be ready to go.
|
||||||
|
|
||||||
Happy developing ;-)
|
|
||||||
|
199
Readme.rst
199
Readme.rst
@@ -1,199 +0,0 @@
|
|||||||
lostplaces-backend
|
|
||||||
==================
|
|
||||||
|
|
||||||
lostplaces-backend is a django (3.x) based webproject. It once wants to
|
|
||||||
become a software which allows a group of urban explorers to manage,
|
|
||||||
document and share the locations of lost places while not exposing too
|
|
||||||
much / any information to the public.
|
|
||||||
|
|
||||||
The software is currently in early development status, neither scope,
|
|
||||||
datalmodel(s) nor features are finalized yet. Therefore we would not
|
|
||||||
recommend to download or install this piece of software anywhere -
|
|
||||||
except your local django dev server.
|
|
||||||
|
|
||||||
Features
|
|
||||||
--------
|
|
||||||
|
|
||||||
- manage lost places with lots of usefull information
|
|
||||||
- sensitive information is not accesiable for anonymous (not logged in)
|
|
||||||
users
|
|
||||||
- user self registration using a voucher system, only people you invite
|
|
||||||
can join your instance
|
|
||||||
- collaboration, every user can add informations like tags, photos and
|
|
||||||
external links to your place
|
|
||||||
|
|
||||||
Dependencies
|
|
||||||
------------
|
|
||||||
|
|
||||||
Right now it depends on the following non-core Python 3 libraries. These
|
|
||||||
can be installed using the package manager of your distribution or into
|
|
||||||
the venv locally.
|
|
||||||
|
|
||||||
- `django <https://www.djangoproject.com/>`__ django is a high-level
|
|
||||||
Python Web framework that encourages rapid development and clean,
|
|
||||||
pragmatic design.
|
|
||||||
- `easy-thumbnails <https://github.com/SmileyChris/easy-thumbnails>`__
|
|
||||||
A powerful, yet easy to implement thumbnailing application for Django
|
|
||||||
1.11+
|
|
||||||
- `image <https://github.com/francescortiz/image>`__ Image cropping for
|
|
||||||
django
|
|
||||||
- `django-widget-tweaks <https://github.com/jazzband/django-widget-tweaks>`__
|
|
||||||
Tweak the form field rendering in templates, not in python-level form
|
|
||||||
definitions.
|
|
||||||
- `django-taggit <https://github.com/jazzband/django-taggit>`__ A
|
|
||||||
simpler approach to tagging with Django.
|
|
||||||
|
|
||||||
Installing a development instance
|
|
||||||
=================================
|
|
||||||
|
|
||||||
Clone the repository
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
``git clone https://git.mowoe.com/reverend/lostplaces-backend.git`` ##
|
|
||||||
Setting up a (pipenv) virtual environment for development
|
|
||||||
|
|
||||||
After having obtained the repository contents (either via .zip download
|
|
||||||
or git clone), you can easily setup a
|
|
||||||
`pipenv <https://docs.pipenv.org/>`__ virtual environment. The repo
|
|
||||||
provides a Pipfile for easy dependency management that does not mess
|
|
||||||
with your system.
|
|
||||||
|
|
||||||
.. code:: shell
|
|
||||||
|
|
||||||
$ cd lostplaces-backend
|
|
||||||
$ pipenv install
|
|
||||||
$ pipenv shell
|
|
||||||
(lostplaces-backend) $ lostplaces/manage.py makemigrations
|
|
||||||
(lostplaces-backend) $ lostplaces/manage.py migrate
|
|
||||||
(lostplaces-backend) $ lostplaces/manage.py createsuperuser
|
|
||||||
(lostplaces-backend) $ lostplaces/manage.py runserver --ipv6
|
|
||||||
|
|
||||||
Returning to the venv
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
.. code:: shell
|
|
||||||
|
|
||||||
$ cd lostplaces-backend
|
|
||||||
$ pipenv shell
|
|
||||||
(lostplaces-backend) $ pipenv update # If dependencies changed, or updates available
|
|
||||||
(lostplaces-backend) $ lostplaces/manage.py makemigrations # If datamodels changed
|
|
||||||
(lostplaces-backend) $ lostplaces/manage.py migrate # If datamodels changed
|
|
||||||
(lostplaces-backend) $ lostplaces/manage.py runserver --ipv6
|
|
||||||
|
|
||||||
Visit: `admin <http://localhost:8000/admin>`__ for administrative
|
|
||||||
backend or `frontend <http://localhost:8000/>`__
|
|
||||||
|
|
||||||
Installing a productive instance
|
|
||||||
================================
|
|
||||||
|
|
||||||
Currently there are two ways to deploy the lostplaces project: 1.
|
|
||||||
Cloning this repository, including the configured django instance 2.
|
|
||||||
Install the package and setup the django instance your self
|
|
||||||
|
|
||||||
Cloning the repository
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Essently, this is the same as installing an development instance, but
|
|
||||||
without the development server (manage.py runserver) and something
|
|
||||||
powerfull (Apache, NGINX) instead. You have to configure the webserve to
|
|
||||||
work with the \*SGI Api respectivly, reference `django's guide for
|
|
||||||
deployment <https://docs.djangoproject.com/en/3.1/howto/deployment/>`__
|
|
||||||
for further information.
|
|
||||||
|
|
||||||
You also should setup an dedicated database server, the build in SQLite
|
|
||||||
file is not recommened for production use. Reference `django's guide for
|
|
||||||
databases <https://docs.djangoproject.com/en/3.1/ref/databases/>`__ for
|
|
||||||
further information.
|
|
||||||
|
|
||||||
Before making the django instance public, you should tweak the config
|
|
||||||
``settings.py``: 1. Change the secret key, the one found in the config
|
|
||||||
is already public. Choose something secure (i.e.
|
|
||||||
`this <https://duckduckgo.com/?q=password+generator+64>`__) 2. Turn off
|
|
||||||
debug mode by setting ``DEBUG = False`` 3. Tune the localization
|
|
||||||
settings, see `django's
|
|
||||||
documentation <https://docs.djangoproject.com/en/3.1/topics/i18n/>`__
|
|
||||||
|
|
||||||
Run ``lostplaces/managy.py collectstatic`` you should be ready to go.
|
|
||||||
|
|
||||||
Installing the lostplaces\_app to an existing django instance
|
|
||||||
-------------------------------------------------------------
|
|
||||||
|
|
||||||
Installing django and the lostplaces app
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
If you haven't already setup an django instance, see `django's
|
|
||||||
documentation <https://docs.djangoproject.com/en/3.1/topics/install/>`__.
|
|
||||||
|
|
||||||
After that, download the desired release (probably the latest one) `from
|
|
||||||
the realeases
|
|
||||||
page <https://git.mowoe.com/reverend/lostplaces-backend/releases>`__ and
|
|
||||||
install it using ``pip install --user name-of-the-file.tar.gz``.
|
|
||||||
|
|
||||||
*Note: You can run pip install without the --user flag, which will
|
|
||||||
require root privileges and introduces potential security issues*
|
|
||||||
|
|
||||||
Configuring the django instance
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Now configure your ``settings.py`` as follows: 1. Add the following apps
|
|
||||||
to the django project
|
|
||||||
|
|
||||||
.. code:: python
|
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
|
||||||
...
|
|
||||||
'lostplaces_app',
|
|
||||||
'easy_thumbnails',
|
|
||||||
'widget_tweaks',
|
|
||||||
'django_taggit'
|
|
||||||
]
|
|
||||||
|
|
||||||
2. Set the URL's and Root-directories for file handling, for example
|
|
||||||
|
|
||||||
.. code:: python
|
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
|
|
||||||
|
|
||||||
MEDIA_URL = '/uploads/'
|
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
|
|
||||||
|
|
||||||
3. Set the user model (this will be changed in the next release)
|
|
||||||
|
|
||||||
.. code:: python
|
|
||||||
|
|
||||||
AUTH_USER_MODEL = 'lostplaces_app.Explorer'
|
|
||||||
|
|
||||||
4. Set the URL's for login, for example
|
|
||||||
|
|
||||||
.. code:: python
|
|
||||||
|
|
||||||
LOGIN_URL = reverse_lazy('login')
|
|
||||||
LOGIN_REDIRECT_URL = reverse_lazy('lostplaces_home')
|
|
||||||
LOGOUT_REDIRECT_URL = reverse_lazy('lostplaces_home')
|
|
||||||
|
|
||||||
Configuring the URL's
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
In the ``urls.py`` configure the ``urlpatter`` like this
|
|
||||||
|
|
||||||
.. code:: python
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
path('admin/', admin.site.urls),
|
|
||||||
path('signup/', SignUpView.as_view(), name='signup'), # If you want to use lostplaces sign up view
|
|
||||||
path('explorers/', include('django.contrib.auth.urls')), # You can change the 'explorers/' to whatever you desire
|
|
||||||
path('', include('lostplaces_app.urls')), # In this configuration lostplaces will be at the top level of you website, change '' to 'lostplaces/', if you don't want this
|
|
||||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # So django can deliver user uploaded files
|
|
||||||
|
|
||||||
Before making the django instance public, you should tweak the config
|
|
||||||
``settings.py``: 1. Change the secret key, the one found in the config
|
|
||||||
is already public. Choose something secure (i.e.
|
|
||||||
`this <https://duckduckgo.com/?q=password+generator+64>`__) 2. Turn off
|
|
||||||
debug mode by setting ``DEBUG = False`` 3. Tune the localization
|
|
||||||
settings, see `django's
|
|
||||||
documentation <https://docs.djangoproject.com/en/3.1/topics/i18n/>`__
|
|
||||||
|
|
||||||
Run ``lostplaces/managy.py collectstatic`` you should be ready to go.
|
|
||||||
|
|
||||||
Happy developing ;-)
|
|
@@ -4,13 +4,16 @@
|
|||||||
"""
|
"""
|
||||||
Django settings for lostplaces project.
|
Django settings for lostplaces project.
|
||||||
|
|
||||||
Generated by 'django-admin startproject' using Django 3.0.8.
|
!!! Instead of changing this file, you can override settings in !!!
|
||||||
|
!!! local_settings.py. That way it won't cause merge conflicts on pull. !!!
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 3.1.8.
|
||||||
|
|
||||||
For more information on this file, see
|
For more information on this file, see
|
||||||
https://docs.djangoproject.com/en/3.0/topics/settings/
|
https://docs.djangoproject.com/en/3.1/topics/settings/
|
||||||
|
|
||||||
For the full list of settings and their values, see
|
For the full list of settings and their values, see
|
||||||
https://docs.djangoproject.com/en/3.0/ref/settings/
|
https://docs.djangoproject.com/en/3.1/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -21,7 +24,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = 'n$(bx8(^)*wz1ygn@-ekt7rl^1km*!_c+fwwjiua8m@-x_rpl0'
|
SECRET_KEY = 'n$(bx8(^)*wz1ygn@-ekt7rl^1km*!_c+fwwjiua8m@-x_rpl0'
|
||||||
@@ -79,7 +82,7 @@ WSGI_APPLICATION = 'lostplaces.wsgi.application'
|
|||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
|
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
@@ -90,7 +93,7 @@ DATABASES = {
|
|||||||
|
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
@@ -109,7 +112,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||||||
|
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/3.0/topics/i18n/
|
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
@@ -123,7 +126,7 @@ USE_TZ = True
|
|||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/3.0/howto/static-files/
|
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
|
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
|
||||||
@@ -131,10 +134,15 @@ STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
|
|||||||
MEDIA_URL = '/uploads/'
|
MEDIA_URL = '/uploads/'
|
||||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
|
||||||
|
|
||||||
# Use custom user model
|
|
||||||
AUTH_USER_MODEL = 'lostplaces_app.Explorer'
|
|
||||||
|
|
||||||
# Templates to use for authentication
|
# Templates to use for authentication
|
||||||
LOGIN_URL = reverse_lazy('login')
|
LOGIN_URL = reverse_lazy('login')
|
||||||
LOGIN_REDIRECT_URL = reverse_lazy('lostplaces_home')
|
LOGIN_REDIRECT_URL = reverse_lazy('lostplaces_home')
|
||||||
LOGOUT_REDIRECT_URL = reverse_lazy('lostplaces_home')
|
LOGOUT_REDIRECT_URL = reverse_lazy('lostplaces_home')
|
||||||
|
|
||||||
|
|
||||||
|
# Load and override settings from local_settings.py and don't fail on errors.
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .local_settings import *
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
@@ -12,17 +12,11 @@ from .forms import ExplorerCreationForm, ExplorerChangeForm
|
|||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
|
|
||||||
class ExplorerAdmin(UserAdmin):
|
|
||||||
add_form = ExplorerCreationForm
|
|
||||||
form = ExplorerChangeForm
|
|
||||||
model = Explorer
|
|
||||||
list_display = ['email', 'username',]
|
|
||||||
|
|
||||||
class VoucherAdmin(admin.ModelAdmin):
|
class VoucherAdmin(admin.ModelAdmin):
|
||||||
fields = ['code', 'expires', 'created']
|
fields = ['code', 'expires', 'created']
|
||||||
readonly_fields = ['created']
|
readonly_fields = ['created']
|
||||||
|
|
||||||
admin.site.register(Explorer, ExplorerAdmin)
|
admin.site.register(Explorer)
|
||||||
admin.site.register(Voucher, VoucherAdmin)
|
admin.site.register(Voucher, VoucherAdmin)
|
||||||
admin.site.register(Place)
|
admin.site.register(Place)
|
||||||
admin.site.register(PlaceImage)
|
admin.site.register(PlaceImage)
|
||||||
|
@@ -5,11 +5,12 @@
|
|||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
|
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
|
||||||
from .models import Explorer, Place, PlaceImage, Voucher
|
from django.contrib.auth.models import User
|
||||||
|
from lostplaces_app.models import Place, PlaceImage, Voucher
|
||||||
|
|
||||||
class ExplorerCreationForm(UserCreationForm):
|
class ExplorerCreationForm(UserCreationForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Explorer
|
model = User
|
||||||
fields = ('username', 'email')
|
fields = ('username', 'email')
|
||||||
voucher = forms.CharField(
|
voucher = forms.CharField(
|
||||||
max_length=30,
|
max_length=30,
|
||||||
@@ -30,7 +31,7 @@ class ExplorerCreationForm(UserCreationForm):
|
|||||||
|
|
||||||
class ExplorerChangeForm(UserChangeForm):
|
class ExplorerChangeForm(UserChangeForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Explorer
|
model = User
|
||||||
fields = ('username', 'email')
|
fields = ('username', 'email')
|
||||||
|
|
||||||
class PlaceForm(forms.ModelForm):
|
class PlaceForm(forms.ModelForm):
|
||||||
|
@@ -10,22 +10,40 @@ import os
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.contrib.auth.models import AbstractUser
|
|
||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from easy_thumbnails.fields import ThumbnailerImageField
|
from easy_thumbnails.fields import ThumbnailerImageField
|
||||||
from taggit.managers import TaggableManager
|
from taggit.managers import TaggableManager
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
class Explorer(AbstractUser):
|
|
||||||
|
class Explorer(models.Model):
|
||||||
"""
|
"""
|
||||||
Custom user model
|
Profile that is linked to the a User.
|
||||||
Addtional fields wbd
|
Every user has a profile.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
user = models.OneToOneField(
|
||||||
|
User,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name='explorer'
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.username
|
return self.user.name
|
||||||
|
|
||||||
|
@receiver(post_save, sender=User)
|
||||||
|
def create_user_profile(sender, instance, created, **kwargs):
|
||||||
|
if created:
|
||||||
|
Explorer.objects.create(user=instance)
|
||||||
|
|
||||||
|
@receiver(post_save, sender=User)
|
||||||
|
def save_user_profile(sender, instance, **kwargs):
|
||||||
|
instance.explorer.save()
|
||||||
|
|
||||||
|
|
||||||
class Voucher(models.Model):
|
class Voucher(models.Model):
|
||||||
"""
|
"""
|
||||||
@@ -42,6 +60,7 @@ class Voucher(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Voucher " + str(self.pk)
|
return "Voucher " + str(self.pk)
|
||||||
|
|
||||||
|
|
||||||
class Place (models.Model):
|
class Place (models.Model):
|
||||||
"""
|
"""
|
||||||
Place defines a lost place (location, name, description etc.).
|
Place defines a lost place (location, name, description etc.).
|
||||||
@@ -53,7 +72,7 @@ class Place (models.Model):
|
|||||||
Explorer,
|
Explorer,
|
||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
related_name='places'
|
related_name='places'
|
||||||
)
|
)
|
||||||
location = models.CharField(max_length=50)
|
location = models.CharField(max_length=50)
|
||||||
@@ -79,7 +98,7 @@ class Place (models.Model):
|
|||||||
# Init fill values to prevent None
|
# Init fill values to prevent None
|
||||||
longitude = 0
|
longitude = 0
|
||||||
latitude = 0
|
latitude = 0
|
||||||
|
|
||||||
if amount > 0:
|
if amount > 0:
|
||||||
for place in place_list:
|
for place in place_list:
|
||||||
longitude += place.longitude
|
longitude += place.longitude
|
||||||
@@ -91,6 +110,7 @@ class Place (models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
def generate_image_upload_path(instance, filename):
|
def generate_image_upload_path(instance, filename):
|
||||||
"""
|
"""
|
||||||
Callback for generating path for uploaded images.
|
Callback for generating path for uploaded images.
|
||||||
@@ -98,13 +118,14 @@ def generate_image_upload_path(instance, filename):
|
|||||||
|
|
||||||
return 'places/' + str(uuid.uuid4())+'.'+filename.split('.')[-1]
|
return 'places/' + str(uuid.uuid4())+'.'+filename.split('.')[-1]
|
||||||
|
|
||||||
|
|
||||||
class PlaceImage (models.Model):
|
class PlaceImage (models.Model):
|
||||||
"""
|
"""
|
||||||
PlaceImage defines an image file object that points to a file in uploads/.
|
PlaceImage defines an image file object that points to a file in uploads/.
|
||||||
Intermediate image sizes are generated as defined in SIZES.
|
Intermediate image sizes are generated as defined in SIZES.
|
||||||
PlaceImage references a Place to which it belongs.
|
PlaceImage references a Place to which it belongs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
description = models.TextField(blank=True)
|
description = models.TextField(blank=True)
|
||||||
filename = ThumbnailerImageField(upload_to=generate_image_upload_path)
|
filename = ThumbnailerImageField(upload_to=generate_image_upload_path)
|
||||||
place = models.ForeignKey(
|
place = models.ForeignKey(
|
||||||
@@ -117,7 +138,7 @@ class PlaceImage (models.Model):
|
|||||||
Explorer,
|
Explorer,
|
||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
related_name='images'
|
related_name='images'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -130,6 +151,8 @@ class PlaceImage (models.Model):
|
|||||||
return ' '.join([self.place.name, str(self.pk)])
|
return ' '.join([self.place.name, str(self.pk)])
|
||||||
|
|
||||||
# These two auto-delete files from filesystem when they are unneeded:
|
# These two auto-delete files from filesystem when they are unneeded:
|
||||||
|
|
||||||
|
|
||||||
@receiver(models.signals.post_delete, sender=PlaceImage)
|
@receiver(models.signals.post_delete, sender=PlaceImage)
|
||||||
def auto_delete_file_on_delete(sender, instance, **kwargs):
|
def auto_delete_file_on_delete(sender, instance, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -140,6 +163,7 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
|
|||||||
if os.path.isfile(instance.filename.path):
|
if os.path.isfile(instance.filename.path):
|
||||||
os.remove(instance.filename.path)
|
os.remove(instance.filename.path)
|
||||||
|
|
||||||
|
|
||||||
@receiver(models.signals.pre_save, sender=PlaceImage)
|
@receiver(models.signals.pre_save, sender=PlaceImage)
|
||||||
def auto_delete_file_on_change(sender, instance, **kwargs):
|
def auto_delete_file_on_change(sender, instance, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -160,6 +184,7 @@ def auto_delete_file_on_change(sender, instance, **kwargs):
|
|||||||
if os.path.isfile(old_file.path):
|
if os.path.isfile(old_file.path):
|
||||||
os.remove(old_file.path)
|
os.remove(old_file.path)
|
||||||
|
|
||||||
|
|
||||||
class ExternalLink(models.Model):
|
class ExternalLink(models.Model):
|
||||||
url = models.URLField(max_length=200)
|
url = models.URLField(max_length=200)
|
||||||
label = models.CharField(max_length=100)
|
label = models.CharField(max_length=100)
|
||||||
@@ -167,11 +192,12 @@ class ExternalLink(models.Model):
|
|||||||
Explorer,
|
Explorer,
|
||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
related_name='external_links'
|
related_name='external_links'
|
||||||
)
|
)
|
||||||
submitted_when = models.DateTimeField(auto_now_add=True, null=True)
|
submitted_when = models.DateTimeField(auto_now_add=True, null=True)
|
||||||
|
|
||||||
|
|
||||||
class PhotoAlbum(ExternalLink):
|
class PhotoAlbum(ExternalLink):
|
||||||
place = models.ForeignKey(
|
place = models.ForeignKey(
|
||||||
Place,
|
Place,
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
<a href="#" class="LP-Link">
|
<a href="#" class="LP-Link">
|
||||||
<span class="LP-Link__Text">{{tag}}</span>
|
<span class="LP-Link__Text">{{tag}}</span>
|
||||||
</a>
|
</a>
|
||||||
{% if request.user and request.user == config.tagged_item.submitted_by %}
|
{% if request.user and request.user.explorer == config.tagged_item.submitted_by %}
|
||||||
<a href="{% url config.delete_url_name tagged_id=config.tagged_item.id tag_id=tag.id %}" class="LP-Link">
|
<a href="{% url config.delete_url_name tagged_id=config.tagged_item.id tag_id=tag.id %}" class="LP-Link">
|
||||||
<span class="LP-Tag__Remove RV-Iconized__Container RV-Iconized__Container--extraSmall">
|
<span class="LP-Tag__Remove RV-Iconized__Container RV-Iconized__Container--extraSmall">
|
||||||
<svg class="RV-Iconized__Icon" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
<svg class="RV-Iconized__Icon" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<legend class="LP-Form__Legend">Tags hinzufügen</legend>
|
<legend class="LP-Form__Legend">Tags hinzufügen</legend>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="LP-Form__Composition LP-Form__Composition--breakable">
|
<div class="LP-Form__Composition LP-Form__Composition--breakable">
|
||||||
<div class="LP-Form__Field LP-Form__Button LP-Input LP-Input--tagging">
|
<div class="LP-Form__Field LP-Form__Button LP-Input LP-Input--tagging">
|
||||||
<button id="id_tag_submit_button" class="LP-Button"> Tags hinzufügen</button>
|
<button id="id_tag_submit_button" class="LP-Button"> Tags hinzufügen</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="LP-Form__Field">
|
<div class="LP-Form__Field">
|
||||||
@@ -46,11 +46,15 @@
|
|||||||
submit_form.onsubmit = () => false
|
submit_form.onsubmit = () => false
|
||||||
|
|
||||||
const tagify = new Tagify(input, {
|
const tagify = new Tagify(input, {
|
||||||
'whitelist': [
|
'whitelist': [{
|
||||||
{% for tag in all_tags %}
|
%
|
||||||
'{{tag}}',
|
for tag in all_tags %
|
||||||
{% endfor %}
|
}
|
||||||
]
|
'{{tag}}',
|
||||||
|
{
|
||||||
|
% endfor %
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
const on_form_submit = function() {
|
const on_form_submit = function() {
|
||||||
|
@@ -62,7 +62,7 @@
|
|||||||
<a target="_blank" href="{{photo_album.url}}" class="LP-Link">
|
<a target="_blank" href="{{photo_album.url}}" class="LP-Link">
|
||||||
<span class="LP-Text">{{photo_album.label}}</span>
|
<span class="LP-Text">{{photo_album.label}}</span>
|
||||||
</a>
|
</a>
|
||||||
{% if user == photo_album.submitted_by or user == place.submitted_by %}
|
{% if user.explorer == photo_album.submitted_by or user.explorer == place.submitted_by %}
|
||||||
<a href="{% url 'photo_album_delete' pk=photo_album.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete Photo Album">
|
<a href="{% url 'photo_album_delete' pk=photo_album.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete Photo Album">
|
||||||
<div class="RV-Iconized__Container RV-Iconized__Container--small">
|
<div class="RV-Iconized__Container RV-Iconized__Container--small">
|
||||||
{% icon 'trash' className="RV-Iconized__Icon" %}
|
{% icon 'trash' className="RV-Iconized__Icon" %}
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
from django.db import models as django_models
|
from django.db import models as django_models
|
||||||
from lostplaces_app.models import Explorer
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
|
||||||
def mock_user():
|
def mock_user():
|
||||||
explorer_list = Explorer.objects.all()
|
explorer_list = User.objects.all()
|
||||||
if len(explorer_list) <= 0:
|
if len(explorer_list) <= 0:
|
||||||
return Explorer.objects.create_user(
|
return User.objects.create_user(
|
||||||
username='testpeter',
|
username='testpeter',
|
||||||
password='Develop123'
|
password='Develop123'
|
||||||
)
|
)
|
||||||
|
@@ -19,7 +19,7 @@ def mock_place_image():
|
|||||||
filename=mock.MagicMock(spec=File, name='FileMock'),
|
filename=mock.MagicMock(spec=File, name='FileMock'),
|
||||||
place=mock_place(),
|
place=mock_place(),
|
||||||
submitted_when=datetime.datetime.now(),
|
submitted_when=datetime.datetime.now(),
|
||||||
submitted_by=mock_user()
|
submitted_by=mock_user().explorer
|
||||||
)
|
)
|
||||||
|
|
||||||
class TestPlaceImage(TestSubmittable, TestCase):
|
class TestPlaceImage(TestSubmittable, TestCase):
|
||||||
|
@@ -14,7 +14,7 @@ def mock_place():
|
|||||||
place = Place.objects.create(
|
place = Place.objects.create(
|
||||||
name='Im a place',
|
name='Im a place',
|
||||||
submitted_when=datetime.datetime.now(),
|
submitted_when=datetime.datetime.now(),
|
||||||
submitted_by=mock_user(),
|
submitted_by=mock_user().explorer,
|
||||||
location='Testtown',
|
location='Testtown',
|
||||||
latitude=50.5,
|
latitude=50.5,
|
||||||
longitude=7.0,
|
longitude=7.0,
|
||||||
|
@@ -3,7 +3,7 @@ from django.urls import reverse_lazy
|
|||||||
|
|
||||||
from lostplaces_app.models import Place
|
from lostplaces_app.models import Place
|
||||||
|
|
||||||
from lostplaces_app.models import Explorer
|
from django.contrib.auth.models import User
|
||||||
from lostplaces_app.tests.models.test_place_model import mock_place
|
from lostplaces_app.tests.models.test_place_model import mock_place
|
||||||
from lostplaces_app.tests import mock_user
|
from lostplaces_app.tests import mock_user
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ class TestIsAuthenticated(TestCase):
|
|||||||
response = self.client.get(url, follow=True)
|
response = self.client.get(url, follow=True)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response=response,
|
response=response,
|
||||||
expected_url='?'.join([str(reverse_lazy('login')), 'redirect_to=/place/1/']),
|
expected_url='?'.join([str(reverse_lazy('login')), 'next=/place/1/']),
|
||||||
status_code=302,
|
status_code=302,
|
||||||
target_status_code=200,
|
target_status_code=200,
|
||||||
msg_prefix='''Accesing an IsAuthenticated view while not logged should
|
msg_prefix='''Accesing an IsAuthenticated view while not logged should
|
||||||
@@ -47,7 +47,7 @@ class TestIsPlaceSubmitter(TestCase):
|
|||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
def test_is_no_submitter(self):
|
def test_is_no_submitter(self):
|
||||||
Explorer.objects.create_user(
|
User.objects.create_user(
|
||||||
username='manfred',
|
username='manfred',
|
||||||
password='Develop123'
|
password='Develop123'
|
||||||
)
|
)
|
||||||
|
@@ -23,7 +23,7 @@ class TestPlaceCreateView(TestCase):
|
|||||||
response = self.client.get(url)
|
response = self.client.get(url)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response=response,
|
response=response,
|
||||||
expected_url='?'.join([str(reverse_lazy('login')), 'redirect_to=/place/1/']),
|
expected_url='?'.join([str(reverse_lazy('login')), 'next=/place/1/']),
|
||||||
status_code=302,
|
status_code=302,
|
||||||
target_status_code=200,
|
target_status_code=200,
|
||||||
msg_prefix='''Accesing PlaceDetailView while not logged should
|
msg_prefix='''Accesing PlaceDetailView while not logged should
|
||||||
|
@@ -48,7 +48,7 @@ class IsPlaceSubmitter(UserPassesTestMixin, View):
|
|||||||
# Check if currently logged in user was the submitter
|
# Check if currently logged in user was the submitter
|
||||||
place_obj = self.get_place()
|
place_obj = self.get_place()
|
||||||
|
|
||||||
if place_obj and hasattr(place_obj, 'submitted_by') and self.request.user == place_obj.submitted_by:
|
if place_obj and hasattr(place_obj, 'submitted_by') and self.request.user.explorer == place_obj.submitted_by:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self.place_submitter_error_message:
|
if self.place_submitter_error_message:
|
||||||
@@ -69,7 +69,7 @@ class PlaceAssetCreateView(IsAuthenticated, SuccessMessageMixin, CreateView):
|
|||||||
self.place = Place.objects.get(pk=place_id)
|
self.place = Place.objects.get(pk=place_id)
|
||||||
response = super().post(request, *args, **kwargs)
|
response = super().post(request, *args, **kwargs)
|
||||||
self.object.place = self.place
|
self.object.place = self.place
|
||||||
self.object.submitted_by = request.user
|
self.object.submitted_by = request.user.explorer
|
||||||
self.object.save()
|
self.object.save()
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ class PlaceAssetDeleteView(IsAuthenticated, IsPlaceSubmitter, SingleObjectMixin,
|
|||||||
if can_edit_place:
|
if can_edit_place:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self.get_object().submitted_by == self.request.user:
|
if self.get_object().submitted_by == self.request.user.explorer:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
messages.error(self.request, self.permission_denied_message)
|
messages.error(self.request, self.permission_denied_message)
|
||||||
|
@@ -72,7 +72,7 @@ class PlaceCreateView(IsAuthenticated, View):
|
|||||||
place_form = PlaceForm(request.POST)
|
place_form = PlaceForm(request.POST)
|
||||||
|
|
||||||
if place_form.is_valid():
|
if place_form.is_valid():
|
||||||
submitter = request.user
|
submitter = request.user.explorer
|
||||||
place = place_form.save(commit=False)
|
place = place_form.save(commit=False)
|
||||||
# Save logged in user as "submitted_by"
|
# Save logged in user as "submitted_by"
|
||||||
place.submitted_by = submitter
|
place.submitted_by = submitter
|
||||||
|
15
setup.py
15
setup.py
@@ -1,20 +1,25 @@
|
|||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
with open('Readme.md') as f:
|
||||||
|
readme = f.read()
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='django-lostplaces',
|
name='django-lostplaces',
|
||||||
version='0.1.a2',
|
version='0.1.a5',
|
||||||
description='A django app to manage lost places',
|
description='A django app to manage lost places',
|
||||||
author='Reverend :: Commander1024',
|
author='Reverend',
|
||||||
author_email='reverend@reverend2048.de :: commander@commander1024.de',
|
author_email='reverend@reverend2048.de',
|
||||||
url='https://git.mowoe.com/reverend/lostplaces-backend',
|
url='https://git.mowoe.com/reverend/lostplaces-backend',
|
||||||
packages=find_packages(exclude=['lostplaces']),
|
packages=find_packages(exclude=['lostplaces']),
|
||||||
|
long_description=readme,
|
||||||
|
long_description_content_type='text/markdown',
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 3 - Alpha',
|
'Development Status :: 3 - Alpha',
|
||||||
'Environment :: Web Environment',
|
'Environment :: Web Environment',
|
||||||
'Intended Audience :: Explorer :: Photographers :: Proper People',
|
|
||||||
'License :: OSI Approved :: MIT License',
|
'License :: OSI Approved :: MIT License',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python :: 3.7'
|
'Programming Language :: Python :: 3.7',
|
||||||
|
'Framework :: Django'
|
||||||
],
|
],
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'django',
|
'django',
|
||||||
|
Reference in New Issue
Block a user