mirror of
https://github.com/wger-project/wger.git
synced 2026-02-18 00:17:51 +01:00
Rename exercisebase model to exercise
This commit is contained in:
@@ -64,13 +64,13 @@ filter_dump(('exercises.exercisecategory',), 'categories.json')
|
||||
filter_dump(('exercises.exerciseimage',), 'exercise-images.json')
|
||||
filter_dump(
|
||||
(
|
||||
'exercises.exercisebase',
|
||||
'exercises.exercise',
|
||||
'exercises.variation',
|
||||
),
|
||||
'exercise-base-data.json',
|
||||
)
|
||||
filter_dump(
|
||||
('exercises.exercise', 'exercises.exercisecomment', 'exercises.alias'), 'translations.json'
|
||||
('exercises.translation', 'exercises.exercisecomment', 'exercises.alias'), 'translations.json'
|
||||
)
|
||||
filter_dump(
|
||||
(
|
||||
|
||||
@@ -108,6 +108,21 @@
|
||||
"exercises",
|
||||
"translation"
|
||||
],
|
||||
[
|
||||
"add_exercise",
|
||||
"exercises",
|
||||
"exercise"
|
||||
],
|
||||
[
|
||||
"change_exercise",
|
||||
"exercises",
|
||||
"exercise"
|
||||
],
|
||||
[
|
||||
"delete_exercise",
|
||||
"exercises",
|
||||
"exercise"
|
||||
],
|
||||
[
|
||||
"add_exercisecategory",
|
||||
"exercises",
|
||||
@@ -497,6 +512,21 @@
|
||||
"exercises",
|
||||
"translation"
|
||||
],
|
||||
[
|
||||
"add_exercise",
|
||||
"exercises",
|
||||
"exercise"
|
||||
],
|
||||
[
|
||||
"change_exercise",
|
||||
"exercises",
|
||||
"exercise"
|
||||
],
|
||||
[
|
||||
"delete_exercise",
|
||||
"exercises",
|
||||
"exercise"
|
||||
],
|
||||
[
|
||||
"add_exercisecategory",
|
||||
"exercises",
|
||||
|
||||
@@ -24,13 +24,13 @@ from wger.exercises.models import (
|
||||
Alias,
|
||||
DeletionLog,
|
||||
Equipment,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
ExerciseCategory,
|
||||
ExerciseComment,
|
||||
ExerciseImage,
|
||||
ExerciseVideo,
|
||||
Muscle,
|
||||
Translation,
|
||||
Variation,
|
||||
)
|
||||
from wger.utils.cache import CacheKeyMapper
|
||||
@@ -42,7 +42,7 @@ class ExerciseBaseSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = ExerciseBase
|
||||
model = Exercise
|
||||
fields = [
|
||||
'id',
|
||||
'uuid',
|
||||
@@ -307,7 +307,7 @@ class ExerciseTranslationBaseInfoSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False, read_only=True)
|
||||
uuid = serializers.UUIDField(required=False, read_only=True)
|
||||
exercise_base = serializers.PrimaryKeyRelatedField(
|
||||
queryset=ExerciseBase.objects.all(),
|
||||
queryset=Exercise.objects.all(),
|
||||
required=True,
|
||||
)
|
||||
aliases = ExerciseInfoAliasSerializer(source='alias_set', many=True, read_only=True)
|
||||
@@ -344,7 +344,7 @@ class ExerciseTranslationSerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(required=False, read_only=True)
|
||||
uuid = serializers.UUIDField(required=False, read_only=True)
|
||||
exercise_base = serializers.PrimaryKeyRelatedField(
|
||||
queryset=ExerciseBase.objects.all(),
|
||||
queryset=Exercise.objects.all(),
|
||||
required=True,
|
||||
)
|
||||
|
||||
@@ -369,7 +369,7 @@ class ExerciseTranslationSerializer(serializers.ModelSerializer):
|
||||
# Editing an existing object
|
||||
# -> Check if the language already exists, excluding the current object
|
||||
if self.instance:
|
||||
if self.instance.exercise_base.exercises.filter(
|
||||
if self.instance.exercise_base.translations.filter(
|
||||
~Q(id=self.instance.pk),
|
||||
language=value['language'],
|
||||
).exists():
|
||||
@@ -450,7 +450,7 @@ class ExerciseBaseInfoSerializer(serializers.ModelSerializer):
|
||||
last_update_global = serializers.DateTimeField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = ExerciseBase
|
||||
model = Exercise
|
||||
depth = 1
|
||||
fields = [
|
||||
'id',
|
||||
|
||||
@@ -71,13 +71,13 @@ from wger.exercises.models import (
|
||||
Alias,
|
||||
DeletionLog,
|
||||
Equipment,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
ExerciseCategory,
|
||||
ExerciseComment,
|
||||
ExerciseImage,
|
||||
ExerciseVideo,
|
||||
Muscle,
|
||||
Translation,
|
||||
Variation,
|
||||
)
|
||||
from wger.exercises.views.helper import StreamVerbs
|
||||
@@ -101,7 +101,7 @@ class ExerciseBaseViewSet(ModelViewSet):
|
||||
For a read-only endpoint with all the information of an exercise, see /api/v2/exercisebaseinfo/
|
||||
"""
|
||||
|
||||
queryset = ExerciseBase.translations.all()
|
||||
queryset = Exercise.with_translations.all()
|
||||
serializer_class = ExerciseBaseSerializer
|
||||
permission_classes = (CanContributeExercises,)
|
||||
ordering_fields = '__all__'
|
||||
@@ -134,7 +134,7 @@ class ExerciseBaseViewSet(ModelViewSet):
|
||||
action_object=serializer.instance,
|
||||
)
|
||||
|
||||
def perform_destroy(self, instance: ExerciseBase):
|
||||
def perform_destroy(self, instance: Exercise):
|
||||
"""Manually delete the exercise and set the replacement, if any"""
|
||||
|
||||
uuid = self.request.query_params.get('replaced_by', '')
|
||||
@@ -430,7 +430,7 @@ class ExerciseBaseInfoViewset(viewsets.ReadOnlyModelViewSet):
|
||||
is the recommended way to access the exercise data.
|
||||
"""
|
||||
|
||||
queryset = ExerciseBase.objects.all()
|
||||
queryset = Exercise.objects.all()
|
||||
serializer_class = ExerciseBaseInfoSerializer
|
||||
ordering_fields = '__all__'
|
||||
filterset_fields = (
|
||||
|
||||
@@ -27,7 +27,7 @@ class ExerciseConfig(AppConfig):
|
||||
|
||||
registry.register(self.get_model('Alias'))
|
||||
registry.register(self.get_model('Translation'))
|
||||
registry.register(self.get_model('ExerciseBase'))
|
||||
registry.register(self.get_model('Exercise'))
|
||||
registry.register(self.get_model('ExerciseComment'))
|
||||
registry.register(self.get_model('ExerciseImage'))
|
||||
registry.register(self.get_model('ExerciseVideo'))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "exercises.exercisebase",
|
||||
"model": "exercises.exercise",
|
||||
"fields": {
|
||||
"uuid": "acad3949-36fb-4481-9a72-be2ddae2bc05",
|
||||
"category": 2,
|
||||
@@ -43,7 +43,7 @@
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "exercises.exercisebase",
|
||||
"model": "exercises.exercise",
|
||||
"fields": {
|
||||
"uuid": "ae3328ba-9a35-4731-bc23-5da50720c5aa",
|
||||
"category": 2,
|
||||
@@ -61,7 +61,7 @@
|
||||
},
|
||||
{
|
||||
"pk": 3,
|
||||
"model": "exercises.exercisebase",
|
||||
"model": "exercises.exercise",
|
||||
"fields": {
|
||||
"uuid": "c2dc11e9-b14a-49cb-9d11-d1b9441f16f4",
|
||||
"category": 3,
|
||||
@@ -75,7 +75,7 @@
|
||||
},
|
||||
{
|
||||
"pk": 4,
|
||||
"model": "exercises.exercisebase",
|
||||
"model": "exercises.exercise",
|
||||
"fields": {
|
||||
"uuid": "a2f5b6ef-b780-49c0-8d96-fdaff23e27ce",
|
||||
"category": 3,
|
||||
@@ -90,7 +90,7 @@
|
||||
},
|
||||
{
|
||||
"pk": 5,
|
||||
"model": "exercises.exercisebase",
|
||||
"model": "exercises.exercise",
|
||||
"fields": {
|
||||
"uuid": "1ae6a28d-10e7-4ecf-af4f-905f8193e2c6",
|
||||
"category": 1,
|
||||
@@ -102,7 +102,7 @@
|
||||
},
|
||||
{
|
||||
"pk": 6,
|
||||
"model": "exercises.exercisebase",
|
||||
"model": "exercises.exercise",
|
||||
"fields": {
|
||||
"uuid": "95a7e546-e8f8-4521-a76b-983d94161b25",
|
||||
"category": 1,
|
||||
@@ -114,7 +114,7 @@
|
||||
},
|
||||
{
|
||||
"pk": 7,
|
||||
"model": "exercises.exercisebase",
|
||||
"model": "exercises.exercise",
|
||||
"fields": {
|
||||
"uuid": "b186f1f8-4957-44dc-bf30-d0b00064ce6f",
|
||||
"category": 1,
|
||||
@@ -126,7 +126,7 @@
|
||||
},
|
||||
{
|
||||
"pk": 8,
|
||||
"model": "exercises.exercisebase",
|
||||
"model": "exercises.exercise",
|
||||
"fields": {
|
||||
"uuid": "c2078aac-e4e2-4103-a845-6252a3eb795e",
|
||||
"category": 1,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -16,8 +16,10 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
# wger
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Translation
|
||||
from wger.exercises.models import (
|
||||
Exercise,
|
||||
Translation,
|
||||
)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
@@ -61,8 +63,8 @@ class Command(BaseCommand):
|
||||
|
||||
if exercise_base_id is not None:
|
||||
try:
|
||||
exercise_base = ExerciseBase.objects.get(id=exercise_base_id)
|
||||
except ExerciseBase.DoesNotExist:
|
||||
exercise_base = Exercise.objects.get(id=exercise_base_id)
|
||||
except Exercise.DoesNotExist:
|
||||
self.print_error('Failed to find exercise base')
|
||||
return
|
||||
exercise_base.license_author = author_name
|
||||
@@ -71,7 +73,7 @@ class Command(BaseCommand):
|
||||
if exercise_id is not None:
|
||||
try:
|
||||
exercise = Translation.objects.get(id=exercise_id)
|
||||
except ExerciseBase.DoesNotExist:
|
||||
except Exercise.DoesNotExist:
|
||||
self.print_error('Failed to find exercise')
|
||||
return
|
||||
exercise.license_author = author_name
|
||||
|
||||
@@ -21,8 +21,8 @@ from django.core.management.base import BaseCommand
|
||||
# wger
|
||||
from wger.core.models import Language
|
||||
from wger.exercises.models import (
|
||||
Exercise,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
)
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class Command(BaseCommand):
|
||||
out = []
|
||||
|
||||
languages = Language.objects.all()
|
||||
for base in ExerciseBase.objects.all():
|
||||
for base in Exercise.objects.all():
|
||||
data = {
|
||||
'base': {
|
||||
'uuid': base.uuid,
|
||||
|
||||
@@ -21,7 +21,7 @@ from django.core.management.base import BaseCommand
|
||||
|
||||
# wger
|
||||
from wger.core.models import Language
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.utils.constants import ENGLISH_SHORT_NAME
|
||||
|
||||
|
||||
@@ -88,16 +88,16 @@ class Command(BaseCommand):
|
||||
|
||||
self.english = Language.objects.get(short_name=ENGLISH_SHORT_NAME)
|
||||
|
||||
for base in ExerciseBase.objects.all():
|
||||
for base in Exercise.objects.all():
|
||||
self.handle_untranslated(base, delete_untranslated)
|
||||
self.handle_no_english(base, delete_no_english)
|
||||
self.handle_duplicate_translations(base, delete_duplicates)
|
||||
|
||||
def handle_untranslated(self, base: ExerciseBase, delete: bool):
|
||||
def handle_untranslated(self, base: Exercise, delete: bool):
|
||||
"""
|
||||
Delete exercises without translations
|
||||
"""
|
||||
if not base.pk or base.exercises.count():
|
||||
if not base.pk or base.translations.count():
|
||||
return
|
||||
|
||||
self.stdout.write(self.style.WARNING(f'Exercise {base.uuid} has no translations!'))
|
||||
@@ -105,8 +105,8 @@ class Command(BaseCommand):
|
||||
base.delete()
|
||||
self.stdout.write(' -> deleted')
|
||||
|
||||
def handle_no_english(self, base: ExerciseBase, delete: bool):
|
||||
if not base.pk or base.exercises.filter(language=self.english).exists():
|
||||
def handle_no_english(self, base: Exercise, delete: bool):
|
||||
if not base.pk or base.translations.filter(language=self.english).exists():
|
||||
return
|
||||
|
||||
self.stdout.write(self.style.WARNING(f'Exercise {base.uuid} has no English translation!'))
|
||||
@@ -114,11 +114,11 @@ class Command(BaseCommand):
|
||||
base.delete()
|
||||
self.stdout.write(' -> deleted')
|
||||
|
||||
def handle_duplicate_translations(self, base: ExerciseBase, delete: bool):
|
||||
def handle_duplicate_translations(self, base: Exercise, delete: bool):
|
||||
if not base.pk:
|
||||
return
|
||||
|
||||
exercise_languages = base.exercises.values_list('language', flat=True)
|
||||
exercise_languages = base.translations.values_list('language', flat=True)
|
||||
duplicates = [
|
||||
Language.objects.get(pk=item)
|
||||
for item, count in collections.Counter(exercise_languages).items()
|
||||
@@ -133,7 +133,7 @@ class Command(BaseCommand):
|
||||
|
||||
# Output the duplicates
|
||||
for language in duplicates:
|
||||
translations = base.exercises.filter(language=language)
|
||||
translations = base.translations.filter(language=language)
|
||||
self.stdout.write(f'language {language.short_name}:')
|
||||
for translation in translations:
|
||||
self.stdout.write(f' * {translation.name} {translation.uuid}')
|
||||
|
||||
@@ -29,10 +29,10 @@ from wger.core.models import (
|
||||
from wger.exercises.models import (
|
||||
Alias,
|
||||
Equipment,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
ExerciseCategory,
|
||||
ExerciseVideo,
|
||||
Translation,
|
||||
Variation,
|
||||
)
|
||||
from wger.utils.constants import CC_BY_SA_4_ID
|
||||
@@ -120,12 +120,12 @@ class Command(BaseCommand):
|
||||
continue
|
||||
|
||||
base = (
|
||||
ExerciseBase.objects.get_or_create(
|
||||
Exercise.objects.get_or_create(
|
||||
uuid=base_uuid,
|
||||
defaults={'category': ExerciseCategory.objects.get(name=base_category)},
|
||||
)[0]
|
||||
if not new_base
|
||||
else ExerciseBase()
|
||||
else Exercise()
|
||||
)
|
||||
|
||||
# Update the base data
|
||||
@@ -273,9 +273,9 @@ class Command(BaseCommand):
|
||||
|
||||
if base_uuid:
|
||||
try:
|
||||
ExerciseBase.objects.filter(uuid=base_uuid).delete()
|
||||
Exercise.objects.filter(uuid=base_uuid).delete()
|
||||
self.stdout.write(f'* Deleted base {base_uuid}')
|
||||
except ExerciseBase.DoesNotExist:
|
||||
except Exercise.DoesNotExist:
|
||||
pass
|
||||
|
||||
if translation_uuid:
|
||||
|
||||
@@ -17,7 +17,7 @@ from django.core.management.base import BaseCommand
|
||||
|
||||
# wger
|
||||
from wger.exercises.api.serializers import ExerciseBaseInfoSerializer
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.utils.cache import reset_exercise_api_cache
|
||||
|
||||
|
||||
@@ -47,14 +47,14 @@ class Command(BaseCommand):
|
||||
force = options['force']
|
||||
|
||||
if exercise_base_id:
|
||||
exercise = ExerciseBase.objects.get(pk=exercise_base_id)
|
||||
exercise = Exercise.objects.get(pk=exercise_base_id)
|
||||
self.handle_cache(exercise, force)
|
||||
return
|
||||
|
||||
for exercise in ExerciseBase.translations.all():
|
||||
for exercise in Exercise.with_translations.all():
|
||||
self.handle_cache(exercise, force)
|
||||
|
||||
def handle_cache(self, exercise: ExerciseBase, force: bool):
|
||||
def handle_cache(self, exercise: Exercise, force: bool):
|
||||
if force:
|
||||
self.stdout.write(f'Force updating cache for exercise base {exercise.uuid}')
|
||||
else:
|
||||
|
||||
@@ -23,14 +23,14 @@ class ExerciseBaseManagerTranslations(models.Manager):
|
||||
"""Returns all exercise bases that have at least one translation"""
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().annotate(count=Count('exercises')).filter(count__gt=0)
|
||||
return super().get_queryset().annotate(count=Count('translations')).filter(count__gt=0)
|
||||
|
||||
|
||||
class ExerciseBaseManagerNoTranslations(models.Manager):
|
||||
"""Returns all exercise bases that have no translations"""
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().annotate(count=Count('exercises')).filter(count=0)
|
||||
return super().get_queryset().annotate(count=Count('translations')).filter(count=0)
|
||||
|
||||
|
||||
class ExerciseBaseManagerAll(models.Manager):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Generated by Django 4.2.13 on 2024-06-12 12:59
|
||||
# Generated by Django 4.2.13 on 2024-07-08 17:02
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
@@ -6,6 +6,7 @@ from django.db import migrations
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('exercises', '0030_increase_author_field_length'),
|
||||
('manager', '0017_alter_workoutlog_exercise_base'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
@@ -17,4 +18,12 @@ class Migration(migrations.Migration):
|
||||
old_name='HistoricalExercise',
|
||||
new_name='HistoricalTranslation',
|
||||
),
|
||||
migrations.RenameModel(
|
||||
old_name='ExerciseBase',
|
||||
new_name='Exercise',
|
||||
),
|
||||
migrations.RenameModel(
|
||||
old_name='HistoricalExerciseBase',
|
||||
new_name='HistoricalExercise',
|
||||
),
|
||||
]
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Local
|
||||
from .base import ExerciseBase
|
||||
from .base import Exercise
|
||||
from .category import ExerciseCategory
|
||||
from .comment import ExerciseComment
|
||||
from .deletion_log import DeletionLog
|
||||
|
||||
@@ -24,7 +24,10 @@ from typing import (
|
||||
|
||||
# Django
|
||||
from django.core.checks import Warning
|
||||
from django.db import models, OperationalError
|
||||
from django.db import (
|
||||
OperationalError,
|
||||
models,
|
||||
)
|
||||
from django.db.models import Q
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import (
|
||||
@@ -55,14 +58,14 @@ from .muscle import Muscle
|
||||
from .variation import Variation
|
||||
|
||||
|
||||
class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
class Exercise(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
"""
|
||||
Model for an exercise base
|
||||
"""
|
||||
|
||||
objects = ExerciseBaseManagerAll()
|
||||
no_translations = ExerciseBaseManagerNoTranslations()
|
||||
translations = ExerciseBaseManagerTranslations()
|
||||
with_translations = ExerciseBaseManagerTranslations()
|
||||
"""
|
||||
Custom Query Manager
|
||||
"""
|
||||
@@ -150,8 +153,8 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
Warning(
|
||||
'exercises without translations',
|
||||
hint=f'There are {no_translations} exercises without translations, this will '
|
||||
'cause problems! You can output or delete them with "python manage.py '
|
||||
'exercises-health-check --help"',
|
||||
'cause problems! You can output or delete them with "python manage.py '
|
||||
'exercises-health-check --help"',
|
||||
id='wger.W002',
|
||||
)
|
||||
)
|
||||
@@ -172,7 +175,7 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
All authors history related to the BaseExercise.
|
||||
"""
|
||||
collect_for_models = [
|
||||
*self.exercises.all(),
|
||||
*self.translations.all(),
|
||||
*self.exercisevideo_set.all(),
|
||||
*self.exerciseimage_set.all(),
|
||||
]
|
||||
@@ -187,7 +190,7 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
self.last_update,
|
||||
*[image.last_update for image in self.exerciseimage_set.all()],
|
||||
*[video.last_update for video in self.exercisevideo_set.all()],
|
||||
*[translation.last_update for translation in self.exercises.all()],
|
||||
*[translation.last_update for translation in self.translations.all()],
|
||||
datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc),
|
||||
)
|
||||
|
||||
@@ -203,7 +206,7 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
"""
|
||||
Returns the languages from the exercises that use this base
|
||||
"""
|
||||
return [exercise.language for exercise in self.exercises.all()]
|
||||
return [exercise.language for exercise in self.translations.all()]
|
||||
|
||||
@property
|
||||
def base_variations(self):
|
||||
@@ -212,7 +215,7 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
"""
|
||||
if not self.variations:
|
||||
return []
|
||||
return self.variations.exercisebase_set.filter(~Q(id=self.id))
|
||||
return self.variations.exercise_set.filter(~Q(id=self.id))
|
||||
|
||||
def get_translation(self, language: Optional[str] = None):
|
||||
"""
|
||||
@@ -230,14 +233,14 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
language = language or get_language()
|
||||
|
||||
try:
|
||||
translation = self.exercises.get(language__short_name=language)
|
||||
translation = self.translations.get(language__short_name=language)
|
||||
except Translation.DoesNotExist:
|
||||
try:
|
||||
translation = self.exercises.get(language__short_name=ENGLISH_SHORT_NAME)
|
||||
translation = self.translations.get(language__short_name=ENGLISH_SHORT_NAME)
|
||||
except Translation.DoesNotExist:
|
||||
translation = self.exercises.first()
|
||||
translation = self.translations.first()
|
||||
except Translation.MultipleObjectsReturned:
|
||||
translation = self.exercises.filter(language__short_name=language).first()
|
||||
translation = self.translations.filter(language__short_name=language).first()
|
||||
|
||||
return translation
|
||||
|
||||
@@ -255,12 +258,12 @@ class ExerciseBase(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
|
||||
if replace_by:
|
||||
try:
|
||||
ExerciseBase.objects.get(uuid=replace_by)
|
||||
except ExerciseBase.DoesNotExist:
|
||||
Exercise.objects.get(uuid=replace_by)
|
||||
except Exercise.DoesNotExist:
|
||||
replace_by = None
|
||||
|
||||
log = DeletionLog(
|
||||
model_type=DeletionLog.MODEL_BASE,
|
||||
model_type=DeletionLog.MODEL_EXERCISE,
|
||||
uuid=self.uuid,
|
||||
comment=f'Exercise base of {self.get_translation(ENGLISH_SHORT_NAME)}',
|
||||
replaced_by=replace_by,
|
||||
|
||||
@@ -30,13 +30,13 @@ class DeletionLog(models.Model):
|
||||
different DBs, without any way of cleaning them up.
|
||||
"""
|
||||
|
||||
MODEL_BASE = 'base'
|
||||
MODEL_EXERCISE = 'base'
|
||||
MODEL_TRANSLATION = 'translation'
|
||||
MODEL_IMAGE = 'image'
|
||||
MODEL_VIDEO = 'video'
|
||||
|
||||
MODELS = [
|
||||
(MODEL_BASE, 'base'),
|
||||
(MODEL_EXERCISE, 'base'),
|
||||
(MODEL_TRANSLATION, 'translation'),
|
||||
(MODEL_IMAGE, 'image'),
|
||||
(MODEL_VIDEO, 'video'),
|
||||
|
||||
@@ -21,12 +21,11 @@ import uuid
|
||||
# Django
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
# Third Party
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
||||
# wger
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.utils.cache import reset_exercise_api_cache
|
||||
from wger.utils.helpers import BaseImage
|
||||
from wger.utils.models import (
|
||||
@@ -70,7 +69,7 @@ class ExerciseImage(AbstractLicenseModel, AbstractHistoryMixin, models.Model, Ba
|
||||
"""Globally unique ID, to identify the image across installations"""
|
||||
|
||||
exercise_base = models.ForeignKey(
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
verbose_name=_('Exercise'),
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
@@ -185,7 +184,7 @@ class ExerciseImage(AbstractLicenseModel, AbstractHistoryMixin, models.Model, Ba
|
||||
@classmethod
|
||||
def from_json(
|
||||
cls,
|
||||
connect_to: ExerciseBase,
|
||||
connect_to: Exercise,
|
||||
retrieved_image,
|
||||
json_data: dict,
|
||||
generate_uuid: bool = False,
|
||||
|
||||
@@ -30,7 +30,7 @@ from simple_history.models import HistoricalRecords
|
||||
|
||||
# wger
|
||||
from wger.core.models import Language
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.utils.cache import reset_exercise_api_cache
|
||||
from wger.utils.models import (
|
||||
AbstractHistoryMixin,
|
||||
@@ -84,12 +84,12 @@ class Translation(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
"""Globally unique ID, to identify the exercise across installations"""
|
||||
|
||||
exercise_base = models.ForeignKey(
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
verbose_name='ExerciseBase',
|
||||
on_delete=models.CASCADE,
|
||||
default=None,
|
||||
null=False,
|
||||
related_name='exercises',
|
||||
related_name='translations',
|
||||
)
|
||||
""" Refers to the base exercise with non translated information """
|
||||
|
||||
@@ -176,8 +176,8 @@ class Translation(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
"""
|
||||
out = []
|
||||
if self.exercise_base.variations:
|
||||
for variation in self.exercise_base.variations.exercisebase_set.all():
|
||||
for exercise in variation.exercises.filter(language=self.language).all():
|
||||
for variation in self.exercise_base.variations.exercise_set.all():
|
||||
for exercise in variation.translations.filter(language=self.language).all():
|
||||
out.append(exercise)
|
||||
return out
|
||||
|
||||
|
||||
@@ -22,14 +22,12 @@ import uuid
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
# Third Party
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
||||
# wger
|
||||
from wger.utils.cache import reset_exercise_api_cache
|
||||
|
||||
|
||||
try:
|
||||
# Third Party
|
||||
import ffmpeg
|
||||
@@ -37,7 +35,7 @@ except ImportError:
|
||||
ffmpeg = None
|
||||
|
||||
# wger
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.utils.models import (
|
||||
AbstractHistoryMixin,
|
||||
AbstractLicenseModel,
|
||||
@@ -94,7 +92,7 @@ class ExerciseVideo(AbstractLicenseModel, AbstractHistoryMixin, models.Model):
|
||||
"""Globally unique ID, to identify the image across installations"""
|
||||
|
||||
exercise_base = models.ForeignKey(
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
verbose_name=_('Exercise'),
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
@@ -32,9 +32,9 @@ from easy_thumbnails.signals import saved_file
|
||||
# wger
|
||||
from wger.exercises.models import (
|
||||
DeletionLog,
|
||||
Translation,
|
||||
ExerciseImage,
|
||||
ExerciseVideo,
|
||||
Translation,
|
||||
)
|
||||
|
||||
|
||||
@@ -113,27 +113,24 @@ def delete_exercise_video_on_update(sender, instance: ExerciseVideo, **kwargs):
|
||||
|
||||
@receiver(pre_delete, sender=Translation)
|
||||
def add_deletion_log_translation(sender, instance: Translation, **kwargs):
|
||||
log = DeletionLog(
|
||||
DeletionLog(
|
||||
model_type=DeletionLog.MODEL_TRANSLATION,
|
||||
uuid=instance.uuid,
|
||||
comment=instance.name,
|
||||
)
|
||||
log.save()
|
||||
).save()
|
||||
|
||||
|
||||
@receiver(pre_delete, sender=ExerciseImage)
|
||||
def add_deletion_log_image(sender, instance: ExerciseImage, **kwargs):
|
||||
log = DeletionLog(
|
||||
DeletionLog(
|
||||
model_type=DeletionLog.MODEL_IMAGE,
|
||||
uuid=instance.uuid,
|
||||
)
|
||||
log.save()
|
||||
).save()
|
||||
|
||||
|
||||
@receiver(pre_delete, sender=ExerciseVideo)
|
||||
def add_deletion_log_video(sender, instance: ExerciseVideo, **kwargs):
|
||||
log = DeletionLog(
|
||||
DeletionLog(
|
||||
model_type=DeletionLog.MODEL_VIDEO,
|
||||
uuid=instance.uuid,
|
||||
)
|
||||
log.save()
|
||||
).save()
|
||||
|
||||
@@ -44,13 +44,13 @@ from wger.exercises.models import (
|
||||
Alias,
|
||||
DeletionLog,
|
||||
Equipment,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
ExerciseCategory,
|
||||
ExerciseComment,
|
||||
ExerciseImage,
|
||||
ExerciseVideo,
|
||||
Muscle,
|
||||
Translation,
|
||||
)
|
||||
from wger.manager.models import (
|
||||
SlotConfig,
|
||||
@@ -83,7 +83,7 @@ def sync_exercises(
|
||||
muscles = [Muscle.objects.get(pk=i['id']) for i in data['muscles']]
|
||||
muscles_sec = [Muscle.objects.get(pk=i['id']) for i in data['muscles_secondary']]
|
||||
|
||||
base, base_created = ExerciseBase.objects.update_or_create(
|
||||
base, base_created = Exercise.objects.update_or_create(
|
||||
uuid=uuid,
|
||||
defaults={'category_id': category_id, 'created': created},
|
||||
)
|
||||
@@ -295,6 +295,7 @@ def handle_deleted_entries(
|
||||
style_fn=lambda x: x,
|
||||
):
|
||||
if not print_fn:
|
||||
|
||||
def print_fn(_):
|
||||
return None
|
||||
|
||||
@@ -308,18 +309,18 @@ def handle_deleted_entries(
|
||||
replaced_by_uuid = data['replaced_by']
|
||||
model_type = data['model_type']
|
||||
|
||||
if model_type == DeletionLog.MODEL_BASE:
|
||||
if model_type == DeletionLog.MODEL_EXERCISE:
|
||||
obj_replaced = None
|
||||
nr_settings = None
|
||||
nr_slot_configs = None
|
||||
nr_logs = None
|
||||
try:
|
||||
obj_replaced = ExerciseBase.objects.get(uuid=replaced_by_uuid)
|
||||
except ExerciseBase.DoesNotExist:
|
||||
obj_replaced = Exercise.objects.get(uuid=replaced_by_uuid)
|
||||
except Exercise.DoesNotExist:
|
||||
pass
|
||||
|
||||
try:
|
||||
obj = ExerciseBase.objects.get(uuid=uuid)
|
||||
obj = Exercise.objects.get(uuid=uuid)
|
||||
|
||||
# Replace exercise in workouts and logs
|
||||
if obj_replaced:
|
||||
@@ -337,7 +338,7 @@ def handle_deleted_entries(
|
||||
print_fn(f'- replaced in {nr_slot_configs} routines with {replaced_by_uuid}')
|
||||
if nr_logs:
|
||||
print_fn(f'- replaced in {nr_logs} workout logs with {replaced_by_uuid}')
|
||||
except ExerciseBase.DoesNotExist:
|
||||
except Exercise.DoesNotExist:
|
||||
pass
|
||||
|
||||
elif model_type == DeletionLog.MODEL_TRANSLATION:
|
||||
@@ -391,8 +392,8 @@ def download_exercise_images(
|
||||
print_fn(f'Processing image {image_uuid}')
|
||||
|
||||
try:
|
||||
exercise = ExerciseBase.objects.get(uuid=image_data['exercise_base_uuid'])
|
||||
except ExerciseBase.DoesNotExist:
|
||||
exercise = Exercise.objects.get(uuid=image_data['exercise_base_uuid'])
|
||||
except Exercise.DoesNotExist:
|
||||
print_fn(' Remote exercise base not found in local DB, skipping...')
|
||||
continue
|
||||
|
||||
@@ -423,8 +424,8 @@ def download_exercise_videos(
|
||||
print_fn(f'Processing video {video_uuid}')
|
||||
|
||||
try:
|
||||
exercise = ExerciseBase.objects.get(uuid=video_data['exercise_base_uuid'])
|
||||
except ExerciseBase.DoesNotExist:
|
||||
exercise = Exercise.objects.get(uuid=video_data['exercise_base_uuid'])
|
||||
except Exercise.DoesNotExist:
|
||||
print_fn(' Remote exercise base not found in local DB, skipping...')
|
||||
continue
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ from django.core.management import call_command
|
||||
# wger
|
||||
from wger.core.tests.base_testcase import WgerTestCase
|
||||
from wger.exercises.models import Translation
|
||||
from wger.exercises.models.base import ExerciseBase
|
||||
from wger.exercises.models.base import Exercise
|
||||
|
||||
|
||||
class ChangeExerciseAuthorTestCase(WgerTestCase):
|
||||
@@ -52,14 +52,14 @@ class ChangeExerciseAuthorTestCase(WgerTestCase):
|
||||
"""
|
||||
Test to ensure command can handle an exercise base id passed
|
||||
"""
|
||||
exercise = ExerciseBase.objects.get(id=2)
|
||||
exercise = Exercise.objects.get(id=2)
|
||||
self.assertNotEqual(exercise.license_author, 'tom')
|
||||
|
||||
args = ['--author-name', 'tom', '--exercise-base-id', '2']
|
||||
call_command('change-exercise-author', *args, stdout=self.out, no_color=True)
|
||||
self.assertIn('Exercise and/or exercise base has been updated', self.out.getvalue())
|
||||
|
||||
exercise = ExerciseBase.objects.get(id=2)
|
||||
exercise = Exercise.objects.get(id=2)
|
||||
self.assertEqual(exercise.license_author, 'tom')
|
||||
|
||||
def test_can_update_exercise(self):
|
||||
|
||||
@@ -19,8 +19,8 @@ from uuid import UUID
|
||||
from wger.core.tests.base_testcase import WgerTestCase
|
||||
from wger.exercises.models import (
|
||||
DeletionLog,
|
||||
Exercise,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
)
|
||||
|
||||
|
||||
@@ -29,25 +29,25 @@ class DeletionLogTestCase(WgerTestCase):
|
||||
Test that the deletion log entries are correctly generated
|
||||
"""
|
||||
|
||||
def test_base(self):
|
||||
def test_exercise(self):
|
||||
"""
|
||||
Test that an entry is generated when a base is deleted
|
||||
"""
|
||||
self.assertEqual(DeletionLog.objects.all().count(), 0)
|
||||
|
||||
base = ExerciseBase.objects.get(pk=1)
|
||||
base.delete()
|
||||
exercise = Exercise.objects.get(pk=1)
|
||||
exercise.delete()
|
||||
|
||||
# Base is deleted
|
||||
count_base_logs = DeletionLog.objects.filter(
|
||||
model_type=DeletionLog.MODEL_BASE,
|
||||
uuid=base.uuid,
|
||||
# Exercise is deleted
|
||||
count_exercise_logs = DeletionLog.objects.filter(
|
||||
model_type=DeletionLog.MODEL_EXERCISE,
|
||||
uuid=exercise.uuid,
|
||||
).count()
|
||||
log = DeletionLog.objects.get(pk=1)
|
||||
|
||||
self.assertEqual(count_base_logs, 1)
|
||||
self.assertEqual(log.model_type, 'base')
|
||||
self.assertEqual(log.uuid, base.uuid)
|
||||
self.assertEqual(count_exercise_logs, 1)
|
||||
self.assertEqual(log.model_type, DeletionLog.MODEL_EXERCISE)
|
||||
self.assertEqual(log.uuid, exercise.uuid)
|
||||
self.assertEqual(log.comment, 'Exercise base of An exercise')
|
||||
self.assertEqual(log.replaced_by, None)
|
||||
|
||||
@@ -57,49 +57,49 @@ class DeletionLogTestCase(WgerTestCase):
|
||||
|
||||
# First translation
|
||||
log2 = DeletionLog.objects.get(pk=4)
|
||||
self.assertEqual(log2.model_type, 'translation')
|
||||
self.assertEqual(log2.model_type, DeletionLog.MODEL_TRANSLATION)
|
||||
self.assertEqual(log2.uuid, UUID('9838235c-e38f-4ca6-921e-9d237d8e0813'))
|
||||
self.assertEqual(log2.comment, 'An exercise')
|
||||
self.assertEqual(log2.replaced_by, None)
|
||||
|
||||
# Second translation
|
||||
log3 = DeletionLog.objects.get(pk=5)
|
||||
self.assertEqual(log3.model_type, 'translation')
|
||||
self.assertEqual(log3.model_type, DeletionLog.MODEL_TRANSLATION)
|
||||
self.assertEqual(log3.uuid, UUID('13b532f9-d208-462e-a000-7b9982b2b53e'))
|
||||
self.assertEqual(log3.comment, 'Test exercise 123')
|
||||
self.assertEqual(log3.replaced_by, None)
|
||||
|
||||
def test_base_with_replaced_by(self):
|
||||
def test_exercise_with_replaced_by(self):
|
||||
"""
|
||||
Test that an entry is generated when a base is deleted and the replaced by is
|
||||
set correctly
|
||||
"""
|
||||
self.assertEqual(DeletionLog.objects.all().count(), 0)
|
||||
|
||||
exercise = ExerciseBase.objects.get(pk=1)
|
||||
exercise = Exercise.objects.get(pk=1)
|
||||
exercise.delete(replace_by='ae3328ba-9a35-4731-bc23-5da50720c5aa')
|
||||
|
||||
# Base is deleted
|
||||
log = DeletionLog.objects.get(pk=1)
|
||||
|
||||
self.assertEqual(log.model_type, 'base')
|
||||
self.assertEqual(log.model_type, DeletionLog.MODEL_EXERCISE)
|
||||
self.assertEqual(log.uuid, exercise.uuid)
|
||||
self.assertEqual(log.replaced_by, UUID('ae3328ba-9a35-4731-bc23-5da50720c5aa'))
|
||||
|
||||
def test_base_with_nonexistent_replaced_by(self):
|
||||
def test_exercise_with_nonexistent_replaced_by(self):
|
||||
"""
|
||||
Test that an entry is generated when a base is deleted and the replaced by is
|
||||
set correctly. If the UUID is not found in the DB, it's set to None
|
||||
"""
|
||||
self.assertEqual(DeletionLog.objects.all().count(), 0)
|
||||
|
||||
exercise = ExerciseBase.objects.get(pk=1)
|
||||
exercise = Exercise.objects.get(pk=1)
|
||||
exercise.delete(replace_by='12345678-1234-1234-1234-1234567890ab')
|
||||
|
||||
# Base is deleted
|
||||
log = DeletionLog.objects.get(pk=1)
|
||||
|
||||
self.assertEqual(log.model_type, 'base')
|
||||
self.assertEqual(log.model_type, DeletionLog.MODEL_EXERCISE)
|
||||
self.assertEqual(log.replaced_by, None)
|
||||
|
||||
def test_translation(self):
|
||||
@@ -113,6 +113,7 @@ class DeletionLogTestCase(WgerTestCase):
|
||||
|
||||
# Translation is deleted
|
||||
count = DeletionLog.objects.filter(
|
||||
model_type=DeletionLog.MODEL_TRANSLATION, uuid=translation.uuid
|
||||
model_type=DeletionLog.MODEL_TRANSLATION,
|
||||
uuid=translation.uuid,
|
||||
).count()
|
||||
self.assertEqual(count, 1)
|
||||
|
||||
@@ -19,9 +19,9 @@ from django.core.cache import cache
|
||||
from wger.core.tests.base_testcase import WgerTestCase
|
||||
from wger.exercises.models import (
|
||||
Alias,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
ExerciseComment,
|
||||
Translation,
|
||||
)
|
||||
from wger.utils.cache import cache_mapper
|
||||
|
||||
@@ -45,7 +45,7 @@ class ExerciseApiCacheTestCase(WgerTestCase):
|
||||
self.client.get(self.url)
|
||||
self.assertTrue(cache.get(self.cache_key))
|
||||
|
||||
exercise = ExerciseBase.objects.get(pk=1)
|
||||
exercise = Exercise.objects.get(pk=1)
|
||||
exercise.category_id = 1
|
||||
exercise.save()
|
||||
|
||||
@@ -59,7 +59,7 @@ class ExerciseApiCacheTestCase(WgerTestCase):
|
||||
self.client.get(self.url)
|
||||
self.assertTrue(cache.get(self.cache_key))
|
||||
|
||||
exercise = ExerciseBase.objects.get(pk=1)
|
||||
exercise = Exercise.objects.get(pk=1)
|
||||
exercise.delete()
|
||||
|
||||
self.assertFalse(cache.get(self.cache_key))
|
||||
|
||||
@@ -23,8 +23,8 @@ from wger.core.tests.api_base_test import ExerciseCrudApiTestCase
|
||||
from wger.core.tests.base_testcase import WgerTestCase
|
||||
from wger.exercises.models import (
|
||||
DeletionLog,
|
||||
Exercise,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
)
|
||||
from wger.utils.constants import CC_BY_SA_4_ID
|
||||
|
||||
@@ -57,7 +57,7 @@ class ExerciseBaseTestCase(WgerTestCase):
|
||||
"""
|
||||
Test that the base correctly returns translated exercises
|
||||
"""
|
||||
exercise = ExerciseBase.objects.get(pk=1).get_translation('de')
|
||||
exercise = Exercise.objects.get(pk=1).get_translation('de')
|
||||
self.assertEqual(exercise.name, 'An exercise')
|
||||
|
||||
def test_language_utils_no_translation_exists(self):
|
||||
@@ -65,7 +65,7 @@ class ExerciseBaseTestCase(WgerTestCase):
|
||||
Test that the base correctly returns the English translation if the
|
||||
requested language does not exist
|
||||
"""
|
||||
exercise = ExerciseBase.objects.get(pk=1).get_translation('fr')
|
||||
exercise = Exercise.objects.get(pk=1).get_translation('fr')
|
||||
self.assertEqual(exercise.name, 'Test exercise 123')
|
||||
|
||||
def test_language_utils_no_translation_fallback(self):
|
||||
@@ -73,7 +73,7 @@ class ExerciseBaseTestCase(WgerTestCase):
|
||||
Test that the base correctly returns the first translation if for whatever
|
||||
reason English is not available
|
||||
"""
|
||||
exercise = ExerciseBase.objects.get(pk=2).get_translation('pt')
|
||||
exercise = Exercise.objects.get(pk=2).get_translation('pt')
|
||||
|
||||
self.assertEqual(exercise.name, 'Very cool exercise')
|
||||
|
||||
@@ -82,10 +82,10 @@ class ExerciseBaseTestCase(WgerTestCase):
|
||||
|
||||
# Even if these exercises have the same base, only the variations for
|
||||
# their respective languages are returned.
|
||||
exercise = ExerciseBase.objects.get(pk=1)
|
||||
exercise = Exercise.objects.get(pk=1)
|
||||
self.assertListEqual(sorted([i.id for i in exercise.base_variations]), [2])
|
||||
|
||||
exercise2 = ExerciseBase.objects.get(pk=3)
|
||||
exercise2 = Exercise.objects.get(pk=3)
|
||||
self.assertEqual(sorted([i.id for i in exercise2.base_variations]), [4])
|
||||
|
||||
def test_images(self):
|
||||
@@ -131,14 +131,14 @@ class ExerciseCustomApiTestCase(ExerciseCrudApiTestCase):
|
||||
Test that it is not possible to change the license of an existing
|
||||
exercise base
|
||||
"""
|
||||
exercise = ExerciseBase.objects.get(pk=self.pk)
|
||||
exercise = Exercise.objects.get(pk=self.pk)
|
||||
self.assertEqual(exercise.license_id, 2)
|
||||
|
||||
self.authenticate('trainer1')
|
||||
response = self.client.patch(self.url_detail, data={'license': 3})
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
exercise = ExerciseBase.objects.get(pk=self.pk)
|
||||
exercise = Exercise.objects.get(pk=self.pk)
|
||||
self.assertEqual(exercise.license_id, 2)
|
||||
|
||||
def test_cant_set_license(self):
|
||||
@@ -152,5 +152,5 @@ class ExerciseCustomApiTestCase(ExerciseCrudApiTestCase):
|
||||
response = self.client.post(self.url, data=self.data)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
exercise = ExerciseBase.objects.get(pk=self.pk)
|
||||
exercise = Exercise.objects.get(pk=self.pk)
|
||||
self.assertEqual(exercise.license_id, CC_BY_SA_4_ID)
|
||||
|
||||
@@ -18,8 +18,8 @@ import datetime
|
||||
# wger
|
||||
from wger.core.tests.base_testcase import WgerTestCase
|
||||
from wger.exercises.models import (
|
||||
Exercise,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
)
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@ class ExerciseBaseTranslationHandlingTestCase(WgerTestCase):
|
||||
Translation.objects.get(pk=5).delete()
|
||||
|
||||
def test_managers(self):
|
||||
self.assertEqual(ExerciseBase.translations.all().count(), 7)
|
||||
self.assertEqual(ExerciseBase.no_translations.all().count(), 1)
|
||||
self.assertEqual(ExerciseBase.objects.all().count(), 8)
|
||||
self.assertEqual(Exercise.with_translations.all().count(), 7)
|
||||
self.assertEqual(Exercise.no_translations.all().count(), 1)
|
||||
self.assertEqual(Exercise.objects.all().count(), 8)
|
||||
|
||||
def test_checks(self):
|
||||
out = ExerciseBase.check()
|
||||
out = Exercise.check()
|
||||
self.assertEqual(len(out), 1)
|
||||
self.assertEqual(out[0].id, 'wger.W002')
|
||||
|
||||
@@ -49,11 +49,11 @@ class ExerciseBaseModelTestCase(WgerTestCase):
|
||||
Test custom model logic
|
||||
"""
|
||||
|
||||
exercise: ExerciseBase
|
||||
exercise: Exercise
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.exercise = ExerciseBase.objects.get(pk=1)
|
||||
self.exercise = Exercise.objects.get(pk=1)
|
||||
|
||||
def test_access_date(self):
|
||||
utc = datetime.timezone.utc
|
||||
@@ -66,7 +66,7 @@ class ExerciseBaseModelTestCase(WgerTestCase):
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
max(*[translation.last_update for translation in self.exercise.exercises.all()]),
|
||||
max(*[translation.last_update for translation in self.exercise.translations.all()]),
|
||||
datetime.datetime(2022, 2, 2, 5, 45, 11, tzinfo=utc),
|
||||
)
|
||||
|
||||
|
||||
@@ -17,12 +17,10 @@ from django.core.files import File
|
||||
|
||||
# wger
|
||||
from wger.core.tests import api_base_test
|
||||
from wger.core.tests.base_testcase import (
|
||||
WgerTestCase,
|
||||
)
|
||||
from wger.core.tests.base_testcase import WgerTestCase
|
||||
from wger.exercises.models import (
|
||||
Translation,
|
||||
ExerciseImage,
|
||||
Translation,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -27,12 +27,10 @@ from rest_framework import status
|
||||
# wger
|
||||
from wger.core.tests import api_base_test
|
||||
from wger.core.tests.api_base_test import ExerciseCrudApiTestCase
|
||||
from wger.core.tests.base_testcase import (
|
||||
WgerTestCase,
|
||||
)
|
||||
from wger.core.tests.base_testcase import WgerTestCase
|
||||
from wger.exercises.models import (
|
||||
Translation,
|
||||
Muscle,
|
||||
Translation,
|
||||
)
|
||||
from wger.utils.constants import CC_BY_SA_4_ID
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ from django.test import SimpleTestCase
|
||||
# wger
|
||||
from wger.core.tests.base_testcase import WgerTestCase
|
||||
from wger.exercises.models import (
|
||||
Exercise,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
)
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ class TestHealthCheckManagementCommands(WgerTestCase):
|
||||
|
||||
call_command('exercises-health-check', '--delete-untranslated', stdout=self.out)
|
||||
self.assertIn('-> deleted', self.out.getvalue())
|
||||
self.assertRaises(ExerciseBase.DoesNotExist, ExerciseBase.objects.get, pk=1)
|
||||
self.assertRaises(Exercise.DoesNotExist, Exercise.objects.get, pk=1)
|
||||
|
||||
def test_find_no_english_translation(self):
|
||||
Translation.objects.get(pk=1).delete()
|
||||
@@ -110,7 +110,7 @@ class TestHealthCheckManagementCommands(WgerTestCase):
|
||||
|
||||
call_command('exercises-health-check', '--delete-no-english', stdout=self.out)
|
||||
self.assertIn('-> deleted', self.out.getvalue())
|
||||
self.assertRaises(ExerciseBase.DoesNotExist, ExerciseBase.objects.get, pk=1)
|
||||
self.assertRaises(Exercise.DoesNotExist, Exercise.objects.get, pk=1)
|
||||
|
||||
def test_find_duplicate_translations(self):
|
||||
exercise = Translation.objects.get(pk=1)
|
||||
|
||||
@@ -23,10 +23,10 @@ from wger.core.models import (
|
||||
from wger.core.tests.base_testcase import WgerTestCase
|
||||
from wger.exercises.models import (
|
||||
Equipment,
|
||||
Translation,
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
ExerciseCategory,
|
||||
Muscle,
|
||||
Translation,
|
||||
)
|
||||
from wger.exercises.sync import (
|
||||
handle_deleted_entries,
|
||||
@@ -647,11 +647,11 @@ class TestSyncMethods(WgerTestCase):
|
||||
|
||||
@patch('requests.get', return_value=MockDeletionLogResponse())
|
||||
def test_deletion_log(self, mock_request):
|
||||
self.assertEqual(ExerciseBase.objects.count(), 8)
|
||||
self.assertEqual(Exercise.objects.count(), 8)
|
||||
self.assertEqual(Translation.objects.count(), 11)
|
||||
|
||||
exercise1 = ExerciseBase.objects.get(pk=1)
|
||||
exercise2 = ExerciseBase.objects.get(pk=4)
|
||||
exercise1 = Exercise.objects.get(pk=1)
|
||||
exercise2 = Exercise.objects.get(pk=4)
|
||||
self.assertFalse(SlotConfig.objects.filter(exercise=exercise2).count())
|
||||
self.assertFalse(WorkoutLog.objects.filter(exercise=exercise2).count())
|
||||
|
||||
@@ -664,10 +664,10 @@ class TestSyncMethods(WgerTestCase):
|
||||
'https://wger.de/api/v2/deletion-log/?limit=100',
|
||||
headers=wger_headers(),
|
||||
)
|
||||
self.assertEqual(ExerciseBase.objects.count(), 7)
|
||||
self.assertEqual(Exercise.objects.count(), 7)
|
||||
self.assertEqual(Translation.objects.count(), 8)
|
||||
self.assertRaises(Translation.DoesNotExist, Translation.objects.get, pk=3)
|
||||
self.assertRaises(ExerciseBase.DoesNotExist, ExerciseBase.objects.get, pk=1)
|
||||
self.assertRaises(Exercise.DoesNotExist, Exercise.objects.get, pk=1)
|
||||
|
||||
# Workouts and logs have been moved
|
||||
for pk in slot_configs:
|
||||
@@ -677,9 +677,9 @@ class TestSyncMethods(WgerTestCase):
|
||||
|
||||
@patch('requests.get', return_value=MockExerciseResponse())
|
||||
def test_exercise_sync(self, mock_request):
|
||||
self.assertEqual(ExerciseBase.objects.count(), 8)
|
||||
self.assertEqual(Exercise.objects.count(), 8)
|
||||
self.assertEqual(Translation.objects.count(), 11)
|
||||
exercise = ExerciseBase.objects.get(uuid='ae3328ba-9a35-4731-bc23-5da50720c5aa')
|
||||
exercise = Exercise.objects.get(uuid='ae3328ba-9a35-4731-bc23-5da50720c5aa')
|
||||
self.assertEqual(exercise.category_id, 2)
|
||||
|
||||
sync_exercises(lambda x: x)
|
||||
@@ -688,11 +688,11 @@ class TestSyncMethods(WgerTestCase):
|
||||
'https://wger.de/api/v2/exercisebaseinfo/?limit=100',
|
||||
headers=wger_headers(),
|
||||
)
|
||||
self.assertEqual(ExerciseBase.objects.count(), 9)
|
||||
self.assertEqual(Exercise.objects.count(), 9)
|
||||
self.assertEqual(Translation.objects.count(), 14)
|
||||
|
||||
# New exercise was created
|
||||
new_exercise = ExerciseBase.objects.get(uuid='1b020b3a-3732-4c7e-92fd-a0cec90ed69b')
|
||||
new_exercise = Exercise.objects.get(uuid='1b020b3a-3732-4c7e-92fd-a0cec90ed69b')
|
||||
self.assertEqual(new_exercise.category_id, 2)
|
||||
self.assertEqual([e.id for e in new_exercise.equipment.all()], [2])
|
||||
self.assertEqual([m.id for m in new_exercise.muscles.all()], [2])
|
||||
@@ -714,7 +714,7 @@ class TestSyncMethods(WgerTestCase):
|
||||
self.assertEqual(translation_en.description, 'TBD')
|
||||
|
||||
# Existing exercise was updated
|
||||
exercise = ExerciseBase.objects.get(uuid='ae3328ba-9a35-4731-bc23-5da50720c5aa')
|
||||
exercise = Exercise.objects.get(uuid='ae3328ba-9a35-4731-bc23-5da50720c5aa')
|
||||
self.assertEqual(exercise.category_id, 3)
|
||||
|
||||
translation_de = exercise.get_translation('de')
|
||||
|
||||
@@ -31,9 +31,7 @@ from django.utils.translation import (
|
||||
gettext as _,
|
||||
gettext_lazy,
|
||||
)
|
||||
from django.views.generic import (
|
||||
DeleteView,
|
||||
)
|
||||
from django.views.generic import DeleteView
|
||||
|
||||
# wger
|
||||
from wger.exercises.models import Translation
|
||||
|
||||
@@ -27,7 +27,7 @@ from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
||||
# wger
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.manager.api.consts import CONFIG_FIELDS
|
||||
from wger.manager.api.serializers import (
|
||||
DaySerializer,
|
||||
@@ -228,7 +228,7 @@ class WorkoutViewSet(viewsets.ModelViewSet):
|
||||
if not base_id:
|
||||
return Response("Please provide an base ID in the 'id' GET parameter")
|
||||
|
||||
base = get_object_or_404(ExerciseBase, pk=base_id)
|
||||
base = get_object_or_404(Exercise, pk=base_id)
|
||||
logs = base.workoutlog_set.filter(
|
||||
user=self.request.user,
|
||||
weight_unit__in=(1, 2),
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
This file contains forms used in the application
|
||||
"""
|
||||
|
||||
# Third Party
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import (
|
||||
Column,
|
||||
Layout,
|
||||
Row,
|
||||
Submit,
|
||||
)
|
||||
# Django
|
||||
from django.forms import (
|
||||
BooleanField,
|
||||
@@ -35,21 +43,12 @@ from django.utils.translation import (
|
||||
gettext_lazy,
|
||||
)
|
||||
|
||||
# Third Party
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import (
|
||||
Column,
|
||||
Layout,
|
||||
Row,
|
||||
Submit,
|
||||
)
|
||||
|
||||
# wger
|
||||
from wger.core.models import (
|
||||
RepetitionUnit,
|
||||
WeightUnit,
|
||||
)
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.manager.consts import RIR_OPTIONS
|
||||
from wger.manager.models import (
|
||||
Workout,
|
||||
@@ -119,7 +118,7 @@ class WorkoutLogForm(ModelForm):
|
||||
required=False,
|
||||
)
|
||||
exercise_base = ModelChoiceField(
|
||||
queryset=ExerciseBase.objects.all(),
|
||||
queryset=Exercise.objects.all(),
|
||||
label=_('Exercise'),
|
||||
required=False,
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@ from django.contrib.auth.models import User
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
# wger
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.manager.models import (
|
||||
Day,
|
||||
RepsConfig,
|
||||
@@ -34,7 +34,6 @@ from wger.manager.models import (
|
||||
WeightConfig,
|
||||
)
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -111,7 +110,7 @@ class Command(BaseCommand):
|
||||
day_list[-1].save()
|
||||
|
||||
# Add exercises (no supersets, all very simple)
|
||||
exercise_list = [i for i in ExerciseBase.objects.all()]
|
||||
exercise_list = [i for i in Exercise.objects.all()]
|
||||
for day in day_list:
|
||||
nr_of_exercises = random.randint(3, 6)
|
||||
exercises = random.choices(exercise_list, k=nr_of_exercises)
|
||||
|
||||
@@ -11,7 +11,7 @@ class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('core', '0016_alter_language_short_name'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('exercises', '0028_add_uuid_alias_and_comments'),
|
||||
('exercises', '0032_rename_exercise'),
|
||||
('manager', '0017_alter_workoutlog_exercise_base'),
|
||||
]
|
||||
|
||||
@@ -149,7 +149,7 @@ class Migration(migrations.Migration):
|
||||
(
|
||||
'exercise',
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to='exercises.exercisebase'
|
||||
on_delete=django.db.models.deletion.CASCADE, to='exercises.exercise'
|
||||
),
|
||||
),
|
||||
(
|
||||
|
||||
@@ -28,7 +28,7 @@ from wger.core.models import (
|
||||
RepetitionUnit,
|
||||
WeightUnit,
|
||||
)
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.manager.consts import RIR_OPTIONS
|
||||
from wger.manager.models.session import WorkoutSession
|
||||
from wger.utils.cache import reset_workout_log
|
||||
@@ -77,7 +77,7 @@ class WorkoutLog(models.Model):
|
||||
"""
|
||||
|
||||
exercise = models.ForeignKey(
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
verbose_name=_('Exercise'),
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
@@ -27,7 +27,7 @@ from wger.core.models import (
|
||||
RepetitionUnit,
|
||||
WeightUnit,
|
||||
)
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.manager.dataclasses import SetConfigData
|
||||
from wger.manager.models.abstract_config import (
|
||||
AbstractChangeConfig,
|
||||
@@ -59,7 +59,7 @@ class SlotConfig(models.Model):
|
||||
)
|
||||
|
||||
exercise = models.ForeignKey(
|
||||
ExerciseBase,
|
||||
Exercise,
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import datetime
|
||||
import logging
|
||||
|
||||
# Django
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.cache import cache
|
||||
from django.urls import (
|
||||
reverse,
|
||||
@@ -30,15 +29,9 @@ from wger.core.tests.base_testcase import (
|
||||
WgerDeleteTestCase,
|
||||
WgerTestCase,
|
||||
)
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.manager.models import (
|
||||
Workout,
|
||||
WorkoutLog,
|
||||
WorkoutSession,
|
||||
)
|
||||
from wger.manager.models import WorkoutLog
|
||||
from wger.utils.cache import cache_mapper
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
@@ -15,24 +15,22 @@
|
||||
# Standard Library
|
||||
import logging
|
||||
|
||||
# Third Party
|
||||
import requests
|
||||
# Django
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.cache import cache
|
||||
from django.shortcuts import render
|
||||
|
||||
# Third Party
|
||||
import requests
|
||||
|
||||
# wger
|
||||
from wger.core.forms import (
|
||||
RegistrationForm,
|
||||
RegistrationFormNoCaptcha,
|
||||
)
|
||||
from wger.exercises.models import ExerciseBase
|
||||
from wger.exercises.models import Exercise
|
||||
from wger.nutrition.models import Ingredient
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CACHE_KEY = 'landing-page-context'
|
||||
@@ -48,7 +46,7 @@ def features(request):
|
||||
result_github_api = requests.get('https://api.github.com/repos/wger-project/wger').json()
|
||||
context = {
|
||||
'nr_users': User.objects.count(),
|
||||
'nr_exercises': ExerciseBase.objects.count(),
|
||||
'nr_exercises': Exercise.objects.count(),
|
||||
'nr_ingredients': Ingredient.objects.count(),
|
||||
'nr_stars': result_github_api.get('stargazers_count', '2000'),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user