From aba7e11ad0c020419d24799ac5cc0051e7ceb33e Mon Sep 17 00:00:00 2001 From: "fred.perso" Date: Tue, 7 Jan 2020 01:24:32 +0100 Subject: [PATCH 1/9] update python requirements --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 712d73cb..8d7dc46f 100755 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,8 @@ django-js-asset==1.2.2 django-leaflet==0.24.0 django-nested-admin==3.2.4 django-tables2==2.1.1 +djangorestframework==3.11.0 +djangorestframework-gis==0.15 et-xmlfile==1.0.1 jdcal==1.4.1 odfpy==1.4.0 -- GitLab From 863cd0bc548b8c884c9adea02e482b4ae204bb9a Mon Sep 17 00:00:00 2001 From: lpofredc Date: Tue, 7 Jan 2020 12:20:06 +0100 Subject: [PATCH 2/9] WIP ubuntu based geodjango image --- Dockerfile.ubuntu | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Dockerfile.ubuntu diff --git a/Dockerfile.ubuntu b/Dockerfile.ubuntu new file mode 100644 index 00000000..8e1e671b --- /dev/null +++ b/Dockerfile.ubuntu @@ -0,0 +1,33 @@ +FROM makinacorpus/geodjango:bionic-3.7 + +ENV PYTHONUNBUFFERED 1 +ENV PYTHONDONTWRITEBYTECODE 1 + +WORKDIR /usr/src/dbchiro + +COPY requirements.txt /usr/src/dbchiro + +RUN apt update -y add --no-cache \ + --upgrade \ + --repository http://dl-cdn.alpinelinux.org/alpine/edge/main \ + postgresql-client \ + libpq \ + nginx + +COPY requirements.txt /usr/src/dbchiro + +RUN python3 -m pip install --upgrade pip --no-cache-dir \ + && python3 -m pip install -r requirements.txt --no-cache-dir \ + && python3 -m pip install gunicorn --no-cache-dir + +COPY docker-entrypoint.sh /usr/bin/docker-entrypoint.sh + +COPY . /usr/src/dbchiro + +VOLUME ["/dbchiro"] + +WORKDIR /app + +EXPOSE 80 + +ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"] \ No newline at end of file -- GitLab From 0a5631cf8120a485e3dfc275be378f8ef2829e73 Mon Sep 17 00:00:00 2001 From: fredperso Date: Tue, 7 Jan 2020 23:00:33 +0100 Subject: [PATCH 3/9] Ubuntu based docker image --- .docker-entrypoint-ubuntu.sh.swp | Bin 0 -> 16384 bytes Dockerfile | 7 +- Dockerfile.ubuntu | 19 ++- docker-compose.yaml | 6 +- docker-entrypoint-ubuntu.sh | 198 +++++++++++++++++++++++++++++++ 5 files changed, 214 insertions(+), 16 deletions(-) create mode 100644 .docker-entrypoint-ubuntu.sh.swp create mode 100755 docker-entrypoint-ubuntu.sh diff --git a/.docker-entrypoint-ubuntu.sh.swp b/.docker-entrypoint-ubuntu.sh.swp new file mode 100644 index 0000000000000000000000000000000000000000..2b19f0ffc4ffe4df758b3f90d6a4b027a646157e GIT binary patch literal 16384 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 QaMbB=*myVP2Y2y*0kEbXr~m)} literal 0 HcmV?d00001 diff --git a/Dockerfile b/Dockerfile index 6b755551..697df63b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,8 @@ RUN apk add --no-cache \ --repository http://dl-cdn.alpinelinux.org/alpine/edge/main \ postgresql-client \ libpq \ - nginx\ + nginx \ + binutils \ && apk add --no-cache \ --upgrade \ --repository http://dl-cdn.alpinelinux.org/alpine/edge/main \ @@ -20,13 +21,13 @@ RUN apk add --no-cache \ postgresql-dev \ zlib-dev jpeg-dev \ alpine-sdk \ + poppler \ && apk add --no-cache \ --upgrade \ - --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing \ + --repository http://dl-cdn.alpinelinux.org/alpine/edge/community \ geos \ proj \ gdal \ - binutils \ && ln -s /usr/lib/libproj.so.15 /usr/lib/libproj.so \ && ln -s /usr/lib/libgdal.so.20 /usr/lib/libgdal.so \ && ln -s /usr/lib/libgeos_c.so.1 /usr/lib/libgeos_c.so \ diff --git a/Dockerfile.ubuntu b/Dockerfile.ubuntu index 8e1e671b..b863c145 100644 --- a/Dockerfile.ubuntu +++ b/Dockerfile.ubuntu @@ -7,20 +7,19 @@ WORKDIR /usr/src/dbchiro COPY requirements.txt /usr/src/dbchiro -RUN apt update -y add --no-cache \ - --upgrade \ - --repository http://dl-cdn.alpinelinux.org/alpine/edge/main \ +RUN apt update -y \ + && apt-get install -y \ postgresql-client \ - libpq \ - nginx + nginx \ + python3-pip COPY requirements.txt /usr/src/dbchiro -RUN python3 -m pip install --upgrade pip --no-cache-dir \ - && python3 -m pip install -r requirements.txt --no-cache-dir \ - && python3 -m pip install gunicorn --no-cache-dir +RUN python3 -m pip install --upgrade pip \ + && python3 -m pip install -r requirements.txt \ + && python3 -m pip install gunicorn -COPY docker-entrypoint.sh /usr/bin/docker-entrypoint.sh +COPY docker-entrypoint-ubuntu.sh /usr/bin/docker-entrypoint.sh COPY . /usr/src/dbchiro @@ -30,4 +29,4 @@ WORKDIR /app EXPOSE 80 -ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"] diff --git a/docker-compose.yaml b/docker-compose.yaml index 031460dd..10a47013 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,7 +4,7 @@ services: db: image: mdillon/postgis:11-alpine - container_name: dbchiro_db + container_name: dbchirodev_db volumes: - $POSTGRES_DATA_DIR:/var/lib/postgresql/data environment: @@ -14,8 +14,8 @@ services: dbchiro: - image: dbchiro/dbchiroweb:alpine - container_name: dbchiro_app + image: dbchiro/dbchiroweb:develop + container_name: dbchirodev_app volumes: - $DBCHIRO_APP_DIR:/dbchiro links: diff --git a/docker-entrypoint-ubuntu.sh b/docker-entrypoint-ubuntu.sh new file mode 100755 index 00000000..8c150769 --- /dev/null +++ b/docker-entrypoint-ubuntu.sh @@ -0,0 +1,198 @@ +#!/bin/sh + +echo "" +echo "dbChiro init_____________________________________________" +echo "" +echo " * * * *" +echo " *** ********** ***" +echo " ***** ********** *****" +echo " ******* ********** *******" +echo " ********** ************ **********" +echo " ****************************************************" +echo " ******************************************************" +echo "********************************************************" +echo "********************************************************" +echo "********************************************************" +echo " ******************************************************" +echo " ******** ************************ ********" +echo " ******* * ********* * *******" +echo " ****** ******* ******" +echo " ***** ***** *****" +echo " *** *** ***" +echo " ** * **" +echo "" + + +export DBHOST=${POSTGRES_HOST:-db} +export DBNAME=${POSTGRES_DB:-dbchiro} +export DBUSER=${POSTGRES_USER:-dbadmin} +export DBPWD=${POSTGRES_PASSWORD:-myDbPassword} +export DBPORT=${POSTGRES_PORT:-5432} +export SECRETKEY=${SECRETKEY:-$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c50)} +export SRID=${SRID:-4326} +export X=${DEFAULT_X:-5} +export Y=${DEFAULT_Y:-45} +export SETTINGS=${SETTINGS:-production} + +export SU_USERNAME=${SU_USERNAME:-admin} +export SU_PWD=${SU_PWD:-admin} +export SU_EMAIL=${SU_EMAIL:-admin@domain.tld} + +export EMAIL_SMTP=${EMAIL_SMTP:-smtp.domain.tld} +export EMAIL_SSL=${EMAIL_SSL:-False} +export EMAIL_PORT=${EMAIL_PORT:-465} +export EMAIL_USER=${EMAIL_USER:-$SU_EMAIL} +export EMAIL_PWD=${EMAIL_PWD:-passWord} +export EMAIL_DEFAULT_FROM=${EMAIL_SMTP:-$EMAIL_USER} + +export IGN_API_KEY=${IGN_API_KEY:-yourapikey} + +shopt -s dotglob nullglob +mv /usr/src/dbchiro/* /app/ + +if [ ! -f /dbchiro/config.py ]; then + echo "generate new config file" + mv /app/dbchiro/settings/configuration/config.py.sample /dbchiro/config.py + sed -i "s/dbHost/${DBHOST}/g" /dbchiro/config.py + sed -i "s/dbName/${DBNAME}/g" /dbchiro/config.py + sed -i "s/dbUser/${DBUSER}/g" /dbchiro/config.py + sed -i "s/dbPassword/${DBPWD}/g" /dbchiro/config.py + sed -i "s/dbPort/${DBPORT}/g" /dbchiro/config.py + sed -i "s/secretKey/${SECRETKEY}/g" /dbchiro/config.py + sed -i "s/geoDefaultProj/${SRID}/g" /dbchiro/config.py + sed -i "s/geoDefaultX/${X}/g" /dbchiro/config.py + sed -i "s/geoDefaultY/${Y}/g" /dbchiro/config.py + sed -i "s/emailSmtpHost/${EMAIL_SMTP}/g" /dbchiro/config.py + sed -i "s/emailSsl/${EMAIL_SSL}/g" /dbchiro/config.py + sed -i "s/emailPort/${EMAIL_PORT}/g" /dbchiro/config.py + sed -i "s/emailAddress/${EMAIL_USER}/g" /dbchiro/config.py + sed -i "s/emailPassword/${EMAIL_PWD}/g" /dbchiro/config.py + sed -i "s/emailDefaultFrom/${EMAIL_DEFAULT_FROM}/g" /dbchiro/config.py + sed -i "s/IGN_API_KEY = 'yourapikey'/IGN_API_KEY = '${IGN_API_KEY}'/g" /dbchiro/config.py +else + echo "config file already exists" +fi +rm -f /app/dbchiro/settings/configuration/config.py +ln -s /dbchiro/config.py /app/dbchiro/settings/configuration/config.py + + +djapps="accounts blog dicts geodata management sights" +if [ ! -d /dbchiro/migrations ]; then + echo "Create symlink for migrations dirs" + mkdir /dbchiro/migrations + for a in $djapps; do + echo "create $a migrations symlink" + if [ ! -d /dbchiro/migrations/$a ]; then + mkdir /dbchiro/migrations/$a + else + "$a migration dir and symlink already exists" + fi + done +else + echo "Migrations dir already exists" +fi + +for a in $djapps; do + rm -rf /app/$a/migrations + ln -s /dbchiro/migrations/$a /app/$a/migrations +done + +if [ ! -d /dbchiro/media ]; then + echo "Create media dir" + mkdir /dbchiro/media +else + echo "Media dir already exusts" +fi + +rm -rf /app/media +ln -s /dbchiro/media /app/media + +until pg_isready -h $DBHOST -p $DBPORT +do + echo "Awaiting Database container" + sleep 1 +done +sleep 2 + +cd /app + +chown -R www-data:www-data /app + +export DJANGO_SETTINGS_MODULE=dbchiro.settings.$SETTINGS + +echo "************ Init database ****************" + +python3 -m manage makemigrations accounts core blog dicts geodata management sights +python3 -m manage migrate +python3 -m manage collectstatic --noinput + + +if [ ! -f /dbchiro/logo_site.png ]; then + echo "Create default site logo image" + cp /app/static/img/logo_site.png.sample /dbchiro/logo_site.png +else + echo "Site logo already exists" +fi +rm -f /app/static/img/logo_site.png +ln -s /dbchiro/logo_site.png /app/static/img/logo_site.png + +echo "************** Create dbChiro SU ******************" + +script=" +from accounts.models import Profile; + +username = '$SU_USERNAME'; +password = '$SU_PWD'; +email = '$SU_EMAIL'; + +if Profile.objects.filter(username=username).count()==0: + superuser=Profile.objects.create_user(username, email, password); + superuser.is_superuser=True; + superuser.save(); + print('Superuser',username,'created.'); +else: + print('Superuser creation skipped.') +" +printf "$script" | python3 manage.py shell + + +echo "************** Populate with initial data ***************" + +export countdict=$(printf "from dicts.models import PlacePrecision; print(PlacePrecision.objects.count())" | python3 manage.py shell) + +if [ $countdict -eq 0 ] + then + echo "load dicts data" + python3 -m manage loaddata datas/dicts.json + rm -f datas/dicts.json + echo "dicts data loaded" + else + echo "dicts data already exists" +fi + +export countterritory=$(printf "from geodata.models import Territory; print(Territory.objects.count())" | python3 manage.py shell) + +if [ $countterritory -eq 0 ] + then + echo "load geo datas, this may take a while..." + python3 -m manage loaddata datas/geodata.json.gz + rm -f datas/geodata.json.gz + echo "geo datas loaded" + else + echo "geo datas already exists" +fi + + +#nginx Conf +echo "************ Configure NGINX ***************" +rm -f /etc/nginx/conf.d/default.conf +cp /app/dbchiro/settings/configuration/nginx_dbchiro.conf.sample /etc/nginx/conf.d/dbchiro.conf +rm -rf /etc/nginx/sites-enabled/* +sed -i "s/pathToApp/app/g" /etc/nginx/conf.d/dbchiro.conf +#/etc/init.d/nginx restart +nginx -g "daemon off;" & + +echo "************ Start Gunicorn ***************" +gunicorn -b 127.0.0.1:8000 dbchiro.wsgi + + -- GitLab From 9131586cf6e55cba18921f1ebbc74b37ae32cd16 Mon Sep 17 00:00:00 2001 From: "fred.perso" Date: Tue, 7 Jan 2020 23:06:59 +0100 Subject: [PATCH 4/9] Fix superuser creation skipped if superuser exists --- accounts/models.py | 4 +- accounts/tables.py | 54 ++- accounts/urls.py | 6 +- accounts/views.py | 20 +- blog/urls.py | 2 +- blog/views.py | 76 ++-- core/js.py | 2 +- core/mixins.py | 4 +- core/views.py | 12 +- dbchiro/settings/helper/context_processors.py | 4 +- dicts/admin.py | 4 +- docker-entrypoint-ubuntu.sh | 4 +- docker-entrypoint.sh | 6 +- geodata/models.py | 12 +- management/models.py | 49 +-- management/tables.py | 87 +++-- management/urls.py | 81 +++-- sights/countdetail/urls.py | 8 +- sights/countdetail/views.py | 36 +- sights/forms.py | 102 ++++-- sights/metaplace/urls.py | 16 +- sights/mixins.py | 340 ++++++++++++------ sights/session/urls.py | 41 +-- sights/session/views.py | 36 +- sights/urls.py | 12 +- synthesis/urls.py | 4 +- synthesis/views.py | 111 +++--- 27 files changed, 664 insertions(+), 469 deletions(-) diff --git a/accounts/models.py b/accounts/models.py index 0b3a1465..288224e7 100755 --- a/accounts/models.py +++ b/accounts/models.py @@ -82,9 +82,7 @@ class Profile(AbstractBaseUser, PermissionsMixin): default=False, verbose_name=_("Peut éditer toutes les données") ) catchauth = models.ManyToManyField( - 'management.CatchAuth', - blank=True, - verbose_name=_("Authorisations de capture"), + "management.CatchAuth", blank=True, verbose_name=_("Authorisations de capture"), ) organism = models.CharField( max_length=255, blank=True, null=True, verbose_name=_("Organisme") diff --git a/accounts/tables.py b/accounts/tables.py index abb20271..17fd6c6b 100644 --- a/accounts/tables.py +++ b/accounts/tables.py @@ -6,7 +6,7 @@ from .models import Profile class ProfileTable(tables.Table): - ACTIONS = ''' + ACTIONS = """
- ''' + """ MODIFY_BY = """ {% if record.updated_by %}{{record.updated_by}}{% else %}{{ record.created_by }}{% endif %} """ - is_resp = tables.BooleanColumn(verbose_name=_('Responsable local')) - access_all_data = tables.BooleanColumn(verbose_name=_('Peut tout lire')) - edit_all_data = tables.BooleanColumn(verbose_name=_('Peut tout éditer')) - mobile_phone = tables.Column(verbose_name=_('n° mobile')) - home_phone = tables.Column(verbose_name=_('n° domicile')) - email = tables.EmailColumn(verbose_name=_('@email')) + is_resp = tables.BooleanColumn(verbose_name=_("Responsable local")) + access_all_data = tables.BooleanColumn(verbose_name=_("Peut tout lire")) + edit_all_data = tables.BooleanColumn(verbose_name=_("Peut tout éditer")) + mobile_phone = tables.Column(verbose_name=_("n° mobile")) + home_phone = tables.Column(verbose_name=_("n° domicile")) + email = tables.EmailColumn(verbose_name=_("@email")) actions = tables.TemplateColumn( - ACTIONS, verbose_name="Actions", orderable=False, attrs={'th': {'style': 'width: 75px;'}}) - username = tables.LinkColumn('accounts:user_detail', args=[A('id')], accessor='username') + ACTIONS, + verbose_name="Actions", + orderable=False, + attrs={"th": {"style": "width: 75px;"}}, + ) + username = tables.LinkColumn( + "accounts:user_detail", args=[A("id")], accessor="username" + ) modify_by = tables.TemplateColumn( - MODIFY_BY, verbose_name="Dernière modification", orderable=False) + MODIFY_BY, verbose_name="Dernière modification", orderable=False + ) last_login = tables.DateTimeColumn() class Meta: model = Profile - template = 'table_bootstrap.html' - attrs = {'class': 'table table-striped'} + template = "table_bootstrap.html" + attrs = {"class": "table table-striped"} fields = ( - 'actions', 'username', 'email', 'first_name', 'last_name', 'organism', 'is_active', 'is_resp', - 'access_all_data', - 'edit_all_data', 'home_phone', 'mobile_phone', 'addr_city', 'last_login', 'modify_by',) - exclude = ('id',) + "actions", + "username", + "email", + "first_name", + "last_name", + "organism", + "is_active", + "is_resp", + "access_all_data", + "edit_all_data", + "home_phone", + "mobile_phone", + "addr_city", + "last_login", + "modify_by", + ) + exclude = ("id",) diff --git a/accounts/urls.py b/accounts/urls.py index 4c30a03f..4f9210a6 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -24,7 +24,11 @@ urlpatterns = [ path("/detail", UserDetail.as_view(), name="user_detail"), path("myprofile/change_password", change_password, name="change_password"), path("myprofile/detail", MyProfileDetail.as_view(), name="myprofile_detail"), - path("myprofile/detail/export", MyProfileDetailExport.as_view(), name="myprofile_detail_export"), + path( + "myprofile/detail/export", + MyProfileDetailExport.as_view(), + name="myprofile_detail_export", + ), path("myprofile/update", MyProfileUpdate.as_view(), name="myprofile_update"), path("list", UserListView.as_view(), name="user_search"), ] diff --git a/accounts/views.py b/accounts/views.py index 890a37a4..786c70a2 100755 --- a/accounts/views.py +++ b/accounts/views.py @@ -31,6 +31,7 @@ from .tables import ProfileTable logger = logging.getLogger(__name__) + class UserCreate(ManageAccountAuthMixin, CreateView): """ User Creation View @@ -185,9 +186,7 @@ class MyProfileUpdate(ManageMyAccountAuthMixin, UpdateView): return super(MyProfileUpdate, self).form_valid(form) def get_object(self): - return get_user_model().objects.get( - id=self.request.user.id - ) # or request.POST + return get_user_model().objects.get(id=self.request.user.id) # or request.POST def get_context_data(self, **kwargs): context = super(MyProfileUpdate, self).get_context_data(**kwargs) @@ -214,31 +213,30 @@ class UserDelete(ManageAccountAuthMixin, DeleteView): class UserDetail(LoginRequiredMixin, DetailView): model = get_user_model() template_name = "accounts/profile.html" - + + class MyProfileDetail(LoginRequiredMixin, DetailView): model = get_user_model() template_name = "accounts/profile.html" def get_object(self): logger.info(self.request.user.id) - return get_user_model().objects.get( - id=self.request.user.id - ) + return get_user_model().objects.get(id=self.request.user.id) + -class MyProfileDetailExport(LoginRequiredMixin,DetailView, TemplateResponseMixin): +class MyProfileDetailExport(LoginRequiredMixin, DetailView, TemplateResponseMixin): model = get_user_model() - content_type="text/plain; charset=utf-8" + content_type = "text/plain; charset=utf-8" template_name = "accounts/personnal_data.txt" def get_object(self): logger.debug(self.request.user.id) profile = get_user_model().objects.get(id=self.request.user.id) dict = model_to_dict(profile) - del dict['password'] + del dict["password"] return dict - @login_required() def change_password(request): """ diff --git a/blog/urls.py b/blog/urls.py index 68f8af61..b1218976 100755 --- a/blog/urls.py +++ b/blog/urls.py @@ -11,4 +11,4 @@ urlpatterns = [ path("actu/add", ActuCreate.as_view(), name="actu_create"), path("actu//update", ActuUpdate.as_view(), name="actu_update"), path("actu//delete", ActuDelete.as_view(), name="actu_delete"), -] \ No newline at end of file +] diff --git a/blog/views.py b/blog/views.py index 469fb0da..2a4b2a50 100755 --- a/blog/views.py +++ b/blog/views.py @@ -19,10 +19,11 @@ from accounts.models import Profile # model = Actu # + class ActuCreate(BlogCreateAuthMixin, CreateView): model = Actu form_class = ActuForm - template_name = 'normal_form.html' + template_name = "normal_form.html" def form_valid(self, form): form.instance.created_by = self.request.user @@ -31,9 +32,11 @@ class ActuCreate(BlogCreateAuthMixin, CreateView): def get_context_data(self, **kwargs): context = super(ActuCreate, self).get_context_data(**kwargs) - context['icon'] = 'fi-align-left' - context['title'] = _('Ajout d\'une actualité') - context['js'] = """ + context["icon"] = "fi-align-left" + context["title"] = _("Ajout d'une actualité") + context[ + "js" + ] = """ """ return context @@ -41,7 +44,7 @@ class ActuCreate(BlogCreateAuthMixin, CreateView): class ActuUpdate(BlogModifyAuthMixin, UpdateView): model = Actu form_class = ActuForm - template_name = 'normal_form.html' + template_name = "normal_form.html" def form_valid(self, form): form.instance.created_by = self.request.user @@ -49,57 +52,64 @@ class ActuUpdate(BlogModifyAuthMixin, UpdateView): def get_context_data(self, **kwargs): context = super(ActuUpdate, self).get_context_data(**kwargs) - context['icon'] = 'fi-align-left' - context['title'] = _('Modification d\'une actualité') - context['js'] = """ + context["icon"] = "fi-align-left" + context["title"] = _("Modification d'une actualité") + context[ + "js" + ] = """ """ return context class ActuDelete(BlogModifyAuthMixin, DeleteView): model = Actu - template_name = 'confirm_delete.html' - success_url = reverse_lazy('blog:home') + template_name = "confirm_delete.html" + success_url = reverse_lazy("blog:home") def get_context_data(self, **kwargs): context = super(ActuDelete, self).get_context_data(**kwargs) - context['icon'] = 'fi-trash' - context['title'] = _('Suppression d\'une actualité') - context['message_alert'] = _('Êtes-vous certain de vouloir supprimer l\'actualité') + context["icon"] = "fi-trash" + context["title"] = _("Suppression d'une actualité") + context["message_alert"] = _( + "Êtes-vous certain de vouloir supprimer l'actualité" + ) return context class ActuDetail(DetailView): model = Actu - template_name = 'actu_detail.html' + template_name = "actu_detail.html" def get_context_data(self, **kwargs): context = super(ActuDetail, self).get_context_data(**kwargs) - context['icon'] = 'fi-align-left' - context['js'] = """ + context["icon"] = "fi-align-left" + context[ + "js" + ] = """ """ return context + class ActuList(ListView): model = Actu - template_name = 'actu_list.html' - ordering = '-timestamp_update' + template_name = "actu_list.html" + ordering = "-timestamp_update" paginate_by = 3 def get_context_data(self, **kwargs): context = super(ActuList, self).get_context_data(**kwargs) - context['icon'] = 'fas fa-info-circle' - context['title'] = _('Dernières actualités') - context['sightingsicon'] = 'fi-eye' - context['sightingscount'] = Sighting.objects.all().count() - context['sightingstext'] = _('observations') - context['placesicon'] = 'fi-marker' - context['placescount'] = Place.objects.all().count() - context['placestext'] = _('localités') - context['sessionsicon'] = 'far fa-calendar-alt' - context['sessionscount'] = Session.objects.all().count() - context['sessionstext'] = _('sessions') - context['observersicon'] = 'fi-torsos-all-female' - context['observerscount'] = Profile.objects.all().count() - context['observerstext'] = _('observateurs') - return context \ No newline at end of file + context["icon"] = "fas fa-info-circle" + context["title"] = _("Dernières actualités") + context["sightingsicon"] = "fi-eye" + context["sightingscount"] = Sighting.objects.all().count() + context["sightingstext"] = _("observations") + context["placesicon"] = "fi-marker" + context["placescount"] = Place.objects.all().count() + context["placestext"] = _("localités") + context["sessionsicon"] = "far fa-calendar-alt" + context["sessionscount"] = Session.objects.all().count() + context["sessionstext"] = _("sessions") + context["observersicon"] = "fi-torsos-all-female" + context["observerscount"] = Profile.objects.all().count() + context["observerstext"] = _("observateurs") + return context diff --git a/core/js.py b/core/js.py index 43bbbdf8..f8a8c001 100644 --- a/core/js.py +++ b/core/js.py @@ -46,4 +46,4 @@ TimeInput = """ format: 'HH:mm' }); }); -""" \ No newline at end of file +""" diff --git a/core/mixins.py b/core/mixins.py index 217d9b77..def6a17a 100644 --- a/core/mixins.py +++ b/core/mixins.py @@ -2,7 +2,7 @@ Mixins """ -from django.contrib.auth.mixins import LoginRequiredMixin,UserPassesTestMixin +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin class ManageAccountAuthMixin: @@ -29,8 +29,6 @@ class ManageAccountAuthMixin: return redirect("core:view_unauth") - - class AdminRequiredMixin(LoginRequiredMixin, UserPassesTestMixin): def test_func(self): return self.request.user.is_superuser or self.request.user.is_staff diff --git a/core/views.py b/core/views.py index 80435c57..16aa1efa 100644 --- a/core/views.py +++ b/core/views.py @@ -5,15 +5,18 @@ from .mixins import AdminRequiredMixin from .functions import version import os + def db_datas(): with connection.cursor() as cursor: - cursor.execute("SELECT pg_size_pretty( pg_database_size( current_database() ) ), version(), postgis_version()") + cursor.execute( + "SELECT pg_size_pretty( pg_database_size( current_database() ) ), version(), postgis_version()" + ) row = cursor.fetchone() print(row) data = {} - data['database_size']= row[0] - data['database_pg_version'] = row[1] - data['database_postgis_version'] = row[2] + data["database_size"] = row[0] + data["database_pg_version"] = row[1] + data["database_postgis_version"] = row[2] return data @@ -49,4 +52,3 @@ class SystemInformation(AdminRequiredMixin, TemplateView): sysinfo = {**server_info, **db_datas()} context["sysinfo"] = sysinfo return context - diff --git a/dbchiro/settings/helper/context_processors.py b/dbchiro/settings/helper/context_processors.py index abb276d6..ac125454 100755 --- a/dbchiro/settings/helper/context_processors.py +++ b/dbchiro/settings/helper/context_processors.py @@ -5,6 +5,6 @@ from core.functions import version def site_info(request): """Return SITE NAME to frontend""" return { - 'SITE_NAME': settings.SITE_NAME, - 'VERSION' : version(), + "SITE_NAME": settings.SITE_NAME, + "VERSION": version(), } diff --git a/dicts/admin.py b/dicts/admin.py index 5ed939b0..9bba9550 100755 --- a/dicts/admin.py +++ b/dicts/admin.py @@ -14,10 +14,10 @@ class CustomApp(AppConfig): name = "dicts" def ready(self): - models = apps.get_app_config('dicts').get_models() + models = apps.get_app_config("dicts").get_models() for model in models: admin_class = type("AdminClass", (ListAdminMixin, admin.ModelAdmin), {}) try: admin.site.register(model, admin_class) except admin.sites.AlreadyRegistered as e: - pass \ No newline at end of file + pass diff --git a/docker-entrypoint-ubuntu.sh b/docker-entrypoint-ubuntu.sh index 8c150769..53c97455 100755 --- a/docker-entrypoint-ubuntu.sh +++ b/docker-entrypoint-ubuntu.sh @@ -145,13 +145,13 @@ username = '$SU_USERNAME'; password = '$SU_PWD'; email = '$SU_EMAIL'; -if Profile.objects.filter(username=username).count()==0: +if Profile.objects.filter(is_superuser=True).count()==0: superuser=Profile.objects.create_user(username, email, password); superuser.is_superuser=True; superuser.save(); print('Superuser',username,'created.'); else: - print('Superuser creation skipped.') + print('One or more Superuser already exists, creation skipped.') " printf "$script" | python3 manage.py shell diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 1bd1ea1e..813ef746 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -101,7 +101,7 @@ if [ ! -d /dbchiro/media ]; then echo "Create media dir" mkdir /dbchiro/media else - echo "Media dir already exusts" + echo "Media dir already exists" fi rm -rf /app/media @@ -145,13 +145,13 @@ username = '$SU_USERNAME'; password = '$SU_PWD'; email = '$SU_EMAIL'; -if Profile.objects.filter(username=username).count()==0: +if Profile.objects.filter(is_superuser=True).count()==0: superuser=Profile.objects.create_user(username, email, password); superuser.is_superuser=True; superuser.save(); print('Superuser',username,'created.'); else: - print('Superuser creation skipped.') + print('One or more Superuser already exists, creation skipped.') " printf "$script" | python manage.py shell diff --git a/geodata/models.py b/geodata/models.py index 551cba32..0872e863 100755 --- a/geodata/models.py +++ b/geodata/models.py @@ -52,11 +52,14 @@ class Municipality(models.Model): class LandCover(models.Model): id = models.AutoField(primary_key=True) code = models.ForeignKey( - LandCoverCLC, verbose_name=_("Code"), blank=True, null=True, on_delete=models.CASCADE) + LandCoverCLC, + verbose_name=_("Code"), + blank=True, + null=True, + on_delete=models.CASCADE, + ) geom = models.MultiPolygonField( - srid=settings.GEODATA_SRID, - verbose_name=_("Géométries"), - spatial_index=True, + srid=settings.GEODATA_SRID, verbose_name=_("Géométries"), spatial_index=True, ) def __str__(self): @@ -75,4 +78,3 @@ class Elevation(models.Model): class Meta: verbose_name = _("Altitude") - diff --git a/management/models.py b/management/models.py index b6d06fa6..ba81cffd 100755 --- a/management/models.py +++ b/management/models.py @@ -15,17 +15,13 @@ class CatchAuth(models.Model): related_name="catchauth", ) date_start = models.DateField( - verbose_name=_("Date de début d'application"), - help_text=_("format jj/mm/aaaa"), + verbose_name=_("Date de début d'application"), help_text=_("format jj/mm/aaaa"), ) date_end = models.DateField( - verbose_name=_("Date de fin d'application"), - help_text=_("format jj/mm/aaaa"), + verbose_name=_("Date de fin d'application"), help_text=_("format jj/mm/aaaa"), ) official_reference = models.CharField( - max_length=255, - unique=True, - verbose_name=_("Référence du texte officiel"), + max_length=255, unique=True, verbose_name=_("Référence du texte officiel"), ) file = models.FileField( upload_to="catchauth/%Y/", @@ -42,7 +38,7 @@ class CatchAuth(models.Model): db_index=True, editable=False, related_name="catchauth_creator", - on_delete=models.SET_NULL + on_delete=models.SET_NULL, ) updated_by = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -51,7 +47,7 @@ class CatchAuth(models.Model): db_index=True, editable=False, related_name="catchauth_modifier", - on_delete=models.SET_NULL + on_delete=models.SET_NULL, ) def __str__(self): @@ -75,9 +71,7 @@ class Study(models.Model): max_length=255, db_index=True, verbose_name="nom du l'étude" ) year = models.CharField( - max_length=10, - db_index=True, - verbose_name="Année de réalisation l'étude", + max_length=10, db_index=True, verbose_name="Année de réalisation l'étude", ) project_manager = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -86,7 +80,7 @@ class Study(models.Model): related_name="study", null=True, blank=True, - on_delete=models.SET_NULL + on_delete=models.SET_NULL, ) # study_organism = models.ForeignKey( # 'Organism', @@ -111,9 +105,7 @@ class Study(models.Model): type_espace = models.CharField( max_length=255, blank=True, null=True, verbose_name="Type d'espace" ) - comment = models.TextField( - blank=True, null=True, verbose_name="Commentaire" - ) + comment = models.TextField(blank=True, null=True, verbose_name="Commentaire") timestamp_create = models.DateTimeField(auto_now_add=True, editable=False) timestamp_update = models.DateTimeField(auto_now=True, editable=False) created_by = models.ForeignKey( @@ -123,7 +115,7 @@ class Study(models.Model): db_index=True, editable=False, related_name="study_creator", - on_delete=models.SET_NULL + on_delete=models.SET_NULL, ) updated_by = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -132,7 +124,7 @@ class Study(models.Model): db_index=True, editable=False, related_name="study_modifier", - on_delete=models.SET_NULL + on_delete=models.SET_NULL, ) def __str__(self): @@ -170,9 +162,7 @@ class Transmitter(models.Model): max_length=30, unique=True, null=True, verbose_name="Référence" ) frequency = models.FloatField(null=True, verbose_name="Fréquence en MHz") - weight = models.FloatField( - null=True, blank=True, verbose_name="Poids (en grammes)" - ) + weight = models.FloatField(null=True, blank=True, verbose_name="Poids (en grammes)") autonomy = models.FloatField( null=True, blank=True, verbose_name="Autonomie (en jours)" ) @@ -185,24 +175,17 @@ class Transmitter(models.Model): owner = models.CharField( max_length=100, null=True, blank=True, verbose_name="Propriétaire" ) - buying_date = models.DateField( - null=True, blank=True, verbose_name="Date d'achat" - ) + buying_date = models.DateField(null=True, blank=True, verbose_name="Date d'achat") last_recond_date = models.DateField( null=True, blank=True, verbose_name="Date de dernier reconditionnement" ) status = models.CharField( - max_length=50, - choices=TRANSMITTER_STATUS, - default="ok", - verbose_name="Statut", + max_length=50, choices=TRANSMITTER_STATUS, default="ok", verbose_name="Statut", ) available = models.BooleanField( verbose_name="Disponible pour la saisie", default=True ) - comment = models.TextField( - blank=True, null=True, verbose_name="Commentaire" - ) + comment = models.TextField(blank=True, null=True, verbose_name="Commentaire") timestamp_create = models.DateTimeField(auto_now_add=True, editable=False) timestamp_update = models.DateTimeField(auto_now=True, editable=False) created_by = models.ForeignKey( @@ -212,7 +195,7 @@ class Transmitter(models.Model): db_index=True, editable=False, related_name="transmitter_creator", - on_delete=models.SET_NULL + on_delete=models.SET_NULL, ) updated_by = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -221,7 +204,7 @@ class Transmitter(models.Model): db_index=True, editable=False, related_name="transmitter_modifier", - on_delete=models.SET_NULL + on_delete=models.SET_NULL, ) def __str__(self): diff --git a/management/tables.py b/management/tables.py index 1022552d..3caf985f 100644 --- a/management/tables.py +++ b/management/tables.py @@ -4,7 +4,7 @@ from .models import Study, Transmitter, CatchAuth class StudyTable(tables.Table): - ACTIONS = ''' + ACTIONS = """
- ''' - actions = tables.TemplateColumn( - ACTIONS, verbose_name="Actions", orderable=False) + """ + actions = tables.TemplateColumn(ACTIONS, verbose_name="Actions", orderable=False) class Meta: model = Study - template = 'table_bootstrap.html' - attrs = {'class': 'table table-striped table-condensed'} - fields = ('actions', 'name', 'year', 'project_manager', 'type_etude', 'type_espace', - 'public_funding', 'public_report', 'public_raw_data', 'confidential', 'confidential_end_data', - 'timestamp_create', 'timestamp_update', 'created_by', 'comment') + template = "table_bootstrap.html" + attrs = {"class": "table table-striped table-condensed"} + fields = ( + "actions", + "name", + "year", + "project_manager", + "type_etude", + "type_espace", + "public_funding", + "public_report", + "public_raw_data", + "confidential", + "confidential_end_data", + "timestamp_create", + "timestamp_update", + "created_by", + "comment", + ) class TransmitterTable(tables.Table): - ACTIONS = ''' + ACTIONS = """
- ''' - COMMENT = ''' + """ + COMMENT = """ {% if record.comment %}