Commit 3825fcb6 authored by Thomas Frion's avatar Thomas Frion

Merge branch 'dev' into master-test

parents 1c38de76 3f04df10
......@@ -46,8 +46,13 @@ INSTALLED_APPS += [
'drf_yasg',
'leaflet',
'djgeojson',
'choucas',
# Submodule
'pghm',
'choucas'
'external_service',
'unit',
'webcam',
]
## Activation of JWT
......
......@@ -23,8 +23,6 @@ from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from pghm import views
schema_view = get_schema_view(
openapi.Info(
title="PGHM API Documentation",
......@@ -47,10 +45,9 @@ urlpatterns = [
path('admin/', admin.site.urls),
path('token/',TokenObtainPairView.as_view()),
path('token/refresh',TokenRefreshView.as_view()),
path('users/', views.UserList.as_view()),
path('users/<int:pk>', views.UserDetail.as_view()),
path('units/', views.UnitList.as_view()),
path('units/<int:pk>', views.UnitDetail.as_view()),
path('units/<slug:code>', views.UnitDetailCode.as_view()),
path('units/settings/<slug:code>',views.SettingUnitDetail.as_view())
path('', include('external_service.urls')),
path('', include('pghm.urls')),
path('', include('unit.urls')),
path('', include('webcam.urls')),
]
from django.contrib.gis import admin
from external_service.forms import *
from external_service.models import *
class ExternalServiceSettingInline(admin.TabularInline):
model = ExternalServiceSetting
extra = 1 # Number of forms to display
verbose_name = 'External Service Setting'
verbose_name_plural = 'External Service Settings'
@admin.register(ExternalService)
class ExternalServiceAdmin(admin.ModelAdmin):
# Link between ExternalServiceAdmin & ExternalServiceSettingInline
inlines = [ExternalServiceSettingInline]
# Fields used to order the list
ordering = ('name',)
# Column of the list
list_display = ('name', 'baseUrl',)
# Fields used by the search bar
search_fields = ('name', 'baseUrl',)
fieldsets = (
("Service", {'fields': ('name', 'baseUrl', 'key', 'desc',)}),
)
add_fieldsets = (
("Service", {'fields': ('name', 'baseUrl', 'key', 'desc',)}),
)
form = ExternalServiceForm
add_form = ExternalServiceForm
# We get the defined structure
def get_fieldsets(self, request, obj=None):
if not obj:
return self.add_fieldsets
return super().get_fieldsets(request, obj)
# We get the creation form
def get_form(self, request, obj=None, **kwargs):
defaults = {}
if obj is None:
defaults['form'] = self.add_form
defaults.update(kwargs)
return super().get_form(request, obj, **defaults)
from django.apps import AppConfig
class ExternalServiceConfig(AppConfig):
name = 'external_service'
from django.contrib.gis import forms
from external_service.models import *
class ExternalServiceForm(forms.ModelForm):
name = forms.CharField(
label='Nom',
max_length=1024
)
baseUrl = forms.CharField(
label='URL',
max_length=2048
)
key = forms.CharField(
label='Clef',
max_length=1024,
required=False,
)
desc = forms.CharField(
label='Description',
required=False,
widget=forms.Textarea
)
class Meta:
model = ExternalService
exclude = ()
\ No newline at end of file
# Generated by Django 3.0.4 on 2020-05-13 09:35
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='ExternalService',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=1024)),
('baseUrl', models.CharField(max_length=2048)),
('key', models.CharField(blank=True, max_length=1024, null=True)),
('desc', models.TextField(blank=True, null=True)),
],
options={
'db_table': 'pghm_external_service',
'managed': True,
},
),
migrations.CreateModel(
name='ExternalServiceSetting',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=256)),
('value', models.CharField(max_length=1024)),
('service', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='serviceSettings', to='external_service.ExternalService')),
],
options={
'db_table': 'pghm_external_service_settings',
'managed': True,
},
),
]
from __future__ import unicode_literals
from django.contrib.gis.db import models
# This class allows to manage the different external services such as IGN API
class ExternalService(models.Model):
name = models.CharField(max_length=1024) # Name of the service
baseUrl = models.CharField(max_length=2048) # Base url of the service
# Key of the service if the authentication ask for a key
key = models.CharField(max_length=1024, blank=True, null=True)
# Description of the service
desc = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
class Meta:
managed = True
db_table = 'pghm_external_service'
# This class save the different parameters of a service that may be requested
class ExternalServiceSetting(models.Model):
name = models.CharField(max_length=256)
value = models.CharField(max_length=1024)
# Link between this class and ExternalService class
service = models.ForeignKey(
ExternalService,
related_name="serviceSettings", # Relation name
on_delete=models.CASCADE
)
def __str__(self):
return self.name
class Meta:
managed = True
db_table = 'pghm_external_service_settings'
\ No newline at end of file
from rest_framework import serializers
from external_service.models import *
class ExternalServiceSettingSerializer(serializers.ModelSerializer):
class Meta:
model = ExternalServiceSetting
fields = '__all__'
class ExternalServiceSerializer(serializers.ModelSerializer):
serviceSettings = ExternalServiceSettingSerializer(many=True,read_only=True)
class Meta:
model = ExternalService
fields = '__all__'
from django.test import TestCase
# Create your tests here.
from django.urls import path
from django.conf.urls import url
from external_service import views
urlpatterns = [
path('services/', views.ServiceList.as_view()),
path('services/<int:pk>', views.ServiceDetail.as_view()),
]
\ No newline at end of file
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.schemas import SchemaGenerator
from rest_framework.response import Response
from django.http import Http404
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from external_service.serializers import *
from external_service.models import *
"""
=== Service API VIEW
"""
class ServiceList(APIView):
@swagger_auto_schema(
responses={200: ExternalServiceSerializer(many=True)},
)
def get(self, request, format=None):
serices = ExternalService.objects.all()
serializer = ExternalServiceSerializer(serices, many = True)
return Response(serializer.data)
@swagger_auto_schema(request_body=ExternalServiceSerializer,)
def post(self, request, format=None):
serializer = ExternalServiceSerializer(data = request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
"""
=== Service API VIEW, with service id
"""
class ServiceDetail(APIView):
def get_object(self, pk):
try:
return ExternalService.objects.get(pk=pk)
except ExternalService.DoesNotExist:
raise Http404
@swagger_auto_schema(
responses={200: ExternalServiceSerializer},
)
def get(self, request, pk, format=None):
service = self.get_object(pk)
serializer = ExternalServiceSerializer(service)
return Response(serializer.data)
@swagger_auto_schema(request_body=ExternalServiceSerializer,)
def put(self, request, pk, format=None):
service = self.get_object(pk)
serializer = ExternalServiceSerializer(service, data = request.data)
if serializer.is_valid(): # If sent data are correct, we update the user
serializer.save()
# We return sent data, the HTTP code is 200
return Response(serializer.data)
# We return all catched errors whith the HTTP code 400
return Response(serializer.errors, status = 400)
@swagger_auto_schema(
responses={
status.HTTP_204_NO_CONTENT: openapi.Response(
description="This should not crash (response object with no schema)"
)
}
)
def delete(self, request, pk, format=None):
service = self.get_object(pk)
service.delete() # We delete
# We return with HTTP code 204
return Response(status = 204)
......@@ -9,53 +9,6 @@ from .models import *
# We set the title of the page
admin.site.site_header = 'PGHM - CHOUCAS ADMINISTRATION'
class SettingUnitInline(admin.TabularInline):
model = SettingUnit
extra = 1
# Add Unit management to admin page
@admin.register(Unit)
class UnitAdmin(admin.OSMGeoAdmin): # We use the OpenStreet Map Admin model
inlines = [SettingUnitInline]
# Fields to which filters can be applied
list_filter = ('dept',) # Keep the comma, ovewise there will be an error
# Fields used to order the list
ordering = ('code', 'nom', 'dept')
# Column of the list
list_display = ('code', 'nom', 'email', 'dept')
# Fields used by the search bar
search_fields = ('code', 'nom', 'email', 'dept')
# We create groups to structure the forms
fieldsets = (
('Unité', {'fields': ('code', 'nom', 'email')}),
('Localisation', {'fields': ('dept','geom')}),
)
# We create groups and we select the fields for the Add form
add_fieldsets = (
('Unité', {'fields': ('code', 'nom', 'email')}),
('Localisation', {'fields': ('dept','geom')})
)
form = UnitForm
# We select the add form
add_form = UnitCreationForm
# We get the defined structure
def get_fieldsets(self, request, obj=None):
if not obj:
return self.add_fieldsets
return super().get_fieldsets(request, obj)
# We get the creation form
def get_form(self, request, obj=None, **kwargs):
defaults = {}
if obj is None:
defaults['form'] = self.add_form
defaults.update(kwargs)
return super().get_form(request, obj, **defaults)
# The classes below aims to add an input to set the user' unit
class PghmUserInline(admin.StackedInline):
model = PghmUser # We select the model
......@@ -92,6 +45,7 @@ class CustomUserAdmin(UserAdmin):
add_form = PghmUserCreationForm
# The two lines below aims to change the user administration interface
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
[{"model": "pghm.unit", "pk": 1, "fields": {"code": "PG38", "nom": "PGHM ISERE", "email": "pghm.le-versoud@gendarmerie.interieur.gouv.fr", "geom": "SRID=4326;POINT (5.850563049316404 45.21808242410029)", "dept": "38"}}, {"model": "pghm.settingunit", "pk": 1, "fields": {"name": "Zoom", "value": "\u00e7", "unit": "PG38"}}, {"model": "pghm.settingunit", "pk": 2, "fields": {"name": "Test", "value": "dfs", "unit": "PG38"}}, {"model": "pghm.pghmuser", "pk": 1, "fields": {"user": 1, "unit": 1}}]
\ No newline at end of file
[{"model": "pghm.unit", "pk": 1, "fields": {"code": "PG38", "nom": "PGHM ISERE", "email": "pghm.le-versoud@gendarmerie.interieur.gouv.fr", "geom": "SRID=4326;POINT (5.850563049316404 45.21808242410029)", "dept": "38"}}, {"model": "pghm.settingunit", "pk": 1, "fields": {"name": "Zoom", "value": "\u00e7", "unit": "PG38"}}, {"model": "pghm.settingunit", "pk": 2, "fields": {"name": "Test", "value": "dfs", "unit": "PG38"}}, {"model": "pghm.pghmuser", "pk": 1, "fields": {"user": 1, "unit": 1}}, {"model": "pghm.webcam", "pk": 1, "fields": {"name": "LE PLEYNET \u2013 SOMMET DE L\u2019OURSIERE", "station": "Les 7 Laux", "site": "https://www.skaping.com/les7laux/pleynet/oursiere", "img": null, "location": "SRID=4326;POINT (6.032351105564849 45.25316670880032)"}}, {"model": "pghm.webcam", "pk": 2, "fields": {"name": "D\u00e9part Crolles", "station": "Le Grand Revard", "site": "", "img": "", "location": "SRID=4326;POINT (5.982971348306217 45.68622369792225)"}}, {"model": "pghm.webcam", "pk": 3, "fields": {"name": "Le Belv\u00e9d\u00e8re", "station": "Le Grand Revard", "site": "", "img": "", "location": "SRID=4326;POINT (5.975914159051984 45.68002746779146)"}}, {"model": "pghm.externalservice", "pk": 1, "fields": {"name": "IGN", "baseUrl": "http://wxs.ign.fr/{key}/geoportail/wmts", "key": "2pkukowxt0podbngs5sckjry"}}, {"model": "pghm.externalservicesetting", "pk": 1, "fields": {"name": "service", "value": "&service=WMTS&request=GetTile&version=1.0.0&style=normal&tilematrixset=PM&format=image/jpeg&tilematrix={z}&tilerow={y}&tilecol={x}", "service": 1}}]
\ No newline at end of file
......@@ -3,68 +3,7 @@ from django.contrib.gis import forms
from django.contrib.auth.forms import UserCreationForm
from .models import *
# This form was created to put label.
class UnitCreationForm(forms.ModelForm):
code = forms.CharField(
label="Code",
)
nom = forms.CharField(
label="Nom",
)
email = forms.EmailField(
label="E-mail",
)
dept = forms.CharField(
label="Departement",
)
geom = forms.PointField(
label="Location",
widget=forms.OSMWidget(
attrs={
'default_lon': 2.299281,
'default_lat': 47.011913,
'default_zoom': 5.4,
}
)
)
class Meta:
model = Unit
exclude = ()
# This form was created to put label.
class UnitForm(forms.ModelForm):
code = forms.CharField(
label="Code",
)
nom = forms.CharField(
label="Nom",
)
email = forms.EmailField(
label="E-mail",
)
dept = forms.CharField(
label="Departement",
)
geom = forms.PointField(
label="Location",
widget=forms.OSMWidget(
)
)
class Meta:
model = Unit
exclude = ()
from unit.models import Unit
class PghmUserCreationForm(UserCreationForm):
......@@ -80,4 +19,4 @@ class PghmUserCreationForm(UserCreationForm):
user.save()
pghm_user = PghmUser.objects.create(user=user,unit=self.cleaned_data['unit'])
pghm_user.save()
return user
return user
\ No newline at end of file
# Generated by Django 3.0.4 on 2020-04-29 09:56
# Generated by Django 3.0.4 on 2020-05-13 09:34
from django.conf import settings
import django.contrib.gis.db.models.fields
from django.db import migrations, models
import django.db.models.deletion
......@@ -11,43 +10,16 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('unit', '__first__'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Unit',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('code', models.CharField(max_length=16, unique=True)),
('nom', models.CharField(max_length=64)),
('email', models.EmailField(max_length=64, unique=True)),
('geom', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326)),
('dept', models.CharField(blank=True, max_length=3, null=True)),
],
options={
'db_table': 'pghm_unit',
'managed': True,
},
),
migrations.CreateModel(
name='SettingUnit',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(choices=[('Zoom', 'Zoom'), ('Test', 'Test')], max_length=255)),
('value', models.CharField(max_length=1000)),
('unit_code', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='settings', to='pghm.Unit', to_field='code')),
],
options={
'db_table': 'pghm_unit_settings',
'managed': True,
},
),
migrations.CreateModel(
name='PghmUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('unit', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='pghm.Unit')),
('unit', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='unit.Unit')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
......
# Generated by Django 3.0.4 on 2020-04-29 12:07
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('pghm', '0001_initial'),
]
operations = [
migrations.RenameField(
model_name='settingunit',
old_name='unit_code',
new_name='unit',
),
migrations.AlterUniqueTogether(
name='settingunit',
unique_together={('name', 'unit')},
),
]
......@@ -3,50 +3,7 @@ from __future__ import unicode_literals
from django.contrib.gis.db import models
from django.contrib.auth.models import User
class Unit(models.Model):
code = models.CharField(max_length=16, unique = True)
nom = models.CharField(max_length=64)
email = models.EmailField(max_length=64, unique = True)
geom = models.PointField(blank=True, null=True)
dept = models.CharField(max_length=3, blank=True, null=True)
#zoom = models.IntegerField(default=10)
def __str__(self):
return self.code + ' : ' + self.nom
class Meta:
managed = True # Allows to write the table (in database)
db_table = 'pghm_unit'
class SettingUnit(models.Model):
OPTIONS = (
('Zoom','Zoom'),
('Test','Test'),
# Add more settings here like:
# ('Setting name to show','Real setting name'),
)
name = models.CharField(max_length=255,choices=OPTIONS)
value = models.CharField(max_length=1000)
unit = models.ForeignKey(
Unit,
# This line below is very important: is the name of the relationship.
# It's will use with serializers
related_name="settings",
to_field='code',
on_delete=models.CASCADE
)
def __str__(self):
return self.name+ ' = ' + self.value
class Meta:
managed = True # Allows to write the table (in database)
db_table = 'pghm_unit_settings'
unique_together = (('name','unit'),)
from unit.models import Unit
class PghmUser(models.Model):
# This line is to get the default auth_user properties.
......@@ -60,4 +17,4 @@ class PghmUser(models.Model):
class Meta:
managed = True
db_table = 'pghm_user'
db_table = 'pghm_user'
\ No newline at end of file
from rest_framework import serializers
from rest_framework import serializers
from django.contrib.auth.models import User, Group
from .models import *
from .models import *
from unit.serializers import UnitSerializer
from unit.models import Unit
# Function to check if a string is empty or not.
# If the string is empty, we raise a ValidationError
......@@ -9,25 +11,6 @@ def not_empty(value):
if not value:
raise serializers.ValidationError('The value has to be set')
# Classes allowing a model to become serializable
# Is very important for the REST API
class SettingUnitSerializer(serializers.ModelSerializer):
class Meta:
model = SettingUnit
fields = '__all__' # We select fields to serialize
class UnitSerializer(serializers.ModelSerializer):
settings = SettingUnitSerializer(many=True, read_only=True)
class Meta:
model = Unit
fields = ['code', 'nom', 'email', 'geom', 'dept', 'settings']
extra_kwargs = {
'code': {'validators': [not_empty]}, # Set validators
'email':{'validators': [not_empty]},
}
class UserSerializer(serializers.ModelSerializer):
class Meta:
......
from django.urls import path
from django.conf.urls import url
from pghm import views
urlpatterns = [
path('users/', views.UserList.as_view()),
path('users/<int:pk>', views.UserDetail.as_view()),
]
\ No newline at end of file
......@@ -7,14 +7,11 @@ from django.contrib.auth.models import User, Group
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from .serializers import *
from .models import *
from pghm.serializers import *
from pghm.models import *
"""
================================================================================
=== User API VIEW
"""
class UserList(APIView):
@swagger_auto_schema(
......@@ -75,143 +72,3 @@ class UserDetail(APIView):
user.delete() # We delete
# We return with HTTP code 204
return Response(status = 204)
"""
================================================================================
"""
"""
================================================================================
=== Unit API VIEW
"""
class UnitList(APIView):
@swagger_auto_schema(
responses={200: UnitSerializer(many=True)},
)