Django форма: как получить данные в поле ManyToMany? - PullRequest
0 голосов
/ 27 апреля 2020

Моя цель состоит в том, чтобы реализовать те же функции, что и в админ-панели, со многими взаимосвязями. Кажется, все работает хорошо, но когда я отправляю свою форму, я получаю странные результаты: я, возможно, что-то упускаю, но не могу понять, что идет не так.

Пока что, когда я добавляю строки, все все в порядке. Проблемы возникают, когда я пытаюсь удалить строки из группы. Я рассуждаю о пользователях, у меня есть первый список «всех пользователей», а второй создаст группу. Когда у меня есть пользователь, затем удалите другого, форму нельзя проверить; список пуст, удаленный пользователь «исчезает» (его нет ни в списке групп, ни среди «всех пользователей». Если я удаляю одного пользователя, то добавляю нового, единственным пользователем в моей форме после проверки является тот, которого я добавлено, все остальные удалены.

Я надеюсь, что все ясно, заранее большое спасибо за ваш совет.

Вот соответствующие блоки кода.

Модели:

class UserComp(models.Model):
    """
    Link between users and companies
    Used to restrict display to companie(s) the users belong to
    """
    user = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name="Utilisateur")
    company = models.ForeignKey(Company, on_delete=models.CASCADE, verbose_name="Société")
    phone_regex = RegexValidator(regex=r'^0[0-9]([ .-]?[0-9]{2}){4}$', message=("Format de numéro de téléphone invalide"))
    phone_num = models.CharField("numéro de téléphone", validators=[phone_regex], max_length=14, null=True, blank=True)
    is_admin = models.BooleanField("administrateur", default=False)

class EventGroup(models.Model):
    """
    Groups of users
    The link with events is supported by the Event
    (as groups can be reused in several Events)
    """
    company = models.ForeignKey(
        Company, on_delete=models.CASCADE, verbose_name="société"
    )
    users = models.ManyToManyField(UserComp, verbose_name="utilisateurs", blank=True)
    group_name = models.CharField("nom", max_length=100)
    weight = models.IntegerField("poids", default=0)

Форма:

class GroupDetail(forms.ModelForm):
    users = forms.ModelMultipleChoiceField(
        label="Dans le groupe",
        queryset=None,
        widget=forms.SelectMultiple,
        required=False
        )
    all_users = forms.ModelMultipleChoiceField(
        label="Utilisateurs",
        queryset=None,
        widget=forms.SelectMultiple,
        required=False
        )

    class Meta:
        model = EventGroup
        fields = ['group_name', 'weight', 'all_users', 'users']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        instance = kwargs.get('instance', None)
        if instance is not None:
            # Users to be selected : all users except the ones already in group
            self.fields['all_users'].queryset= UserComp.objects.\
                                                        filter(company=instance.company).\
                                                        exclude(eventgroup=instance).\
                                                        order_by('user__last_name', 'user__first_name')
            # Current users in group
            self.fields['users'].queryset = instance.users.all().\
                                                     order_by('user__last_name', 'user__first_name')

Представление:

def GroupInfo(request, pk):
    current_group = EventGroup.objects.get(id=pk)
    group_form = GroupDetail(request.POST or None, instance=current_group)

    if request.method == 'POST':
        # Values are string and need to be converted to integers to match IDs
        usr_list = [int(elt) for elt in request.POST.getlist('users')]
        group_form.fields['users'].queryset = UserComp.objects.filter(id__in=usr_list)
        if group_form.is_valid():
            new_group.save()
        else:
            # For testing purposes
            print(group_form.errors)

    return render(request, "polls/group_info.html", locals())

Чтобы переместить пользователя из одного списка (фактически выберите несколько объектов HTML), У меня есть такой код js (функция, вызываемая один раз или в течение всего oop при двойном щелчке, перемещении выбранных элементов (1 или нескольких) или перемещении всех элементов):

let new_option = new Option($(this).text(), $(this).val())
$('#id_dest').append(new_option);
$(this).remove();

РЕДАКТИРОВАТЬ Я внес некоторые изменения, моя проблема определенно состоит в удалении пользователей из группы. Я обновил свое представление, чтобы создать новый список пользователей в группе (текущие пользователи + добавляемые пользователи - пользователи удалить) и добавьте al oop, чтобы добавить каждого пользователя:

def GroupInfo(request, pk):
    current_group = EventGroup.objects.get(id=pk)
    list_users = [elt.id for elt in current_group.users.all()]
    group_form = GroupDetail(request.POST or None, instance=current_group)

    if request.method == 'POST':
        usr_list = [elt.id for elt in current_group.users.all() if elt not in request.POST.getlist('all_users')]
        usr_list += [int(elt) for elt in request.POST.getlist('users')]
        group_form.fields['users'].queryset = UserComp.objects.filter(id__in=usr_list)

        if group_form.is_valid():
            new_group = group_form.save()
            for usr in usr_list:
                new_group.users.add(usr)
            new_group.save()
        else:
            print(group_form.errors)

    return render(request, "polls/group_info.html", locals())

На лицевой стороне я сделал 2 теста: 1. Выберите все строки в части «группа» перед отправкой: я должен получить исчерпывающий список пользователей в группе и построить его из этого списка 2. Выберите только изменения, новых пользователей в списке «группы», пользователей, которых нужно удалить в списке «всех_пользователей». Так или иначе, когда я удаляю пользователя из группы, он не передается и все еще находится в группе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...