<commit_before>from crispy_forms.layout import Div
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _
from geotrek.common.forms import CommonForm
from geotrek.outdoor.models import RatingScale, Site, Course, OrderedCourseChild


class SiteForm(CommonForm):
    orientation = forms.MultipleChoiceField(choices=Site.ORIENTATION_CHOICES, required=False)
    wind = forms.MultipleChoiceField(choices=Site.ORIENTATION_CHOICES, required=False)

    geomfields = ['geom']

    fieldslayout = [
        Div(
            'structure',
            'name',
            'parent',
            'review',
            'published',
            'practice',
            'type',
            'description_teaser',
            'ambiance',
            'description',
            'advice',
            'period',
            'orientation',
            'wind',
            'labels',
            'themes',
            'information_desks',
            'web_links',
            'portal',
            'source',
            'pois_excluded',
            'managers',
            'eid',
        )
    ]

    class Meta:
        fields = ['geom', 'structure', 'name', 'review', 'published', 'practice', 'description',
                  'description_teaser', 'ambiance', 'advice', 'period', 'labels', 'themes',
                  'portal', 'source', 'information_desks', 'web_links', 'type', 'parent', 'eid',
                  'orientation', 'wind', 'managers', 'pois_excluded']
        model = Site

    def __init__(self, site=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['parent'].initial = site
        if self.instance.pk:
            descendants = self.instance.get_descendants(include_self=True).values_list('pk', flat=True)
            self.fields['parent'].queryset = Site.objects.exclude(pk__in=descendants)
        for scale in RatingScale.objects.all():
            ratings = None
            if self.instance.pk:
                ratings = self.instance.ratings.filter(scale=scale)
            fieldname = 'rating_scale_{}'.format(scale.pk)
            self.fields[fieldname] = forms.ModelMultipleChoiceField(
                label=scale.name,
                queryset=scale.ratings.all(),
                required=False,
                initial=ratings if ratings else None
            )
            self.fieldslayout[0].insert(7, fieldname)
        if self.instance.pk:
            self.fields['pois_excluded'].queryset = self.instance.all_pois.all()
        else:
            self.fieldslayout[0].remove('pois_excluded')

    def save(self, *args, **kwargs):
        site = super().save(self, *args, **kwargs)

        # Save ratings
        if site.practice:
            field = getattr(site, 'ratings')
            to_remove = list(field.exclude(scale__practice=site.practice).values_list('pk', flat=True))
            to_add = []
            for scale in site.practice.rating_scales.all():
                ratings = self.cleaned_data.get('rating_scale_{}'.format(scale.pk))
                needs_removal = field.filter(scale=scale)
                if ratings is not None:
                    for rating in ratings:
                        needs_removal = needs_removal.exclude(pk=rating.pk)
                        to_add.append(rating.pk)
                to_remove += list(needs_removal.values_list('pk', flat=True))
            field.remove(*to_remove)
            field.add(*to_add)

        return site


class CourseForm(CommonForm):
    children_course = forms.ModelMultipleChoiceField(label=_("Children"),
                                                     queryset=Course.objects.all(), required=False,
                                                     help_text=_("Select children in order"))
    hidden_ordered_children = forms.CharField(label=_("Hidden ordered children"),
                                              widget=forms.widgets.HiddenInput(),
                                              required=False)

    geomfields = ['geom']

    fieldslayout = [
        Div(
            'structure',
            'name',
            'site',
            'type',
            'review',
            'published',
            'description',
            'ratings_description',
            'duration',
            'advice',
            'equipment',
            'gear',
            'height',
            'pois_excluded',
            'children_course',
            'eid',
            'hidden_ordered_children',
        )
    ]

    class Meta:
        fields = ['geom', 'structure', 'name', 'site', 'type', 'review', 'published', 'description', 'ratings_description', 'duration', 'pois_excluded',
                  'advice', 'gear', 'equipment', 'height', 'eid', 'children_course', 'hidden_ordered_children']
        model = Course

    def __init__(self, site=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['site'].initial = site
        self.fields['duration'].widget.attrs['min'] = '0'
        for scale in RatingScale.objects.all():
            ratings = None
            if self.instance.pk and self.instance.site and self.instance.site.practice:
                ratings = self.instance.ratings.filter(scale=scale)
            fieldname = 'rating_scale_{}'.format(scale.pk)
            self.fields[fieldname] = forms.ModelChoiceField(
                label=scale.name,
                queryset=scale.ratings.all(),
                required=False,
                initial=ratings[0] if ratings else None
            )
            self.fieldslayout[0].insert(3, fieldname)
        if self.instance:
            queryset_children = OrderedCourseChild.objects.filter(parent__id=self.instance.pk).order_by('order')
            # init multiple children field with data
            self.fields['children_course'].queryset = Course.objects.exclude(pk=self.instance.pk)
            self.fields['children_course'].initial = [c.child.pk for c in self.instance.course_children.all()]
            # init hidden field with children order
            self.fields['hidden_ordered_children'].initial = ",".join(str(x) for x in queryset_children.values_list('child__id', flat=True))
        if self.instance.pk:
            self.fields['pois_excluded'].queryset = self.instance.all_pois.all()
        else:
            self.fieldslayout[0].remove('pois_excluded')
<commit_msg>Fix dynamic forms on outdoor cotations always displayed after practice and type<commit_after>from crispy_forms.layout import Div
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _
from geotrek.common.forms import CommonForm
from geotrek.outdoor.models import RatingScale, Site, Course, OrderedCourseChild


class SiteForm(CommonForm):
    orientation = forms.MultipleChoiceField(choices=Site.ORIENTATION_CHOICES, required=False)
    wind = forms.MultipleChoiceField(choices=Site.ORIENTATION_CHOICES, required=False)

    geomfields = ['geom']

    fieldslayout = [
        Div(
            'structure',
            'name',
            'parent',
            'review',
            'published',
            'practice',
            'type',
            'description_teaser',
            'ambiance',
            'description',
            'advice',
            'period',
            'orientation',
            'wind',
            'labels',
            'themes',
            'information_desks',
            'web_links',
            'portal',
            'source',
            'pois_excluded',
            'managers',
            'eid',
        )
    ]

    class Meta:
        fields = ['geom', 'structure', 'name', 'review', 'published', 'practice', 'description',
                  'description_teaser', 'ambiance', 'advice', 'period', 'labels', 'themes',
                  'portal', 'source', 'information_desks', 'web_links', 'type', 'parent', 'eid',
                  'orientation', 'wind', 'managers', 'pois_excluded']
        model = Site

    def __init__(self, site=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['parent'].initial = site
        if self.instance.pk:
            descendants = self.instance.get_descendants(include_self=True).values_list('pk', flat=True)
            self.fields['parent'].queryset = Site.objects.exclude(pk__in=descendants)
        for scale in RatingScale.objects.all():
            ratings = None
            if self.instance.pk:
                ratings = self.instance.ratings.filter(scale=scale)
            fieldname = 'rating_scale_{}'.format(scale.pk)
            self.fields[fieldname] = forms.ModelMultipleChoiceField(
                label=scale.name,
                queryset=scale.ratings.all(),
                required=False,
                initial=ratings if ratings else None
            )
            right_after_type_index = self.fieldslayout[0].fields.index('type') + 1
            self.fieldslayout[0].insert(right_after_type_index, fieldname)
        if self.instance.pk:
            self.fields['pois_excluded'].queryset = self.instance.all_pois.all()
        else:
            self.fieldslayout[0].remove('pois_excluded')

    def save(self, *args, **kwargs):
        site = super().save(self, *args, **kwargs)

        # Save ratings
        if site.practice:
            field = getattr(site, 'ratings')
            to_remove = list(field.exclude(scale__practice=site.practice).values_list('pk', flat=True))
            to_add = []
            for scale in site.practice.rating_scales.all():
                ratings = self.cleaned_data.get('rating_scale_{}'.format(scale.pk))
                needs_removal = field.filter(scale=scale)
                if ratings is not None:
                    for rating in ratings:
                        needs_removal = needs_removal.exclude(pk=rating.pk)
                        to_add.append(rating.pk)
                to_remove += list(needs_removal.values_list('pk', flat=True))
            field.remove(*to_remove)
            field.add(*to_add)

        return site


class CourseForm(CommonForm):
    children_course = forms.ModelMultipleChoiceField(label=_("Children"),
                                                     queryset=Course.objects.all(), required=False,
                                                     help_text=_("Select children in order"))
    hidden_ordered_children = forms.CharField(label=_("Hidden ordered children"),
                                              widget=forms.widgets.HiddenInput(),
                                              required=False)

    geomfields = ['geom']

    fieldslayout = [
        Div(
            'structure',
            'name',
            'site',
            'type',
            'review',
            'published',
            'description',
            'ratings_description',
            'duration',
            'advice',
            'equipment',
            'gear',
            'height',
            'pois_excluded',
            'children_course',
            'eid',
            'hidden_ordered_children',
        )
    ]

    class Meta:
        fields = ['geom', 'structure', 'name', 'site', 'type', 'review', 'published', 'description', 'ratings_description', 'duration', 'pois_excluded',
                  'advice', 'gear', 'equipment', 'height', 'eid', 'children_course', 'hidden_ordered_children']
        model = Course

    def __init__(self, site=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['site'].initial = site
        self.fields['duration'].widget.attrs['min'] = '0'
        for scale in RatingScale.objects.all():
            ratings = None
            if self.instance.pk and self.instance.site and self.instance.site.practice:
                ratings = self.instance.ratings.filter(scale=scale)
            fieldname = 'rating_scale_{}'.format(scale.pk)
            self.fields[fieldname] = forms.ModelChoiceField(
                label=scale.name,
                queryset=scale.ratings.all(),
                required=False,
                initial=ratings[0] if ratings else None
            )
            right_after_type_index = self.fieldslayout[0].fields.index('type') + 1
            self.fieldslayout[0].insert(right_after_type_index, fieldname)
        if self.instance:
            queryset_children = OrderedCourseChild.objects.filter(parent__id=self.instance.pk).order_by('order')
            # init multiple children field with data
            self.fields['children_course'].queryset = Course.objects.exclude(pk=self.instance.pk)
            self.fields['children_course'].initial = [c.child.pk for c in self.instance.course_children.all()]
            # init hidden field with children order
            self.fields['hidden_ordered_children'].initial = ",".join(str(x) for x in queryset_children.values_list('child__id', flat=True))
        if self.instance.pk:
            self.fields['pois_excluded'].queryset = self.instance.all_pois.all()
        else:
            self.fieldslayout[0].remove('pois_excluded')

{'fraction_non_alphanumeric': 0.1196515892420538, 'fraction_numerical': 0.0013753056234718827, 'mean_word_length': 1.96131221719457, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1746041', 'n_tokens_mistral': 3561, 'n_tokens_neox': 3456, 'n_words': 657}