Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Julien Jerphanion
Rex Dri
Commits
4fe1bdf2
Commit
4fe1bdf2
authored
Feb 24, 2019
by
Florent Chehab
Browse files
Cleaning
parent
0e42118e
Changes
106
Hide whitespace changes
Inline
Side-by-side
.editorconfig
View file @
4fe1bdf2
...
...
@@ -15,4 +15,7 @@ indent_size = 4
indent_size = 2
[*.json]
indent_size = 2
\ No newline at end of file
indent_size = 2
[Makefile]
indent_style = tab
Makefile
View file @
4fe1bdf2
...
...
@@ -9,6 +9,9 @@ docker-pull:
up--build
:
docker-compose up
--build
reformat_backend
:
docker-compose
exec
backend sh
-c
"cd backend && black ."
test_backend
:
docker-compose
exec
backend sh
-c
"cd backend && pytest base_app/ frontend_app/ backend_app/"
...
...
backend/backend_app/admin.py
View file @
4fe1bdf2
...
...
@@ -7,31 +7,44 @@ import importlib
api_config
=
get_api_config
()
CLASSIC_MODELS
=
[]
# models that are versionned in the app
VERSIONNED_MODELS
=
[]
# Other models, ie not versionned
CLASSIC_MODELS
=
[]
for
model
in
api_config
:
if
"model"
in
model
and
model
[
"model"
]:
model
=
DotMap
(
model
)
if
(
not
model
.
requires_testing
)
and
(
not
model
.
ignore_in_admin
):
# Go through the API configuraion
for
entry
in
api_config
:
if
"model"
in
entry
and
entry
[
"model"
]:
model_obj
=
DotMap
(
entry
)
if
(
not
model_obj
.
requires_testing
)
and
(
not
model_obj
.
ignore_in_admin
):
# Import the model
module
=
importlib
.
import_module
(
"backend_app.models.{}"
.
format
(
model
.
import_location
)
"backend_app.models.{}"
.
format
(
model
_obj
.
import_location
)
)
if
model
.
versionned
:
VERSIONNED_MODELS
.
append
(
getattr
(
module
,
model
.
model
))
# Add it to the correct list of models
if
model_obj
.
versionned
:
VERSIONNED_MODELS
.
append
(
getattr
(
module
,
model_obj
.
model
))
else
:
CLASSIC_MODELS
.
append
(
getattr
(
module
,
model
.
model
))
CLASSIC_MODELS
.
append
(
getattr
(
module
,
model
_obj
.
model
))
#######
# Some dynamic checks
#######
for
model
in
CLASSIC_MODELS
:
admin
.
site
.
register
(
model
)
for
Model
in
CLASSIC_MODELS
:
# Register the model in the admin in a standard way
admin
.
site
.
register
(
Model
)
try
:
model
.
get_serializer
()
raise
Exception
(
"CLASSIC MODEL SHOULDN'T have this method"
)
# Check that it doesn't have the get_serializer method
Model
.
get_serializer
()
raise
Exception
(
"A 'CLASSIC MODEL' SHOULDN'T have the get_serializer method"
)
except
AttributeError
:
pass
for
model
in
VERSIONNED_MODELS
:
admin
.
site
.
register
(
model
,
CompareVersionAdmin
)
if
model
.
get_serializer
().
Meta
.
model
!=
model
:
raise
Exception
(
"Get_serializer configuration incorrect in"
,
str
(
model
))
for
Model
in
VERSIONNED_MODELS
:
# Register the model in the admin with versioning
admin
.
site
.
register
(
Model
,
CompareVersionAdmin
)
# Check that it has a get_serializer method
if
Model
.
get_serializer
().
Meta
.
model
!=
Model
:
raise
Exception
(
"Get_serializer configuration incorrect in"
,
str
(
Model
))
backend/backend_app/custom/mySerializerWithJSON.py
View file @
4fe1bdf2
...
...
@@ -2,12 +2,13 @@ from backend_app.fields import JSONField
from
rest_framework
import
serializers
field_mapping
=
serializers
.
ModelSerializer
.
serializer_field_mapping
# Small hack to register our custom JSONField class as a regular JSONfield
field_mapping
[
JSONField
]
=
serializers
.
JSONField
class
MySerializerWithJSON
(
serializers
.
ModelSerializer
):
"""
Simple class to add support for custom JSONField
support
Simple class to add
serializing
support for custom JSONField
"""
serializer_field_mapping
=
field_mapping
backend/backend_app/load_data/assets/extract_universities.py
View file @
4fe1bdf2
#!/usr/bin/env python3
"""
Script to insert the country data in the database
IT HAS TO BE RUN INSIDE ./manage.py shell
TODO YURK. Use pandas @florent !!
"""
import
csv
import
os
import
time
from
geopy.geocoders
import
Nominatim
import
reverse_geocoder
as
rg
from
geopy.geocoders
import
Nominatim
tmp
=
os
.
path
.
join
(
os
.
path
.
realpath
(
__file__
),
"../../assets/destinations.csv"
)
destinations_path
=
os
.
path
.
abspath
(
tmp
)
...
...
backend/backend_app/load_data/load_all.py
View file @
4fe1bdf2
from
.loading_scripts
import
LoadGroups
from
.loading_scripts
import
LoadAdminUser
from
.loading_scripts
import
LoadCurrencies
from
.loading_scripts
import
LoadCountries
from
.loading_scripts
import
LoadUniversities
from
.loading_scripts
import
LoadTags
from
.loading_scripts
import
LoadUniversityEx
import
reversion
from
.loading_scripts
import
(
LoadAdminUser
,
LoadCountries
,
LoadCurrencies
,
LoadGroups
,
LoadTags
,
LoadUniversities
,
LoadUniversityEx
,
)
def
load_all
():
"""Function to load all the initial data in the app
"""
with
reversion
.
create_revision
():
LoadGroups
()
admin
=
LoadAdminUser
().
get
()
...
...
backend/backend_app/load_data/loading_scripts/__init__.py
View file @
4fe1bdf2
...
...
@@ -15,3 +15,5 @@ __all__ = [
"LoadCurrencies"
,
"LoadUniversityEx"
,
]
# TODO in all loading files, use a path to the assets folder define somewhere else.
backend/backend_app/load_data/loading_scripts/loadAdminUser.py
View file @
4fe1bdf2
...
...
@@ -22,5 +22,5 @@ class LoadAdminUser(object):
username
=
os
.
environ
[
"DJANGO_ADMIN_USERNAME"
]
)[
0
]
def
get
(
self
):
def
get
(
self
)
->
User
:
return
self
.
admin
backend/backend_app/load_data/loading_scripts/loadCountries.py
View file @
4fe1bdf2
from
backend_app.models.country
import
Country
import
os
from
django.contrib.auth.models
import
User
import
pandas
as
pd
from
backend_app.models.country
import
Country
from
.loadGeneric
import
LoadGeneric
class
LoadCountries
(
LoadGeneric
):
def
__init__
(
self
,
admin
):
"""
Class to handle the loading of countries in the app
"""
def
__init__
(
self
,
admin
:
User
):
self
.
admin
=
admin
def
load
(
self
):
...
...
backend/backend_app/load_data/loading_scripts/loadCurrencies.py
View file @
4fe1bdf2
from
backend_app.models.currency
import
Currency
import
os
import
csv
from
.loadGeneric
import
LoadGeneric
import
os
from
decimal
import
Decimal
from
django.contrib.auth.models
import
User
from
backend_app.models.currency
import
Currency
from
.loadGeneric
import
LoadGeneric
class
LoadCurrencies
(
LoadGeneric
):
def
__init__
(
self
,
admin
):
"""
Load currencies in the app
"""
def
__init__
(
self
,
admin
:
User
):
self
.
admin
=
admin
def
load
(
self
):
...
...
backend/backend_app/load_data/loading_scripts/loadGeneric.py
View file @
4fe1bdf2
from
django.contrib.auth.models
import
User
from
django.utils
import
timezone
import
reversion
from
backend_app.models.abstract.my_model
import
MyModel
class
LoadGeneric
(
object
):
"""Class to handle the loading of initial data in a generic fashion
"""
@
classmethod
def
add_info_and_save
(
cls
,
obj
,
admin
):
def
add_info_and_save
(
cls
,
obj
:
MyModel
,
admin
:
User
):
with
reversion
.
create_revision
():
obj
.
moderated_by
=
admin
obj
.
updated_by
=
admin
...
...
backend/backend_app/load_data/loading_scripts/loadGroups.py
View file @
4fe1bdf2
...
...
@@ -2,6 +2,9 @@ from django.contrib.auth.models import Group
class
LoadGroups
(
object
):
"""Class to add the default user groups to the app
"""
def
__init__
(
self
):
Group
.
objects
.
get_or_create
(
name
=
"Moderators"
)
Group
.
objects
.
get_or_create
(
name
=
"DRI"
)
backend/backend_app/load_data/loading_scripts/loadTags.py
View file @
4fe1bdf2
import
json
import
os
from
django.contrib.auth.models
import
User
from
backend_app.models.tag
import
Tag
import
os
import
json
from
.loadGeneric
import
LoadGeneric
class
LoadTags
(
LoadGeneric
):
def
__init__
(
self
,
admin
):
"""
Class to load the tags in the app.
"""
def
__init__
(
self
,
admin
:
User
):
self
.
admin
=
admin
def
load
(
self
):
...
...
backend/backend_app/load_data/loading_scripts/loadUniversities.py
View file @
4fe1bdf2
from
backend_app.models.country
import
Country
import
os
from
django.contrib.auth.models
import
User
import
pandas
as
pd
from
backend_app.models.campus
import
Campus
from
backend_app.models.city
import
City
from
backend_app.models.country
import
Country
from
backend_app.models.university
import
University
from
backend_app.models.campus
import
Campus
import
os
import
pandas
as
pd
from
.loadGeneric
import
LoadGeneric
class
LoadUniversities
(
LoadGeneric
):
def
__init__
(
self
,
admin
):
"""
Load the universities in the app
"""
def
__init__
(
self
,
admin
:
User
):
self
.
admin
=
admin
def
load
(
self
):
...
...
backend/backend_app/load_data/loading_scripts/loadUniversityEx.py
View file @
4fe1bdf2
from
.loadGeneric
import
LoadGeneric
from
backend_app.models.university
import
University
from
backend_app.models.university
import
UniversityDri
from
backend_app.models.university
import
UniversityInfo
from
backend_app.models.university
import
UniversitySemestersDates
from
backend_app.models.country
import
CountryScholarship
from
backend_app.models.country
import
Country
from
backend_app.models.university
import
UniversityTaggedItem
from
datetime
import
datetime
from
django.contrib.auth.models
import
User
from
backend_app.models.country
import
Country
,
CountryScholarship
from
backend_app.models.currency
import
Currency
from
backend_app.models.tag
import
Tag
from
backend_app.models.university
import
(
University
,
UniversityDri
,
UniversityInfo
,
UniversitySemestersDates
,
UniversityTaggedItem
,
)
from
datetime
import
datetime
from
.loadGeneric
import
LoadGeneric
class
LoadUniversityEx
(
LoadGeneric
):
def
__init__
(
self
,
admin
):
"""
Load some exemple data for the EPFL
"""
def
__init__
(
self
,
admin
:
User
):
self
.
admin
=
admin
def
load
(
self
):
...
...
backend/backend_app/models/abstract/basic_module/basicModule.py
View file @
4fe1bdf2
from
django.db
import
models
from
backend_app.fields
import
JSONField
from
backend_app.models.abstract.my_model
import
(
MyModelVersionned
,
MyModelVersionnedSerializer
,
MyModelVersionnedViewSet
,
)
from
backend_app.fields
import
JSONField
from
backend_app.validators.tag
import
validate_content_against_config
from
backend_app.validators.tag.tags_config
import
USEFULL_LINKS_CONFIG
...
...
@@ -12,6 +13,15 @@ IMPORTANCE_LEVEL = (("-", "normal"), ("+", "important"), ("++", "IMPORTANT"))
class
BasicModule
(
MyModelVersionned
):
"""
Abstract module that provides defaults fields:
Title, comment, useful_links and importance_level
Those field will be inherited.
All Basic modules are also "versionned" modules
"""
title
=
models
.
CharField
(
default
=
""
,
blank
=
True
,
max_length
=
150
)
comment
=
models
.
CharField
(
default
=
""
,
blank
=
True
,
max_length
=
5000
)
useful_links
=
JSONField
(
default
=
list
)
...
...
@@ -24,7 +34,15 @@ class BasicModule(MyModelVersionned):
class
BasicModuleSerializer
(
MyModelVersionnedSerializer
):
"""
Custom serializer that performs checks on the Basic module filed
"""
def
my_validate
(
self
,
attrs
):
"""
Checks that the useful_links have been filled properly
"""
content
=
{
"useful_links"
:
attrs
[
"useful_links"
]}
config
=
{
"useful_links"
:
USEFULL_LINKS_CONFIG
}
validate_content_against_config
(
config
,
content
)
...
...
@@ -36,4 +54,8 @@ class BasicModuleSerializer(MyModelVersionnedSerializer):
class
BasicModuleViewSet
(
MyModelVersionnedViewSet
):
"""
Viewset for the Basic Module
"""
serializer_class
=
BasicModuleSerializer
backend/backend_app/models/abstract/my_model/__init__.py
View file @
4fe1bdf2
...
...
@@ -12,6 +12,7 @@ from .forTestingModeration import (
ForTestingModerationViewSet
,
)
from
.myModelVersionned
import
(
Version
,
MyModelVersionned
,
MyModelVersionnedSerializer
,
MyModelVersionnedViewSet
,
...
...
@@ -33,6 +34,7 @@ __all__ = [
"ForTestingModeration"
,
"ForTestingModerationSerializer"
,
"ForTestingModerationViewSet"
,
"Version"
,
"MyModelVersionned"
,
"MyModelVersionnedSerializer"
,
"MyModelVersionnedViewSet"
,
...
...
backend/backend_app/models/abstract/my_model/forTestingModeration.py
View file @
4fe1bdf2
from
django.db
import
models
from
backend_app.utils
import
get_model_config
,
get_viewset_permissions
from
.myModel
import
MyModel
from
.myModelSerializer
import
MyModelSerializer
from
.myModelViewSet
import
MyModelViewSet
from
django.db
import
models
from
backend_app.utils
import
get_model_config
,
get_viewset_permissions
class
ForTestingModeration
(
MyModel
):
...
...
@@ -16,7 +18,7 @@ class ForTestingModeration(MyModel):
class
ForTestingModerationSerializer
(
MyModelSerializer
):
"""
S
ame as abov
e
S
imple serializer for testing purpos
e
"""
class
Meta
:
...
...
@@ -26,7 +28,7 @@ class ForTestingModerationSerializer(MyModelSerializer):
class
ForTestingModerationViewSet
(
MyModelViewSet
):
"""
S
ame as abov
e
S
imple Viewset for testing purpos
e
"""
permission_classes
=
get_viewset_permissions
(
"ForTestingModerationViewSet"
)
...
...
backend/backend_app/models/abstract/my_model/forTestingVersioning.py
View file @
4fe1bdf2
from
django.db
import
models
import
reversion
from
backend_app.utils
import
get_model_config
,
get_viewset_permissions
from
.myModelVersionned
import
(
MyModelVersionned
,
MyModelVersionnedSerializer
,
MyModelVersionnedViewSet
,
)
from
django.db
import
models
import
reversion
from
backend_app.utils
import
get_model_config
,
get_viewset_permissions
@
reversion
.
register
()
class
ForTestingVersioning
(
MyModelVersionned
):
"""
Simple model for testing purposes
Simple model for testing purposes
(versioning)
"""
model_config
=
get_model_config
(
"ForTestingVersioning"
)
...
...
@@ -24,7 +26,7 @@ class ForTestingVersioning(MyModelVersionned):
class
ForTestingVersioningSerializer
(
MyModelVersionnedSerializer
):
"""
S
ame as above
S
imple Serializer for testing purposes (versioning)
"""
class
Meta
:
...
...
@@ -34,7 +36,7 @@ class ForTestingVersioningSerializer(MyModelVersionnedSerializer):
class
ForTestingVersioningViewSet
(
MyModelVersionnedViewSet
):
"""
S
ame as above
S
imple Viewset for testing purposes (versioning)
"""
permission_classes
=
get_viewset_permissions
(
"ForTestingVersioningViewSet"
)
...
...
backend/backend_app/models/abstract/my_model/myModel.py
View file @
4fe1bdf2
from
django.db
import
models
from
django.contrib.auth.models
import
User
from
django.contrib.contenttypes.fields
import
GenericRelation
from
.pendingModeration
import
PendingModeration
from
shared
import
OBJ_MODERATION_PERMISSIONS
from
shared
import
DEFAULT_OBJ_MODERATION_LV
from
django.core.validators
import
MinValueValidator
from
django.core.exceptions
import
ValidationError
from
django.core.validators
import
MinValueValidator
from
django.db
import
models
from
shared
import
DEFAULT_OBJ_MODERATION_LV
,
OBJ_MODERATION_PERMISSIONS
from
.pendingModeration
import
PendingModeration
oml
=
DEFAULT_OBJ_MODERATION_LV
POSSIBLE_OBJ_MODER_LV
=
[
OBJ_MODERATION_PERMISSIONS
[
key
]
for
key
in
OBJ_MODERATION_PERMISSIONS
]
...
...
@@ -21,23 +21,31 @@ def validate_obj_model_lv(value):
class
MyModel
(
models
.
Model
):
"""
All models in the app deppend of this one.
It contains the required attributes for managing
eventual
moderation
data
.
It contains the required attributes for managing
optionnal data
moderation.
All the logic behind moderation is done in myModelSerializer
"""
moderated_by
=
models
.
ForeignKey
(
# store the update author
updated_by
=
models
.
ForeignKey
(
User
,
null
=
True
,
on_delete
=
models
.
SET_NULL
,
related_name
=
"+"
)
moderated_on
=
models
.
DateTimeField
(
null
=
True
)
# store the update date (model can be updated without moderation)
updated_on
=
models
.
DateTimeField
(
null
=
True
)
updated_by
=
models
.
ForeignKey
(
# store the moderator
moderated_by
=
models
.
ForeignKey
(
User
,
null
=
True
,
on_delete
=
models
.
SET_NULL
,
related_name
=
"+"
)
# store the moderation date
moderated_on
=
models
.
DateTimeField
(
null
=
True
)
# Store the object moderation level by default
obj_moderation_level
=
models
.
SmallIntegerField
(
default
=
oml
,
validators
=
[
MinValueValidator
(
0
),
validate_obj_model_lv
]
default
=
DEFAULT_OBJ_MODERATION_LV
,
validators
=
[
MinValueValidator
(
0
),
validate_obj_model_lv
],
)
# Add the link to pending moderation
pending_moderation
=
GenericRelation
(
PendingModeration
)
class
Meta
:
...
...
Prev
1
2
3
4
5
6
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment