BO 1.9 tutorials, model and admin.py separeted, django 3.2
This commit is contained in:
parent
056e22c407
commit
a764cb8f21
@ -1,314 +0,0 @@
|
||||
from django.contrib import admin, messages
|
||||
from django.utils.html import format_html
|
||||
from django.utils.translation import ugettext_lazy as _, ngettext
|
||||
# from treenode.admin import TreeNodeModelAdmin
|
||||
# from treenode.forms import TreeNodeForm
|
||||
|
||||
from .models import ExerciseType, ExerciseTypeAlternative, ExerciseTypeParents
|
||||
from .models import Product
|
||||
from .models import Evaluation, EvaluationAttribute
|
||||
from .models import ExerciseDevice, ExerciseDeviceTranslation, ExerciseTypeDevice, ExerciseDeviceAlternative
|
||||
from .models import ExerciseTypeImage
|
||||
from .models import ExerciseTypeTranslation
|
||||
from .models import ExerciseTreeTranslation
|
||||
from .models import ExerciseTree
|
||||
from .models import ExerciseTreeParents
|
||||
from .models import ExercisePlanTranslation
|
||||
from .models import ExercisePlanTemplate, ExercisePlanTemplateTranslation, ExercisePlanTemplateDetail
|
||||
|
||||
'''
|
||||
ExerciseTree
|
||||
------------
|
||||
'''
|
||||
|
||||
|
||||
class TranslationTreeInline(admin.TabularInline):
|
||||
model = ExerciseTreeTranslation
|
||||
fields = ('language_code', 'name', 'description')
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseTreeParentsInline(admin.TabularInline):
|
||||
model = ExerciseTreeParents
|
||||
fk_name = 'exercise_tree_child'
|
||||
fields = ('exercise_tree_parent',)
|
||||
extra = 0
|
||||
|
||||
|
||||
'''
|
||||
|
||||
|
||||
class ExerciseTreeParentAdmin(TreeNodeModelAdmin):
|
||||
treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_ACCORDION
|
||||
list_display = ('name',)
|
||||
|
||||
# use TreeNodeForm to automatically exclude invalid parent choices
|
||||
form = TreeNodeForm
|
||||
'''
|
||||
|
||||
|
||||
class ExerciseTreeAdmin(admin.ModelAdmin):
|
||||
list_display = ('tree_id', 'name_colored', 'active')
|
||||
search_fields = ['name']
|
||||
|
||||
fields = ["name", 'description', "image_url", "active", "get_image_preview"]
|
||||
readonly_fields = ("get_image_preview",)
|
||||
|
||||
def get_image_preview(self, obj):
|
||||
image_url = '/media/' + str(obj.image_url)
|
||||
if obj.pk:
|
||||
return format_html('<img src="{url}" title="{url}" width="30%" height="30%"/> '
|
||||
.format(url=image_url))
|
||||
|
||||
get_image_preview.short_description = _("Image Preview")
|
||||
|
||||
def name_colored(self, obj):
|
||||
if obj.active:
|
||||
if obj.image_url != "":
|
||||
color_code = '7bc863'
|
||||
else:
|
||||
color_code = 'f2cdb3'
|
||||
else:
|
||||
color_code = 'C20000'
|
||||
html = '<span style="color: #{};">{}</span>˓→'.format(color_code, obj.name)
|
||||
return format_html(html)
|
||||
|
||||
name_colored.admin_order_field = 'name'
|
||||
name_colored.short_description = 'name'
|
||||
|
||||
inlines = [
|
||||
TranslationTreeInline,
|
||||
ExerciseTreeParentsInline
|
||||
]
|
||||
|
||||
|
||||
'''
|
||||
ExerciseTYPE
|
||||
------------
|
||||
'''
|
||||
|
||||
|
||||
class ExerciseTypeDeviceInline(admin.StackedInline):
|
||||
model = ExerciseTypeDevice
|
||||
extra = 0
|
||||
fields = ["exercise_type", "exercise_device"]
|
||||
|
||||
|
||||
class ImageInline(admin.StackedInline):
|
||||
model = ExerciseTypeImage
|
||||
extra = 0
|
||||
fields = ["name", "url", "type", "get_image_preview"]
|
||||
readonly_fields = ("get_image_preview",)
|
||||
|
||||
def get_image_preview(self, obj):
|
||||
image_url = '/media/' + str(obj.url)
|
||||
if obj.pk:
|
||||
return format_html('<img src="{url}" title="{url}" width="30%" height="30%"/> ' \
|
||||
.format(url=image_url))
|
||||
|
||||
get_image_preview.short_description = _("Image Preview")
|
||||
|
||||
|
||||
class TranslationInline(admin.TabularInline):
|
||||
model = ExerciseTypeTranslation
|
||||
fields = ('language_code', 'name', 'description')
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseTypeAlternativesInline(admin.TabularInline):
|
||||
model = ExerciseTypeAlternative
|
||||
fk_name = 'exercise_type_child'
|
||||
fields = ('exercise_type_parent',)
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseTypeParentsInline(admin.TabularInline):
|
||||
model = ExerciseTypeParents
|
||||
fields = ('exercise_tree',)
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseTypeAdmin(admin.ModelAdmin):
|
||||
list_display = ('exercise_type_id', 'name_colored', 'active', 'base')
|
||||
search_fields = ['name', 'exercisetypetranslation__name']
|
||||
fields = ('name', 'description', 'unit', 'unit_quantity', 'unit_quantity_unit', 'active', 'base')
|
||||
|
||||
def name_colored(self, obj):
|
||||
if obj.active:
|
||||
if obj.base:
|
||||
color_code = '7bc863'
|
||||
else:
|
||||
color_code = '4178bc'
|
||||
else:
|
||||
color_code = 'C20000'
|
||||
html = '<span style="color: #{};">{}</span>˓→'.format(color_code, obj.name)
|
||||
return format_html(html)
|
||||
|
||||
name_colored.admin_order_field = 'name'
|
||||
name_colored.short_description = 'name'
|
||||
|
||||
inlines = [
|
||||
ImageInline,
|
||||
TranslationInline,
|
||||
ExerciseTypeDeviceInline,
|
||||
ExerciseTypeAlternativesInline,
|
||||
ExerciseTypeParentsInline
|
||||
]
|
||||
exclude = ('exercise_tree',)
|
||||
|
||||
|
||||
'''
|
||||
ExercisePlan + Template
|
||||
------------
|
||||
'''
|
||||
|
||||
|
||||
class TranslationPlanTemplateInline(admin.TabularInline):
|
||||
model = ExercisePlanTemplateTranslation
|
||||
fields = ('language_code', 'name', 'description')
|
||||
extra = 0
|
||||
|
||||
|
||||
class TranslationPlanTemplateDetailInline(admin.TabularInline):
|
||||
model = ExercisePlanTemplateDetail
|
||||
verbose_name = 'name'
|
||||
fields = ('exercise_type','sort')
|
||||
extra = 0
|
||||
ordering = ('sort',)
|
||||
|
||||
|
||||
class ExercisePlanTemplateAdmin(admin.ModelAdmin):
|
||||
list_display = ('name_colored', 'template_type')
|
||||
search_fields = ['name']
|
||||
|
||||
def name_colored(self, obj):
|
||||
color_code = 'C20000'
|
||||
html = '<span style="color: #{};">{}</span>˓→'.format(color_code, obj.name)
|
||||
return format_html(html)
|
||||
|
||||
name_colored.admin_order_field = 'name'
|
||||
name_colored.short_description = 'name'
|
||||
|
||||
inlines = [
|
||||
TranslationPlanTemplateInline,
|
||||
TranslationPlanTemplateDetailInline
|
||||
]
|
||||
|
||||
|
||||
class ExercisePlanTemplateDetailAdmin(admin.ModelAdmin):
|
||||
list_display = ('get_plan', 'get_exercise_type', 'quantity', 'quantity_unit_quantity', 'rest_time',)
|
||||
list_editable = ('serie', 'quantity', 'quantity_unit_quantity', 'rest_time')
|
||||
|
||||
def get_plan(self, obj):
|
||||
return obj.exercise_plan_template.name
|
||||
|
||||
def get_exercise_type(self, obj):
|
||||
return obj.exercise_type.name
|
||||
|
||||
|
||||
class TranslationPlanInline(admin.TabularInline):
|
||||
model = ExercisePlanTranslation
|
||||
fields = ('language_code', 'name', 'description')
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExercisePlanAdmin(admin.ModelAdmin):
|
||||
list_display = ('name_colored',)
|
||||
search_fields = ['name']
|
||||
|
||||
def name_colored(self, obj):
|
||||
color_code = 'C20000'
|
||||
html = '<span style="color: #{};">{}</span>˓→'.format(color_code, obj.name)
|
||||
return format_html(html)
|
||||
|
||||
name_colored.admin_order_field = 'name'
|
||||
name_colored.short_description = 'name'
|
||||
|
||||
inlines = [
|
||||
TranslationPlanInline
|
||||
]
|
||||
|
||||
|
||||
'''
|
||||
class ExercisePlanDetailAdmin(admin.ModelAdmin):
|
||||
list_display = ('get_plan', 'get_exercise_type', 'serie', 'repeats', 'weight_equation',)
|
||||
list_editable = ('serie', 'repeats', 'weight_equation',)
|
||||
|
||||
# list_editable_link('',)
|
||||
|
||||
def get_plan(self, obj):
|
||||
return obj.exercise_plan.name
|
||||
|
||||
def get_exercise_type(self, obj):
|
||||
return obj.exercise_type.name
|
||||
'''
|
||||
|
||||
|
||||
class ProductAdmin(admin.ModelAdmin):
|
||||
list_display = ('product_id', 'name', 'type')
|
||||
|
||||
|
||||
class TranslationExerciseDeviceInline(admin.TabularInline):
|
||||
model = ExerciseDeviceTranslation
|
||||
fields = ('language_code', 'name')
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseDeviceAlternativesInline(admin.TabularInline):
|
||||
model = ExerciseDeviceAlternative
|
||||
fk_name = 'exercise_device_child'
|
||||
fields = ('exercise_device_parent',)
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseDeviceAdmin(admin.ModelAdmin):
|
||||
list_display = ('name',)
|
||||
fields = ('name', 'description', "image_url", "get_image_preview", "sort", "place")
|
||||
readonly_fields = ("get_image_preview",)
|
||||
|
||||
def get_image_preview(self, obj):
|
||||
image_url = '/media/' + str(obj.image_url)
|
||||
if obj.pk:
|
||||
return format_html('<img src="{url}" title="{url}" width="30%" height="30%"/> ' \
|
||||
.format(url=image_url))
|
||||
|
||||
get_image_preview.short_description = _("Image Preview")
|
||||
|
||||
inlines = [
|
||||
TranslationExerciseDeviceInline,
|
||||
ExerciseDeviceAlternativesInline
|
||||
]
|
||||
|
||||
|
||||
class EvaluationAdmin(admin.ModelAdmin):
|
||||
list_display = ('evaluation_id', 'name', 'get_exercise_type')
|
||||
|
||||
def get_exercise_type(self, obj):
|
||||
return obj.exercise_type.name
|
||||
|
||||
|
||||
class EvaluationAttributeAdmin(admin.ModelAdmin):
|
||||
list_display = (
|
||||
'evaluation_attr_id', 'name', 'sex', 'age_min', 'age_max', 'value_min', 'value_max', 'evaluation_text')
|
||||
list_editable = ('name', 'sex', 'age_min', 'age_max', 'value_min', 'value_max', 'evaluation_text')
|
||||
list_filter = ('evaluation',)
|
||||
|
||||
def copy_attributes(self, request, queryset):
|
||||
for objectAttr in reversed(queryset):
|
||||
objectAttr.pk = None
|
||||
objectAttr.name = objectAttr.name + "_copy"
|
||||
objectAttr.save()
|
||||
|
||||
copy_attributes.short_description = "Clone the selected attribute"
|
||||
|
||||
actions = [copy_attributes]
|
||||
|
||||
|
||||
admin.site.register(ExerciseType, ExerciseTypeAdmin)
|
||||
admin.site.register(ExerciseTree, ExerciseTreeAdmin)
|
||||
admin.site.register(ExercisePlanTemplate, ExercisePlanTemplateAdmin)
|
||||
admin.site.register(Product, ProductAdmin)
|
||||
admin.site.register(ExerciseDevice, ExerciseDeviceAdmin)
|
||||
admin.site.register(Evaluation, EvaluationAdmin)
|
||||
admin.site.register(EvaluationAttribute, EvaluationAttributeAdmin)
|
||||
admin.autodiscover()
|
10
aitrainer_backoffice/aitrainer_backoffice/admin/__init__.py
Normal file
10
aitrainer_backoffice/aitrainer_backoffice/admin/__init__.py
Normal file
@ -0,0 +1,10 @@
|
||||
# init
|
||||
from .exercise_type import ExerciseTypeAdmin
|
||||
from .exercisetree import ExerciseTreeAdmin
|
||||
from .exercise_plan_template import ExercisePlanTemplateAdmin, ExercisePlanTemplateDetailAdmin
|
||||
from .product import ProductAdmin
|
||||
from .exercise_device import ExerciseDeviceAdmin
|
||||
from .tutorial import TutorialAdmin
|
||||
from .evaluation import EvaluationAdmin, EvaluationAttributeAdmin
|
||||
from .exercise_plan import ExercisePlanAdmin
|
||||
|
@ -0,0 +1,32 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from ..models.evaluation import EvaluationAttribute, Evaluation
|
||||
|
||||
|
||||
class EvaluationAdmin(admin.ModelAdmin):
|
||||
list_display = ('evaluation_id', 'name', 'get_exercise_type')
|
||||
|
||||
def get_exercise_type(self, obj):
|
||||
return obj.exercise_type.name
|
||||
|
||||
|
||||
class EvaluationAttributeAdmin(admin.ModelAdmin):
|
||||
list_display = (
|
||||
'evaluation_attr_id', 'name', 'sex', 'age_min', 'age_max', 'value_min', 'value_max', 'evaluation_text')
|
||||
list_editable = ('name', 'sex', 'age_min', 'age_max', 'value_min', 'value_max', 'evaluation_text')
|
||||
list_filter = ('evaluation',)
|
||||
|
||||
def copy_attributes(self, request, queryset):
|
||||
for objectAttr in reversed(queryset):
|
||||
objectAttr.pk = None
|
||||
objectAttr.name = objectAttr.name + "_copy"
|
||||
objectAttr.save()
|
||||
|
||||
copy_attributes.short_description = "Clone the selected attribute"
|
||||
|
||||
actions = [copy_attributes]
|
||||
|
||||
|
||||
admin.site.register(Evaluation, EvaluationAdmin)
|
||||
admin.site.register(EvaluationAttribute, EvaluationAttributeAdmin)
|
||||
admin.autodiscover()
|
@ -0,0 +1,41 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.html import format_html
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..models.exercise_device import ExerciseDeviceTranslation, ExerciseDeviceAlternative, ExerciseDevice
|
||||
|
||||
|
||||
class TranslationExerciseDeviceInline(admin.TabularInline):
|
||||
model = ExerciseDeviceTranslation
|
||||
fields = ('language_code', 'name')
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseDeviceAlternativesInline(admin.TabularInline):
|
||||
model = ExerciseDeviceAlternative
|
||||
fk_name = 'exercise_device_child'
|
||||
fields = ('exercise_device_parent',)
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseDeviceAdmin(admin.ModelAdmin):
|
||||
list_display = ('name',)
|
||||
fields = ('name', 'description', "image_url", "get_image_preview", "sort", "place")
|
||||
readonly_fields = ("get_image_preview",)
|
||||
|
||||
def get_image_preview(self, obj):
|
||||
image_url = '/media/' + str(obj.image_url)
|
||||
if obj.pk:
|
||||
return format_html('<img src="{url}" title="{url}" width="30%" height="30%"/> ' \
|
||||
.format(url=image_url))
|
||||
|
||||
get_image_preview.short_description = _("Image Preview")
|
||||
|
||||
inlines = [
|
||||
TranslationExerciseDeviceInline,
|
||||
ExerciseDeviceAlternativesInline
|
||||
]
|
||||
|
||||
|
||||
admin.site.register(ExerciseDevice, ExerciseDeviceAdmin)
|
||||
admin.autodiscover()
|
@ -0,0 +1,42 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.html import format_html
|
||||
|
||||
from ..models.exercise_plan import ExercisePlanTranslation
|
||||
|
||||
|
||||
class TranslationPlanInline(admin.TabularInline):
|
||||
model = ExercisePlanTranslation
|
||||
fields = ('language_code', 'name', 'description')
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExercisePlanAdmin(admin.ModelAdmin):
|
||||
list_display = ('name_colored',)
|
||||
search_fields = ['name']
|
||||
|
||||
def name_colored(self, obj):
|
||||
color_code = 'C20000'
|
||||
html = '<span style="color: #{};">{}</span>˓→'.format(color_code, obj.name)
|
||||
return format_html(html)
|
||||
|
||||
name_colored.admin_order_field = 'name'
|
||||
name_colored.short_description = 'name'
|
||||
|
||||
inlines = [
|
||||
TranslationPlanInline
|
||||
]
|
||||
|
||||
|
||||
'''
|
||||
class ExercisePlanDetailAdmin(admin.ModelAdmin):
|
||||
list_display = ('get_plan', 'get_exercise_type', 'serie', 'repeats', 'weight_equation',)
|
||||
list_editable = ('serie', 'repeats', 'weight_equation',)
|
||||
|
||||
# list_editable_link('',)
|
||||
|
||||
def get_plan(self, obj):
|
||||
return obj.exercise_plan.name
|
||||
|
||||
def get_exercise_type(self, obj):
|
||||
return obj.exercise_type.name
|
||||
'''
|
@ -0,0 +1,51 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.html import format_html
|
||||
|
||||
from ..models.exercise_plan_template import ExercisePlanTemplateTranslation, ExercisePlanTemplateDetail, ExercisePlanTemplate
|
||||
|
||||
|
||||
class TranslationPlanTemplateInline(admin.TabularInline):
|
||||
model = ExercisePlanTemplateTranslation
|
||||
fields = ('language_code', 'name', 'description')
|
||||
extra = 0
|
||||
|
||||
|
||||
class TranslationPlanTemplateDetailInline(admin.TabularInline):
|
||||
model = ExercisePlanTemplateDetail
|
||||
verbose_name = 'name'
|
||||
fields = ('exercise_type','sort')
|
||||
extra = 0
|
||||
ordering = ('sort',)
|
||||
|
||||
|
||||
class ExercisePlanTemplateAdmin(admin.ModelAdmin):
|
||||
list_display = ('name_colored', 'template_type')
|
||||
search_fields = ['name']
|
||||
|
||||
def name_colored(self, obj):
|
||||
color_code = 'C20000'
|
||||
html = '<span style="color: #{};">{}</span>˓→'.format(color_code, obj.name)
|
||||
return format_html(html)
|
||||
|
||||
name_colored.admin_order_field = 'name'
|
||||
name_colored.short_description = 'name'
|
||||
|
||||
inlines = [
|
||||
TranslationPlanTemplateInline,
|
||||
TranslationPlanTemplateDetailInline
|
||||
]
|
||||
|
||||
|
||||
class ExercisePlanTemplateDetailAdmin(admin.ModelAdmin):
|
||||
list_display = ('get_plan', 'get_exercise_type', 'quantity', 'quantity_unit_quantity', 'rest_time',)
|
||||
list_editable = ('serie', 'quantity', 'quantity_unit_quantity', 'rest_time')
|
||||
|
||||
def get_plan(self, obj):
|
||||
return obj.exercise_plan_template.name
|
||||
|
||||
def get_exercise_type(self, obj):
|
||||
return obj.exercise_type.name
|
||||
|
||||
|
||||
admin.site.register(ExercisePlanTemplate, ExercisePlanTemplateAdmin)
|
||||
admin.autodiscover()
|
@ -0,0 +1,79 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.html import format_html
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..models.exercise_type import ExerciseType, ExerciseTypeImage, ExerciseTypeTranslation, ExerciseTypeAlternative, \
|
||||
ExerciseTypeParents, ExerciseTypeDevice
|
||||
|
||||
|
||||
class ExerciseTypeDeviceInline(admin.StackedInline):
|
||||
model = ExerciseTypeDevice
|
||||
extra = 0
|
||||
fields = ["exercise_type", "exercise_device"]
|
||||
|
||||
|
||||
class ImageInline(admin.StackedInline):
|
||||
model = ExerciseTypeImage
|
||||
extra = 0
|
||||
fields = ["name", "url", "type", "get_image_preview"]
|
||||
readonly_fields = ("get_image_preview",)
|
||||
|
||||
def get_image_preview(self, obj):
|
||||
image_url = '/media/' + str(obj.url)
|
||||
if obj.pk:
|
||||
return format_html('<img src="{url}" title="{url}" width="30%" height="30%"/> ' \
|
||||
.format(url=image_url))
|
||||
|
||||
get_image_preview.short_description = _("Image Preview")
|
||||
|
||||
|
||||
class TranslationInline(admin.TabularInline):
|
||||
model = ExerciseTypeTranslation
|
||||
fields = ('language_code', 'name', 'description')
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseTypeAlternativesInline(admin.TabularInline):
|
||||
model = ExerciseTypeAlternative
|
||||
fk_name = 'exercise_type_child'
|
||||
fields = ('exercise_type_parent',)
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseTypeParentsInline(admin.TabularInline):
|
||||
model = ExerciseTypeParents
|
||||
fields = ('exercise_tree',)
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseTypeAdmin(admin.ModelAdmin):
|
||||
list_display = ('exercise_type_id', 'name_colored', 'active', 'base')
|
||||
search_fields = ['name', 'exercisetypetranslation__name']
|
||||
fields = ('name', 'description', 'unit', 'unit_quantity', 'unit_quantity_unit', 'active', 'base')
|
||||
|
||||
def name_colored(self, obj):
|
||||
if obj.active:
|
||||
if obj.base:
|
||||
color_code = '7bc863'
|
||||
else:
|
||||
color_code = '4178bc'
|
||||
else:
|
||||
color_code = 'C20000'
|
||||
html = '<span style="color: #{};">{}</span>˓→'.format(color_code, obj.name)
|
||||
return format_html(html)
|
||||
|
||||
name_colored.admin_order_field = 'name'
|
||||
name_colored.short_description = 'name'
|
||||
|
||||
inlines = [
|
||||
ImageInline,
|
||||
TranslationInline,
|
||||
ExerciseTypeDeviceInline,
|
||||
ExerciseTypeAlternativesInline,
|
||||
ExerciseTypeParentsInline
|
||||
]
|
||||
exclude = ('exercise_tree',)
|
||||
|
||||
|
||||
admin.site.register(ExerciseType, ExerciseTypeAdmin)
|
||||
admin.autodiscover()
|
@ -0,0 +1,63 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.html import format_html
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..models.exercisetree import ExerciseTree, ExerciseTreeTranslation, \
|
||||
ExerciseTreeParents
|
||||
|
||||
'''
|
||||
ExerciseTree
|
||||
------------
|
||||
'''
|
||||
|
||||
|
||||
class TranslationTreeInline(admin.TabularInline):
|
||||
model = ExerciseTreeTranslation
|
||||
fields = ('language_code', 'name', 'description')
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseTreeParentsInline(admin.TabularInline):
|
||||
model = ExerciseTreeParents
|
||||
fk_name = 'exercise_tree_child'
|
||||
fields = ('exercise_tree_parent',)
|
||||
extra = 0
|
||||
|
||||
|
||||
class ExerciseTreeAdmin(admin.ModelAdmin):
|
||||
list_display = ('tree_id', 'name_colored', 'active')
|
||||
search_fields = ['name']
|
||||
|
||||
fields = ["name", 'description', "image_url", "active", "get_image_preview"]
|
||||
readonly_fields = ("get_image_preview",)
|
||||
|
||||
def get_image_preview(self, obj):
|
||||
image_url = '/media/' + str(obj.image_url)
|
||||
if obj.pk:
|
||||
return format_html('<img src="{url}" title="{url}" width="30%" height="30%"/> '
|
||||
.format(url=image_url))
|
||||
|
||||
get_image_preview.short_description = _("Image Preview")
|
||||
|
||||
def name_colored(self, obj):
|
||||
if obj.active:
|
||||
if obj.image_url != "":
|
||||
color_code = '7bc863'
|
||||
else:
|
||||
color_code = 'f2cdb3'
|
||||
else:
|
||||
color_code = 'C20000'
|
||||
html = '<span style="color: #{};">{}</span>˓→'.format(color_code, obj.name)
|
||||
return format_html(html)
|
||||
|
||||
name_colored.admin_order_field = 'name'
|
||||
name_colored.short_description = 'name'
|
||||
|
||||
inlines = [
|
||||
TranslationTreeInline,
|
||||
ExerciseTreeParentsInline
|
||||
]
|
||||
|
||||
|
||||
admin.site.register(ExerciseTree, ExerciseTreeAdmin)
|
||||
admin.autodiscover()
|
11
aitrainer_backoffice/aitrainer_backoffice/admin/product.py
Normal file
11
aitrainer_backoffice/aitrainer_backoffice/admin/product.py
Normal file
@ -0,0 +1,11 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from ..models.product import Product
|
||||
|
||||
|
||||
class ProductAdmin(admin.ModelAdmin):
|
||||
list_display = ('product_id', 'name', 'type')
|
||||
|
||||
|
||||
admin.site.register(Product, ProductAdmin)
|
||||
admin.autodiscover()
|
29
aitrainer_backoffice/aitrainer_backoffice/admin/tutorial.py
Normal file
29
aitrainer_backoffice/aitrainer_backoffice/admin/tutorial.py
Normal file
@ -0,0 +1,29 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from ..models.tutorial import TutorialTranslation, Tutorial, TutorialSteps
|
||||
|
||||
|
||||
class TranslationTutorialInline(admin.TabularInline):
|
||||
model = TutorialTranslation
|
||||
fields = ('language_code', 'tutorial_text', 'error_text')
|
||||
extra = 0
|
||||
|
||||
|
||||
class TutorialStepsAdmin(admin.ModelAdmin):
|
||||
list_display = ('tutorial', 'step',)
|
||||
list_filter = ('tutorial',)
|
||||
fields = ('tutorial', 'step', "tutorial_text", "error_text", "check_text",)
|
||||
|
||||
inlines = [
|
||||
TranslationTutorialInline,
|
||||
]
|
||||
|
||||
|
||||
class TutorialAdmin(admin.ModelAdmin):
|
||||
list_display = ('name',)
|
||||
fields = ('name',)
|
||||
|
||||
|
||||
admin.site.register(Tutorial, TutorialAdmin)
|
||||
admin.site.register(TutorialSteps, TutorialStepsAdmin)
|
||||
admin.autodiscover()
|
Binary file not shown.
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-04-03 14:27+0200\n"
|
||||
"POT-Creation-Date: 2021-04-24 11:26+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -18,219 +18,243 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: .\aitrainer_backoffice\admin.py:63 .\aitrainer_backoffice\admin.py:109
|
||||
#: .\aitrainer_backoffice\admin.py:275
|
||||
#: .\aitrainer_backoffice\admin\exercise_device.py:32
|
||||
#: .\aitrainer_backoffice\admin\exercise_type.py:27
|
||||
#: .\aitrainer_backoffice\admin\exercisetree.py:40
|
||||
msgid "Image Preview"
|
||||
msgstr "Kép előnézet"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:30 .\aitrainer_backoffice\models.py:211
|
||||
msgid "Exercise Device"
|
||||
msgstr "Edzés eszköz"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:31 .\aitrainer_backoffice\models.py:212
|
||||
msgid "Exercise Devices"
|
||||
msgstr "Edzés eszközök"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:46
|
||||
msgid "exercise_device_parent"
|
||||
msgstr "Gyakorlat Eszköz szülő"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:48
|
||||
msgid "exercise_device_child"
|
||||
msgstr "Gyakorlat eszköz"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:52
|
||||
msgid "Device Alternative"
|
||||
msgstr "Eszköz alternatíva"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:53
|
||||
msgid "Device Alternatives"
|
||||
msgstr "Eszköz alternatívák"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:65 .\aitrainer_backoffice\models.py:106
|
||||
#: .\aitrainer_backoffice\models.py:197 .\aitrainer_backoffice\models.py:271
|
||||
#: .\aitrainer_backoffice\models.py:317 .\aitrainer_backoffice\models.py:400
|
||||
msgid "Translation"
|
||||
msgstr "Fordítás"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:66 .\aitrainer_backoffice\models.py:107
|
||||
#: .\aitrainer_backoffice\models.py:198 .\aitrainer_backoffice\models.py:272
|
||||
#: .\aitrainer_backoffice\models.py:318 .\aitrainer_backoffice\models.py:401
|
||||
msgid "Translations"
|
||||
msgstr "Fordítások"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:89
|
||||
msgid "Exercise Tree"
|
||||
msgstr "Gyakorlat Menü"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:90
|
||||
msgid "Exercise Tree Items"
|
||||
msgstr "Gyakorlat Menü elemek"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:117
|
||||
msgid "exercise_tree_parent"
|
||||
msgstr "Gyakorlat Menü szülő"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:118
|
||||
msgid "Parent menu"
|
||||
msgstr "Szülő menüpont"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:123 .\aitrainer_backoffice\models.py:124
|
||||
msgid "Menu Tree Representation"
|
||||
msgstr ""
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:159
|
||||
msgid "Exercise"
|
||||
msgstr "Gyakorlat"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:160
|
||||
msgid "Exercises"
|
||||
msgstr "Gyakorlatok"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:181
|
||||
msgid "Image"
|
||||
msgstr "Kép"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:182
|
||||
msgid "Images"
|
||||
msgstr "Képek"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:218
|
||||
msgid "exercise_type_parent"
|
||||
msgstr "Gyakorlat szülő"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:220
|
||||
msgid "exercise_type_child"
|
||||
msgstr "Aktuális gyakorlat"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:224
|
||||
msgid "Exercise Alternative"
|
||||
msgstr "Gyakorlat alternatíva"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:225
|
||||
msgid "Exercise Alternatives"
|
||||
msgstr "Gyakorlat alternatívák"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:236
|
||||
msgid "Exercise Parent"
|
||||
msgstr "Gyakorlat szülő"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:237
|
||||
msgid "Exercise Parents"
|
||||
msgstr "Gyakorlat szülők"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:255
|
||||
msgid "Exercise Plan Template"
|
||||
msgstr "Edzésterv sablon"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:256
|
||||
msgid "Exercise Plan Templates"
|
||||
msgstr "Edzésterv sablonok"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:289
|
||||
msgid "Exercise Plan Template Detail"
|
||||
msgstr "Edzésterv sablon gyakorlat"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:290
|
||||
msgid "Exercise Plan Template Details"
|
||||
msgstr "Edzésterv sablon gyakorlatok"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:301
|
||||
msgid "Exercise Plan"
|
||||
msgstr "Edzésterv"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:302
|
||||
msgid "Exercise Plans"
|
||||
msgstr "Edzéstervek"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:334
|
||||
msgid "Exercise Plan Detail"
|
||||
msgstr "Edzésterv gyakorlat"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:335
|
||||
msgid "Exercise Plan Details"
|
||||
msgstr "Edzésterv gyakorlatok"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:357
|
||||
msgid "Product"
|
||||
msgstr "Termék"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:358
|
||||
msgid "Products"
|
||||
msgstr "Termékek"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:374
|
||||
msgid "Purchase"
|
||||
msgstr "Vásárlás"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:375
|
||||
msgid "Purchases"
|
||||
msgstr "Vásárlások"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:385
|
||||
msgid "Customer Property"
|
||||
msgstr "Ügyfél tulajdonság"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:386
|
||||
msgid "Customer Properties"
|
||||
msgstr "Ügyfél tulajdonságok"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:410
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:10
|
||||
msgid "exercise_type"
|
||||
msgstr "Aktuális gyakorlat"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:411
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:11
|
||||
msgid "unit"
|
||||
msgstr "Mértékegység"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:415
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:15
|
||||
msgid "Evaluation"
|
||||
msgstr "Kiértékelés"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:416
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:16
|
||||
msgid "Evaluations"
|
||||
msgstr "Kiértékelés Csoport"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:439
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:39
|
||||
msgid "evaluation_foreign"
|
||||
msgstr "Kiértékelés Főcsoport"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:440
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:40
|
||||
#: .\aitrainer_backoffice\models\tutorial.py:11
|
||||
msgid "name"
|
||||
msgstr "Név"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:441
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:41
|
||||
msgid "sex"
|
||||
msgstr "Nem"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:442
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:42
|
||||
msgid "age_min"
|
||||
msgstr "Kortól"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:443
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:43
|
||||
msgid "age_max"
|
||||
msgstr "Korig"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:444
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:44
|
||||
msgid "value_min"
|
||||
msgstr "Min érték"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:445
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:45
|
||||
msgid "value_max"
|
||||
msgstr "Max érték"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:447
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:47
|
||||
msgid "evaluation_text"
|
||||
msgstr "Osztályozás"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:449
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:49
|
||||
msgid "suggestion"
|
||||
msgstr "Javaslat"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:453
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:53
|
||||
msgid "Evaluation Table"
|
||||
msgstr "Kiértékelés tábla"
|
||||
|
||||
#: .\aitrainer_backoffice\models.py:454
|
||||
#: .\aitrainer_backoffice\models\evaluation.py:54
|
||||
msgid "Evaluation Tables"
|
||||
msgstr "Kiértékelés táblák"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_device.py:18
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:88
|
||||
msgid "Exercise Device"
|
||||
msgstr "Edzés eszköz"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_device.py:19
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:89
|
||||
msgid "Exercise Devices"
|
||||
msgstr "Edzés eszközök"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_device.py:40
|
||||
msgid "Device Alternative"
|
||||
msgstr "Eszköz alternatíva"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_device.py:41
|
||||
msgid "Device Alternatives"
|
||||
msgstr "Eszköz alternatívák"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_device.py:53
|
||||
#: .\aitrainer_backoffice\models\exercise_plan.py:32
|
||||
#: .\aitrainer_backoffice\models\exercise_plan_template.py:40
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:74
|
||||
#: .\aitrainer_backoffice\models\exercisetree.py:33
|
||||
#: .\aitrainer_backoffice\models\property.py:29
|
||||
#: .\aitrainer_backoffice\models\tutorial.py:45
|
||||
msgid "Translation"
|
||||
msgstr "Fordítás"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_device.py:54
|
||||
#: .\aitrainer_backoffice\models\exercise_plan.py:33
|
||||
#: .\aitrainer_backoffice\models\exercise_plan_template.py:41
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:75
|
||||
#: .\aitrainer_backoffice\models\exercisetree.py:34
|
||||
#: .\aitrainer_backoffice\models\property.py:30
|
||||
#: .\aitrainer_backoffice\models\tutorial.py:46
|
||||
msgid "Translations"
|
||||
msgstr "Fordítások"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_plan.py:16
|
||||
msgid "Exercise Plan"
|
||||
msgstr "Edzésterv"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_plan.py:17
|
||||
msgid "Exercise Plans"
|
||||
msgstr "Edzéstervek"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_plan.py:49
|
||||
msgid "Exercise Plan Detail"
|
||||
msgstr "Edzésterv gyakorlat"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_plan.py:50
|
||||
msgid "Exercise Plan Details"
|
||||
msgstr "Edzésterv gyakorlatok"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_plan_template.py:23
|
||||
msgid "Exercise Plan Template"
|
||||
msgstr "Edzésterv sablon"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_plan_template.py:24
|
||||
msgid "Exercise Plan Templates"
|
||||
msgstr "Edzésterv sablonok"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_plan_template.py:59
|
||||
msgid "Exercise Plan Template Detail"
|
||||
msgstr "Edzésterv sablon gyakorlat"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_plan_template.py:60
|
||||
msgid "Exercise Plan Template Details"
|
||||
msgstr "Edzésterv sablon gyakorlatok"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:35
|
||||
msgid "Exercise"
|
||||
msgstr "Gyakorlat"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:36
|
||||
msgid "Exercises"
|
||||
msgstr "Gyakorlatok"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:57
|
||||
msgid "Image"
|
||||
msgstr "Kép"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:58
|
||||
msgid "Images"
|
||||
msgstr "Képek"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:101
|
||||
msgid "Exercise Alternative"
|
||||
msgstr "Gyakorlat alternatíva"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:102
|
||||
msgid "Exercise Alternatives"
|
||||
msgstr "Gyakorlat alternatívák"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:113
|
||||
msgid "Exercise Parent"
|
||||
msgstr "Gyakorlat szülő"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercise_type.py:114
|
||||
msgid "Exercise Parents"
|
||||
msgstr "Gyakorlat szülők"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercisetree.py:16
|
||||
msgid "Exercise Tree"
|
||||
msgstr "Gyakorlat Menü"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercisetree.py:17
|
||||
msgid "Exercise Tree Items"
|
||||
msgstr "Gyakorlat Menü elemek"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercisetree.py:45
|
||||
msgid "Parent menu"
|
||||
msgstr "Szülő menüpont"
|
||||
|
||||
#: .\aitrainer_backoffice\models\exercisetree.py:50
|
||||
#: .\aitrainer_backoffice\models\exercisetree.py:51
|
||||
msgid "Menu Tree Representation"
|
||||
msgstr ""
|
||||
|
||||
#: .\aitrainer_backoffice\models\product.py:24
|
||||
msgid "Product"
|
||||
msgstr "Termék"
|
||||
|
||||
#: .\aitrainer_backoffice\models\product.py:25
|
||||
msgid "Products"
|
||||
msgstr "Termékek"
|
||||
|
||||
#: .\aitrainer_backoffice\models\product.py:41
|
||||
msgid "Purchase"
|
||||
msgstr "Vásárlás"
|
||||
|
||||
#: .\aitrainer_backoffice\models\product.py:42
|
||||
msgid "Purchases"
|
||||
msgstr "Vásárlások"
|
||||
|
||||
#: .\aitrainer_backoffice\models\property.py:14
|
||||
msgid "Customer Property"
|
||||
msgstr "Ügyfél tulajdonság"
|
||||
|
||||
#: .\aitrainer_backoffice\models\property.py:15
|
||||
msgid "Customer Properties"
|
||||
msgstr "Ügyfél tulajdonságok"
|
||||
|
||||
#: .\aitrainer_backoffice\models\tutorial.py:15
|
||||
msgid "Tutorial"
|
||||
msgstr "Tutorial"
|
||||
|
||||
#: .\aitrainer_backoffice\models\tutorial.py:16
|
||||
msgid "Tutorials"
|
||||
msgstr "Tutoriálok"
|
||||
|
||||
#: .\aitrainer_backoffice\models\tutorial.py:32
|
||||
msgid "Tutorial Step"
|
||||
msgstr "Tutorial lépés"
|
||||
|
||||
#: .\aitrainer_backoffice\models\tutorial.py:33
|
||||
msgid "Tutorial Steps"
|
||||
msgstr "Tutorial lépések"
|
||||
|
||||
#~ msgid "exercise_device_parent"
|
||||
#~ msgstr "Gyakorlat Eszköz szülő"
|
||||
|
||||
#~ msgid "exercise_device_child"
|
||||
#~ msgstr "Gyakorlat eszköz"
|
||||
|
||||
#~ msgid "exercise_tree_parent"
|
||||
#~ msgstr "Gyakorlat Menü szülő"
|
||||
|
||||
#~ msgid "exercise_type_parent"
|
||||
#~ msgstr "Gyakorlat szülő"
|
||||
|
||||
#~ msgid "exercise_type_child"
|
||||
#~ msgstr "Aktuális gyakorlat"
|
||||
|
@ -1,458 +0,0 @@
|
||||
from django.db import models
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
# from treenode.models import TreeNodeModel
|
||||
|
||||
|
||||
class LanguageTypes(models.TextChoices):
|
||||
EN = "en"
|
||||
HU = "hu"
|
||||
|
||||
|
||||
'''
|
||||
ExerciseDevice
|
||||
------------
|
||||
'''
|
||||
|
||||
|
||||
class ExerciseDevice(models.Model):
|
||||
exercise_device_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100)
|
||||
image_url = models.ImageField(upload_to='images/', help_text='The image size is 1366x768')
|
||||
description = models.TextField(max_length=1000, blank=True, null=True, help_text="English description here")
|
||||
sort = models.IntegerField(blank=True, null=True)
|
||||
place = models.BooleanField()
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_device'
|
||||
verbose_name = _("Exercise Device")
|
||||
verbose_name_plural = _("Exercise Devices")
|
||||
ordering = ['name']
|
||||
|
||||
def image_tag(self):
|
||||
return mark_safe('<img src="/media/%s" width="30%" height="30%" />' % self.image_url)
|
||||
|
||||
image_tag.short_description = 'Image'
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseDeviceAlternative(models.Model):
|
||||
exercise_device_alternative_id = models.AutoField(primary_key=True)
|
||||
exercise_device_parent = models.ForeignKey(ExerciseDevice, on_delete=models.CASCADE,
|
||||
related_name='exercise_device_parent')
|
||||
exercise_device_child = models.ForeignKey(ExerciseDevice, on_delete=models.CASCADE,
|
||||
related_name='exercise_device_child')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_device_alternative'
|
||||
verbose_name = _("Device Alternative")
|
||||
verbose_name_plural = _("Device Alternatives")
|
||||
unique_together = ['exercise_device_parent', 'exercise_device_child']
|
||||
|
||||
|
||||
class ExerciseDeviceTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
exercise_device = models.ForeignKey(ExerciseDevice, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=100)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_device_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
'''
|
||||
------------
|
||||
ExerciseTree
|
||||
------------
|
||||
'''
|
||||
|
||||
|
||||
class ExerciseTree(models.Model):
|
||||
tree_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
description = models.TextField(max_length=1000, blank=True, null=True, help_text='The description should be in '
|
||||
'English here')
|
||||
image_url = models.ImageField(upload_to='images/', help_text='The menu image size is 1366x768')
|
||||
active = models.BooleanField(default=0, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_tree'
|
||||
verbose_name = _("Exercise Tree")
|
||||
verbose_name_plural = _("Exercise Tree Items")
|
||||
ordering = ['name']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTreeTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
tree = models.ForeignKey(ExerciseTree, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
name = models.CharField(max_length=100)
|
||||
description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_tree_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTreeParents(models.Model):
|
||||
# treenode_display_field = 'name'
|
||||
exercise_tree_parents_id = models.AutoField(primary_key=True)
|
||||
exercise_tree_parent = models.ForeignKey(ExerciseTree, on_delete=models.CASCADE,
|
||||
related_name='exercise_tree_parent',
|
||||
help_text=_('Parent menu'), blank=True)
|
||||
exercise_tree_child = models.ForeignKey(ExerciseTree, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_tree_parents'
|
||||
verbose_name = _("Menu Tree Representation")
|
||||
verbose_name_plural = _("Menu Tree Representation")
|
||||
unique_together = [['exercise_tree_parent', 'exercise_tree_child']]
|
||||
|
||||
|
||||
'''
|
||||
ExerciseTYPE
|
||||
------------
|
||||
'''
|
||||
|
||||
|
||||
class ExerciseType(models.Model):
|
||||
class UnitTypes(models.TextChoices):
|
||||
REPEAT = 'repeat'
|
||||
SECOND = 'second'
|
||||
MINUTE = 'minute'
|
||||
METER = 'meter'
|
||||
CM = 'centimeter'
|
||||
PERCENT = 'percent'
|
||||
CALORIES = 'calories'
|
||||
KG = 'kilogram'
|
||||
|
||||
exercise_type_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
description = models.TextField(max_length=1000, blank=True, null=True, help_text='The description should be in '
|
||||
'English here')
|
||||
unit = models.CharField(choices=UnitTypes.choices, default=UnitTypes.REPEAT, max_length=50, blank=True, null=True)
|
||||
unit_quantity = models.BooleanField(default=0, blank=True, null=True)
|
||||
unit_quantity_unit = models.CharField(choices=UnitTypes.choices, default=UnitTypes.KG, max_length=50, blank=True,
|
||||
null=True)
|
||||
active = models.BooleanField(default=0, blank=True, null=True)
|
||||
base = models.BooleanField(default=0, blank=True, null=True)
|
||||
parents = models.ManyToManyField(ExerciseTree, through='ExerciseTypeParents', related_name='ExerciseTree')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type'
|
||||
verbose_name = _("Exercise")
|
||||
verbose_name_plural = _("Exercises")
|
||||
ordering = ['name']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTypeImage(models.Model):
|
||||
class ImageTypes(models.TextChoices):
|
||||
IMAGE = 'image'
|
||||
VIDEO = 'video'
|
||||
MENU = 'menu'
|
||||
|
||||
image_id = models.AutoField(primary_key=True)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=50, blank=True, null=True)
|
||||
type = models.CharField(choices=ImageTypes.choices, default=ImageTypes.IMAGE, max_length=50, blank=True, null=True)
|
||||
url = models.ImageField(upload_to='images/', help_text='The menu image size is 1366x768')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_image'
|
||||
verbose_name = _("Image")
|
||||
verbose_name_plural = _("Images")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTypeTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
name = models.CharField(max_length=100)
|
||||
description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTypeDevice(models.Model):
|
||||
exercise_type_device_id = models.AutoField(primary_key=True)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
exercise_device = models.ForeignKey(ExerciseDevice, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_device'
|
||||
verbose_name = _("Exercise Device")
|
||||
verbose_name_plural = _("Exercise Devices")
|
||||
|
||||
|
||||
class ExerciseTypeAlternative(models.Model):
|
||||
exercise_type_alternative_id = models.AutoField(primary_key=True)
|
||||
exercise_type_parent = models.ForeignKey(ExerciseType, on_delete=models.CASCADE,
|
||||
related_name='exercise_type_parent')
|
||||
exercise_type_child = models.ForeignKey(ExerciseType, on_delete=models.CASCADE,
|
||||
related_name='exercise_type_child')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_alternative'
|
||||
verbose_name = _("Exercise Alternative")
|
||||
verbose_name_plural = _("Exercise Alternatives")
|
||||
unique_together = [['exercise_type_parent', 'exercise_type_child']]
|
||||
|
||||
|
||||
class ExerciseTypeParents(models.Model):
|
||||
exercise_type_parents_id = models.AutoField(primary_key=True)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
exercise_tree = models.ForeignKey(ExerciseTree, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_parents'
|
||||
verbose_name = _("Exercise Parent")
|
||||
verbose_name_plural = _("Exercise Parents")
|
||||
unique_together = [['exercise_type', 'exercise_tree']]
|
||||
|
||||
|
||||
class TemplateTypes(models.TextChoices):
|
||||
MINI_SET = "mini_test_set"
|
||||
SPECIAL = "special"
|
||||
|
||||
|
||||
class ExercisePlanTemplate(models.Model):
|
||||
exercise_plan_template_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
description = models.TextField(max_length=1000, blank=True, null=True, help_text='The description should be in '
|
||||
'English here')
|
||||
template_type = models.CharField(max_length=20, choices=TemplateTypes.choices, default=TemplateTypes.SPECIAL)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_template'
|
||||
verbose_name = _("Exercise Plan Template")
|
||||
verbose_name_plural = _("Exercise Plan Templates")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExercisePlanTemplateTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
exercise_plan_template = models.ForeignKey(ExercisePlanTemplate, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
name = models.CharField(max_length=100)
|
||||
description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_template_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExercisePlanTemplateDetail(models.Model):
|
||||
exercise_plan_template_detail_id = models.AutoField(primary_key=True)
|
||||
exercise_plan_template = models.ForeignKey(ExercisePlanTemplate, on_delete=models.CASCADE)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
serie = models.IntegerField()
|
||||
quantity = models.FloatField()
|
||||
quantity_unit_quantity = models.FloatField()
|
||||
resting_time = models.TimeField()
|
||||
sort = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_template_detail'
|
||||
verbose_name = _("Exercise Plan Template Detail")
|
||||
verbose_name_plural = _("Exercise Plan Template Details")
|
||||
|
||||
|
||||
class ExercisePlan(models.Model):
|
||||
exercise_plan_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
description = models.TextField(max_length=1000, blank=True, null=True, help_text='The description should be in '
|
||||
'English here')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan'
|
||||
verbose_name = _("Exercise Plan")
|
||||
verbose_name_plural = _("Exercise Plans")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExercisePlanTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
exercise_plan = models.ForeignKey(ExercisePlan, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
name = models.CharField(max_length=100)
|
||||
description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExercisePlanDetail(models.Model):
|
||||
exercise_plan_detail_id = models.AutoField(primary_key=True)
|
||||
exercise_plan = models.ForeignKey(ExercisePlan, on_delete=models.CASCADE)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
serie = models.IntegerField()
|
||||
repeats = models.IntegerField()
|
||||
weight_equation = models.CharField(max_length=100)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_detail'
|
||||
verbose_name = _("Exercise Plan Detail")
|
||||
verbose_name_plural = _("Exercise Plan Details")
|
||||
|
||||
|
||||
class ProductTypes(models.TextChoices):
|
||||
SUBS = "subscription"
|
||||
IN_APP_CURR = "in-app-currency"
|
||||
|
||||
|
||||
class Product(models.Model):
|
||||
product_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=50)
|
||||
description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
type = models.CharField(max_length=15, choices=ProductTypes.choices, default=ProductTypes.SUBS)
|
||||
valid_from = models.DateField(blank=True, null=True)
|
||||
valid_to = models.DateField(blank=True, null=True)
|
||||
product_id_ios = models.CharField(max_length=50, blank=True, null=True)
|
||||
product_id_android = models.CharField(max_length=50, blank=True, null=True)
|
||||
price_ios = models.DecimalField(max_length=12, decimal_places=2, max_digits=12, blank=True)
|
||||
price_android = models.DecimalField(max_length=12, decimal_places=2, max_digits=12, blank=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'product'
|
||||
verbose_name = _("Product")
|
||||
verbose_name_plural = _("Products")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Purchase(models.Model):
|
||||
purchase_id = models.AutoField(primary_key=True)
|
||||
product = models.ForeignKey(Product, on_delete=models.CASCADE)
|
||||
customer_id = models.IntegerField()
|
||||
date_add = models.DateField(blank=True, null=True)
|
||||
purchase_sum = models.DecimalField(decimal_places=2, max_digits=7)
|
||||
currency = models.CharField(max_length=3)
|
||||
|
||||
class Meta:
|
||||
db_table = 'purchase'
|
||||
verbose_name = _("Purchase")
|
||||
verbose_name_plural = _("Purchases")
|
||||
|
||||
|
||||
class Property(models.Model):
|
||||
property_id = models.AutoField(primary_key=True)
|
||||
property_name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
property_unit = models.CharField(max_length=10)
|
||||
|
||||
class Meta:
|
||||
db_table = 'property'
|
||||
verbose_name = _("Customer Property")
|
||||
verbose_name_plural = _("Customer Properties")
|
||||
|
||||
def __str__(self):
|
||||
return self.property_name
|
||||
|
||||
|
||||
class PropertyTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
property = models.ForeignKey(Property, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
property_name = models.CharField(max_length=100)
|
||||
|
||||
class Meta:
|
||||
db_table = 'property_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.property_name
|
||||
|
||||
|
||||
class Evaluation(models.Model):
|
||||
evaluation_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE, verbose_name=_("exercise_type"))
|
||||
unit = models.CharField(max_length=50, verbose_name=_("unit"))
|
||||
|
||||
class Meta:
|
||||
db_table = 'evaluation'
|
||||
verbose_name = _("Evaluation")
|
||||
verbose_name_plural = _("Evaluations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class EvaluationAttribute(models.Model):
|
||||
class SexTypes(models.TextChoices):
|
||||
MAN = 'm'
|
||||
WOMAN = 'w'
|
||||
|
||||
class EvaluationTypes(models.TextChoices):
|
||||
ELITE = "elite"
|
||||
EXCELLENT = "excellent"
|
||||
GOOD = "good"
|
||||
ABOVE_AVERAGE = "above_average"
|
||||
AVERAGE = "average"
|
||||
BELOW_AVERAGE = "below_average"
|
||||
FAIR = "fair"
|
||||
POOR = "poor"
|
||||
VERY_POOR = "very_poor"
|
||||
|
||||
evaluation_attr_id = models.AutoField(primary_key=True)
|
||||
evaluation = models.ForeignKey(Evaluation, on_delete=models.CASCADE, verbose_name=_("evaluation_foreign"))
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here', verbose_name=_("name"))
|
||||
sex = models.CharField(max_length=1, choices=SexTypes.choices, default=SexTypes.MAN, verbose_name=_("sex"))
|
||||
age_min = models.IntegerField(verbose_name=_("age_min"))
|
||||
age_max = models.IntegerField(verbose_name=_("age_max"))
|
||||
value_min = models.FloatField(verbose_name=_("value_min"))
|
||||
value_max = models.FloatField(verbose_name=_("value_max"))
|
||||
evaluation_text = models.CharField(max_length=50, choices=EvaluationTypes.choices, default=EvaluationTypes.AVERAGE,
|
||||
verbose_name=_("evaluation_text"))
|
||||
suggestion = models.TextField(max_length=1000, blank=True, null=True, help_text="English suggestion here",
|
||||
verbose_name=_("suggestion"))
|
||||
|
||||
class Meta:
|
||||
db_table = 'evaluation_attribute'
|
||||
verbose_name = _("Evaluation Table")
|
||||
verbose_name_plural = _("Evaluation Tables")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
12
aitrainer_backoffice/aitrainer_backoffice/models/__init__.py
Normal file
12
aitrainer_backoffice/aitrainer_backoffice/models/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
from .exercisetree import ExerciseTree
|
||||
from .exercise_type import ExerciseType, ExerciseTypeAlternative, ExerciseTypeParents, ExerciseTypeDevice, \
|
||||
ExerciseTypeTranslation, ExerciseTypeImage
|
||||
from .exercise_device import ExerciseDevice, ExerciseDeviceAlternative, ExerciseDeviceTranslation
|
||||
from .exercise_plan import ExercisePlan, ExercisePlanDetail, ExercisePlanTranslation
|
||||
from .exercise_plan_template import ExercisePlanTemplate, ExercisePlanTemplateDetail, ExercisePlanTemplateTranslation
|
||||
from .exercise_type import ExerciseType, ExerciseTypeAlternative, ExerciseTypeParents, ExerciseTypeDevice, \
|
||||
ExerciseTypeTranslation, ExerciseTypeImage
|
||||
from .product import Product, Purchase
|
||||
from .property import Property, PropertyTranslation
|
||||
from .tutorial import Tutorial, TutorialSteps, TutorialTranslation
|
||||
from .evaluation import Evaluation, EvaluationAttribute
|
@ -0,0 +1,7 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class LanguageTypes(models.TextChoices):
|
||||
EN = "en"
|
||||
HU = "hu"
|
||||
|
@ -0,0 +1,57 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .exercise_type import ExerciseType
|
||||
|
||||
|
||||
class Evaluation(models.Model):
|
||||
evaluation_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE, verbose_name=_("exercise_type"))
|
||||
unit = models.CharField(max_length=50, verbose_name=_("unit"))
|
||||
|
||||
class Meta:
|
||||
db_table = 'evaluation'
|
||||
verbose_name = _("Evaluation")
|
||||
verbose_name_plural = _("Evaluations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class EvaluationAttribute(models.Model):
|
||||
class SexTypes(models.TextChoices):
|
||||
MAN = 'm'
|
||||
WOMAN = 'w'
|
||||
|
||||
class EvaluationTypes(models.TextChoices):
|
||||
ELITE = "elite"
|
||||
EXCELLENT = "excellent"
|
||||
GOOD = "good"
|
||||
ABOVE_AVERAGE = "above_average"
|
||||
AVERAGE = "average"
|
||||
BELOW_AVERAGE = "below_average"
|
||||
FAIR = "fair"
|
||||
POOR = "poor"
|
||||
VERY_POOR = "very_poor"
|
||||
|
||||
evaluation_attr_id = models.AutoField(primary_key=True)
|
||||
evaluation = models.ForeignKey(Evaluation, on_delete=models.CASCADE, verbose_name=_("evaluation_foreign"))
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here', verbose_name=_("name"))
|
||||
sex = models.CharField(max_length=1, choices=SexTypes.choices, default=SexTypes.MAN, verbose_name=_("sex"))
|
||||
age_min = models.IntegerField(verbose_name=_("age_min"))
|
||||
age_max = models.IntegerField(verbose_name=_("age_max"))
|
||||
value_min = models.FloatField(verbose_name=_("value_min"))
|
||||
value_max = models.FloatField(verbose_name=_("value_max"))
|
||||
evaluation_text = models.CharField(max_length=50, choices=EvaluationTypes.choices, default=EvaluationTypes.AVERAGE,
|
||||
verbose_name=_("evaluation_text"))
|
||||
suggestion = models.TextField(max_length=1000, blank=True, null=True, help_text="English suggestion here",
|
||||
verbose_name=_("suggestion"))
|
||||
|
||||
class Meta:
|
||||
db_table = 'evaluation_attribute'
|
||||
verbose_name = _("Evaluation Table")
|
||||
verbose_name_plural = _("Evaluation Tables")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
@ -0,0 +1,57 @@
|
||||
from django.db import models
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .enums import LanguageTypes
|
||||
|
||||
|
||||
class ExerciseDevice(models.Model):
|
||||
exercise_device_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100)
|
||||
image_url = models.ImageField(upload_to='images/', help_text='The image size is 1366x768')
|
||||
description = models.TextField(max_length=1000, blank=True, null=True, help_text="English description here")
|
||||
sort = models.IntegerField(blank=True, null=True)
|
||||
place = models.BooleanField()
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_device'
|
||||
verbose_name = _("Exercise Device")
|
||||
verbose_name_plural = _("Exercise Devices")
|
||||
ordering = ['name']
|
||||
|
||||
def image_tag(self):
|
||||
return mark_safe('<img src="/media/%s" width="30%" height="30%" />' % self.image_url)
|
||||
|
||||
image_tag.short_description = 'Image'
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseDeviceAlternative(models.Model):
|
||||
exercise_device_alternative_id = models.AutoField(primary_key=True)
|
||||
exercise_device_parent = models.ForeignKey(ExerciseDevice, on_delete=models.CASCADE,
|
||||
related_name='exercise_device_parent')
|
||||
exercise_device_child = models.ForeignKey(ExerciseDevice, on_delete=models.CASCADE,
|
||||
related_name='exercise_device_child')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_device_alternative'
|
||||
verbose_name = _("Device Alternative")
|
||||
verbose_name_plural = _("Device Alternatives")
|
||||
unique_together = ['exercise_device_parent', 'exercise_device_child']
|
||||
|
||||
|
||||
class ExerciseDeviceTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
exercise_device = models.ForeignKey(ExerciseDevice, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=100)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_device_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
@ -0,0 +1,50 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .enums import LanguageTypes
|
||||
from .exercise_type import ExerciseType
|
||||
|
||||
|
||||
class ExercisePlan(models.Model):
|
||||
exercise_plan_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
description = models.TextField(max_length=1000, blank=True, null=True, help_text='The description should be in '
|
||||
'English here')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan'
|
||||
verbose_name = _("Exercise Plan")
|
||||
verbose_name_plural = _("Exercise Plans")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExercisePlanTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
exercise_plan = models.ForeignKey(ExercisePlan, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
name = models.CharField(max_length=100)
|
||||
description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExercisePlanDetail(models.Model):
|
||||
exercise_plan_detail_id = models.AutoField(primary_key=True)
|
||||
exercise_plan = models.ForeignKey(ExercisePlan, on_delete=models.CASCADE)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
serie = models.IntegerField()
|
||||
repeats = models.IntegerField()
|
||||
weight_equation = models.CharField(max_length=100)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_detail'
|
||||
verbose_name = _("Exercise Plan Detail")
|
||||
verbose_name_plural = _("Exercise Plan Details")
|
@ -0,0 +1,60 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from froala_editor.fields import FroalaField
|
||||
|
||||
from .enums import LanguageTypes
|
||||
from .exercise_type import ExerciseType
|
||||
|
||||
|
||||
class TemplateTypes(models.TextChoices):
|
||||
MINI_SET = "mini_test_set"
|
||||
SPECIAL = "special"
|
||||
|
||||
|
||||
class ExercisePlanTemplate(models.Model):
|
||||
exercise_plan_template_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
#description = models.TextField(max_length=1000, blank=True, null=True, help_text='The description should be in English here')
|
||||
description = FroalaField()
|
||||
template_type = models.CharField(max_length=20, choices=TemplateTypes.choices, default=TemplateTypes.SPECIAL)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_template'
|
||||
verbose_name = _("Exercise Plan Template")
|
||||
verbose_name_plural = _("Exercise Plan Templates")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExercisePlanTemplateTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
exercise_plan_template = models.ForeignKey(ExercisePlanTemplate, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
name = models.CharField(max_length=100)
|
||||
#description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
description = FroalaField(blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_template_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExercisePlanTemplateDetail(models.Model):
|
||||
exercise_plan_template_detail_id = models.AutoField(primary_key=True)
|
||||
exercise_plan_template = models.ForeignKey(ExercisePlanTemplate, on_delete=models.CASCADE)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
serie = models.IntegerField()
|
||||
quantity = models.FloatField()
|
||||
quantity_unit_quantity = models.FloatField()
|
||||
resting_time = models.TimeField()
|
||||
sort = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_plan_template_detail'
|
||||
verbose_name = _("Exercise Plan Template Detail")
|
||||
verbose_name_plural = _("Exercise Plan Template Details")
|
@ -0,0 +1,115 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from froala_editor.fields import FroalaField
|
||||
|
||||
from .enums import LanguageTypes
|
||||
from .exercise_device import ExerciseDevice
|
||||
from .exercisetree import ExerciseTree
|
||||
|
||||
|
||||
class ExerciseType(models.Model):
|
||||
class UnitTypes(models.TextChoices):
|
||||
REPEAT = 'repeat'
|
||||
SECOND = 'second'
|
||||
MINUTE = 'minute'
|
||||
METER = 'meter'
|
||||
CM = 'centimeter'
|
||||
PERCENT = 'percent'
|
||||
CALORIES = 'calories'
|
||||
KG = 'kilogram'
|
||||
|
||||
exercise_type_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
#description = models.TextField(max_length=1000, blank=True, null=True, help_text='The description should be in English here')
|
||||
description = FroalaField()
|
||||
unit = models.CharField(choices=UnitTypes.choices, default=UnitTypes.REPEAT, max_length=50, blank=True, null=True)
|
||||
unit_quantity = models.BooleanField(default=0, blank=True, null=True)
|
||||
unit_quantity_unit = models.CharField(choices=UnitTypes.choices, default=UnitTypes.KG, max_length=50, blank=True,
|
||||
null=True)
|
||||
active = models.BooleanField(default=0, blank=True, null=True)
|
||||
base = models.BooleanField(default=0, blank=True, null=True)
|
||||
parents = models.ManyToManyField(ExerciseTree, through='ExerciseTypeParents', related_name='ExerciseTree')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type'
|
||||
verbose_name = _("Exercise")
|
||||
verbose_name_plural = _("Exercises")
|
||||
ordering = ['name']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTypeImage(models.Model):
|
||||
class ImageTypes(models.TextChoices):
|
||||
IMAGE = 'image'
|
||||
VIDEO = 'video'
|
||||
MENU = 'menu'
|
||||
|
||||
image_id = models.AutoField(primary_key=True)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=50, blank=True, null=True)
|
||||
type = models.CharField(choices=ImageTypes.choices, default=ImageTypes.IMAGE, max_length=50, blank=True, null=True)
|
||||
url = models.ImageField(upload_to='images/', help_text='The menu image size is 1366x768')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_image'
|
||||
verbose_name = _("Image")
|
||||
verbose_name_plural = _("Images")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTypeTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
name = models.CharField(max_length=100)
|
||||
#description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
description = FroalaField(blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTypeDevice(models.Model):
|
||||
exercise_type_device_id = models.AutoField(primary_key=True)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
exercise_device = models.ForeignKey(ExerciseDevice, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_device'
|
||||
verbose_name = _("Exercise Device")
|
||||
verbose_name_plural = _("Exercise Devices")
|
||||
|
||||
|
||||
class ExerciseTypeAlternative(models.Model):
|
||||
exercise_type_alternative_id = models.AutoField(primary_key=True)
|
||||
exercise_type_parent = models.ForeignKey(ExerciseType, on_delete=models.CASCADE,
|
||||
related_name='exercise_type_parent')
|
||||
exercise_type_child = models.ForeignKey(ExerciseType, on_delete=models.CASCADE,
|
||||
related_name='exercise_type_child')
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_alternative'
|
||||
verbose_name = _("Exercise Alternative")
|
||||
verbose_name_plural = _("Exercise Alternatives")
|
||||
unique_together = [['exercise_type_parent', 'exercise_type_child']]
|
||||
|
||||
|
||||
class ExerciseTypeParents(models.Model):
|
||||
exercise_type_parents_id = models.AutoField(primary_key=True)
|
||||
exercise_type = models.ForeignKey(ExerciseType, on_delete=models.CASCADE)
|
||||
exercise_tree = models.ForeignKey(ExerciseTree, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_type_parents'
|
||||
verbose_name = _("Exercise Parent")
|
||||
verbose_name_plural = _("Exercise Parents")
|
||||
unique_together = [['exercise_type', 'exercise_tree']]
|
@ -0,0 +1,53 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from .enums import LanguageTypes
|
||||
|
||||
|
||||
class ExerciseTree(models.Model):
|
||||
tree_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
description = models.TextField(max_length=1000, blank=True, null=True, help_text='The description should be in '
|
||||
'English here')
|
||||
image_url = models.ImageField(upload_to='images/', help_text='The menu image size is 1366x768')
|
||||
active = models.BooleanField(default=0, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_tree'
|
||||
verbose_name = _("Exercise Tree")
|
||||
verbose_name_plural = _("Exercise Tree Items")
|
||||
ordering = ['name']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTreeTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
tree = models.ForeignKey(ExerciseTree, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
name = models.CharField(max_length=100)
|
||||
description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_tree_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ExerciseTreeParents(models.Model):
|
||||
# treenode_display_field = 'name'
|
||||
exercise_tree_parents_id = models.AutoField(primary_key=True)
|
||||
exercise_tree_parent = models.ForeignKey(ExerciseTree, on_delete=models.CASCADE,
|
||||
related_name='exercise_tree_parent',
|
||||
help_text=_('Parent menu'), blank=True)
|
||||
exercise_tree_child = models.ForeignKey(ExerciseTree, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
db_table = 'exercise_tree_parents'
|
||||
verbose_name = _("Menu Tree Representation")
|
||||
verbose_name_plural = _("Menu Tree Representation")
|
||||
unique_together = [['exercise_tree_parent', 'exercise_tree_child']]
|
||||
app_label = 'aitrainer_backoffice.aitrainer_backoffice'
|
42
aitrainer_backoffice/aitrainer_backoffice/models/product.py
Normal file
42
aitrainer_backoffice/aitrainer_backoffice/models/product.py
Normal file
@ -0,0 +1,42 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class ProductTypes(models.TextChoices):
|
||||
SUBS = "subscription"
|
||||
IN_APP_CURR = "in-app-currency"
|
||||
|
||||
|
||||
class Product(models.Model):
|
||||
product_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=50)
|
||||
description = models.TextField(max_length=1000, blank=True, null=True)
|
||||
type = models.CharField(max_length=15, choices=ProductTypes.choices, default=ProductTypes.SUBS)
|
||||
valid_from = models.DateField(blank=True, null=True)
|
||||
valid_to = models.DateField(blank=True, null=True)
|
||||
product_id_ios = models.CharField(max_length=50, blank=True, null=True)
|
||||
product_id_android = models.CharField(max_length=50, blank=True, null=True)
|
||||
price_ios = models.DecimalField(max_length=12, decimal_places=2, max_digits=12, blank=True)
|
||||
price_android = models.DecimalField(max_length=12, decimal_places=2, max_digits=12, blank=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'product'
|
||||
verbose_name = _("Product")
|
||||
verbose_name_plural = _("Products")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Purchase(models.Model):
|
||||
purchase_id = models.AutoField(primary_key=True)
|
||||
product = models.ForeignKey(Product, on_delete=models.CASCADE)
|
||||
customer_id = models.IntegerField()
|
||||
date_add = models.DateField(blank=True, null=True)
|
||||
purchase_sum = models.DecimalField(decimal_places=2, max_digits=7)
|
||||
currency = models.CharField(max_length=3)
|
||||
|
||||
class Meta:
|
||||
db_table = 'purchase'
|
||||
verbose_name = _("Purchase")
|
||||
verbose_name_plural = _("Purchases")
|
33
aitrainer_backoffice/aitrainer_backoffice/models/property.py
Normal file
33
aitrainer_backoffice/aitrainer_backoffice/models/property.py
Normal file
@ -0,0 +1,33 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .enums import LanguageTypes
|
||||
|
||||
|
||||
class Property(models.Model):
|
||||
property_id = models.AutoField(primary_key=True)
|
||||
property_name = models.CharField(max_length=100, help_text='The name should be in English here')
|
||||
property_unit = models.CharField(max_length=10)
|
||||
|
||||
class Meta:
|
||||
db_table = 'property'
|
||||
verbose_name = _("Customer Property")
|
||||
verbose_name_plural = _("Customer Properties")
|
||||
|
||||
def __str__(self):
|
||||
return self.property_name
|
||||
|
||||
|
||||
class PropertyTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
property = models.ForeignKey(Property, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
property_name = models.CharField(max_length=100)
|
||||
|
||||
class Meta:
|
||||
db_table = 'property_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.property_name
|
49
aitrainer_backoffice/aitrainer_backoffice/models/tutorial.py
Normal file
49
aitrainer_backoffice/aitrainer_backoffice/models/tutorial.py
Normal file
@ -0,0 +1,49 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from froala_editor.fields import FroalaField
|
||||
|
||||
from .enums import LanguageTypes
|
||||
|
||||
|
||||
class Tutorial(models.Model):
|
||||
tutorial_id = models.AutoField(primary_key=True)
|
||||
name = models.CharField(max_length=100, help_text='The name should be in English here',
|
||||
verbose_name=_("name"))
|
||||
|
||||
class Meta:
|
||||
db_table = 'tutorial'
|
||||
verbose_name = _("Tutorial")
|
||||
verbose_name_plural = _("Tutorials")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class TutorialSteps(models.Model):
|
||||
tutorial_step_id = models.AutoField(primary_key=True)
|
||||
tutorial = models.ForeignKey(Tutorial, on_delete=models.CASCADE)
|
||||
step = models.IntegerField(help_text="Tutorial Step")
|
||||
tutorial_text = FroalaField()
|
||||
error_text = FroalaField(blank=True, null=True)
|
||||
check_text = models.TextField(max_length=50, blank=True, null=True, help_text="Only for programmers!")
|
||||
|
||||
class Meta:
|
||||
db_table = 'tutorial_steps'
|
||||
verbose_name = _("Tutorial Step")
|
||||
verbose_name_plural = _("Tutorial Steps")
|
||||
|
||||
|
||||
class TutorialTranslation(models.Model):
|
||||
translation_id = models.AutoField(primary_key=True)
|
||||
tutorial_step = models.ForeignKey(TutorialSteps, on_delete=models.CASCADE)
|
||||
language_code = models.CharField(max_length=2, choices=LanguageTypes.choices, default=LanguageTypes.HU)
|
||||
tutorial_text = FroalaField()
|
||||
error_text = FroalaField(blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'tutorial_translation'
|
||||
verbose_name = _("Translation")
|
||||
verbose_name_plural = _("Translations")
|
||||
|
||||
def __str__(self):
|
||||
return self.tutorial_text
|
@ -12,7 +12,7 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
|
||||
|
||||
import os
|
||||
|
||||
BACKOFFICE_VERSION = 1.7
|
||||
BACKOFFICE_VERSION = 1.9
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
@ -44,6 +44,7 @@ INSTALLED_APPS = [
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'froala_editor'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@ -126,6 +127,7 @@ USE_TZ = True
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, "static")
|
||||
STATIC_JS_DIR = os.path.join(STATIC_URL, "js")
|
||||
|
||||
MEDIA_URL = '/media/'
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
|
@ -40,6 +40,7 @@ INSTALLED_APPS = [
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'tinymce'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
@ -16,13 +16,15 @@ Including another URLconf
|
||||
path('admin/', admin.site.urls),
|
||||
"""
|
||||
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.conf import settings #
|
||||
from django.conf.urls.static import static # n
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from froala_editor import views
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('froala_editor/',include('froala_editor.urls'))
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
|
@ -1,5 +1,6 @@
|
||||
django==3.1.7
|
||||
asgiref==3.2.10
|
||||
django==3.2
|
||||
django-froala-editor=3.2.6-1
|
||||
asgiref==3.3.4
|
||||
certifi==2020.6.20
|
||||
chardet==3.0.4
|
||||
idna==2.10
|
||||
|
Loading…
Reference in New Issue
Block a user