Как заставить сигнал работать, только если созданный пользователь находится в определенной группе c в Django? - PullRequest
0 голосов
/ 12 марта 2020

У меня есть модель Client, которая использует сигнал @receiver для обновления своих полей при каждом создании пользователя, поэтому он создает профиль Client.

class Client(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    address = models.CharField(max_length=200, verbose_name="Morada")
    city = models.CharField(max_length=200, verbose_name="Cidade")
    postal = models.CharField(max_length=8, validators=[RegexValidator(r'^\d{4}(-\d{3})?$')], verbose_name="Código Postal")
    nif = models.CharField(max_length=9, verbose_name="NIF", validators=[RegexValidator(r'^\d{1,10}$')], unique=True, null=True)
    mobile = models.CharField(max_length=9, verbose_name="Telemóvel", validators=[RegexValidator(r'^\d{1,10}$')])

    def __str__(self):
        return "%s %s" % (self.user.first_name, self.user.last_name)

    class Meta:
        verbose_name_plural = "Clientes"

    @receiver(post_save, sender=User)
    def update_user_profile(sender, instance, created, **kwargs):
        if created:
            Clients.objects.create(user=instance)
            instance.clients.save()

Существует ли способ только запустить это, если созданный пользователь принадлежит к группе клиентов? Потому что, если пользователь создается в группе «Сотрудники», я не хочу создавать профиль.

Это представление, которое создает клиента в группе «Клиенты»:

@login_required(login_url='./accounts/login/')
def signup(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            user = form.save()  # this creates the user with first_name, email and last_name as well!
            group = Group.objects.get(name='Clients')
            user.groups.add(group)
            user.refresh_from_db()  # load the profile instance created by the signal
            user.clients.address = form.cleaned_data.get('address')
            user.clients.city = form.cleaned_data.get('city')
            user.clients.postal = form.cleaned_data.get('postal')
            user.clients.nif = form.cleaned_data.get('nif')
            user.clients.mobile = form.cleaned_data.get('mobile')
            return redirect('clients')
    else:
        form = SignUpForm()
    return render(request, 'backend/new_client.html', {'form': form})

1 Ответ

1 голос
/ 12 марта 2020

Делаем это в виде (без сигнала):

@login_required(login_url='./accounts/login/')
def signup(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            user = form.save()  
            group = Group.objects.get(name='Clients')
            user.groups.add(group)
            client = Client.objects.create(
                user=user,
                address=form.cleaned_data.get('address')
                city=form.cleaned_data.get('city')
                postal=form.cleaned_data.get('postal')
                nif=form.cleaned_data.get('nif')
                mobile=form.cleaned_data.get('mobile')
            )
            return redirect('clients')
    else:
        form = SignUpForm()
    return render(request, 'backend/new_client.html', {'form': form})

Затем вы можете переместить весь код в user = form.save() в самой форме (я предполагаю, что это пользовательская ModelForm):

# forms.py

class SignUpForm(models.Form):

    # your existing code here

    def save(self):
       # NB if you're still using py2 you'll need
       # `user = super(SignUpForm, self).save()` instead
       user = super().save()
       group = Group.objects.get(name='Clients')
       user.groups.add(group)
       cleaned_data = self.cleaned_data
       client = Client.objects.create(
           user=user,
           address=cleaned_data.get('address')
           city=cleaned_data.get('city')
           postal=cleaned_data.get('postal')
           nif=cleaned_data.get('nif')
           mobile=cleaned_data.get('mobile')
       )
       return user

И ваше представление становится:

@login_required(login_url='./accounts/login/')
def signup(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            form.save()  
            return redirect('clients')
    else:
        form = SignUpForm()
    return render(request, 'backend/new_client.html', {'form': form})

Оба варианта верны и функционально эквивалентны, но второй вариант ИМХО более удобен в обслуживании - во-первых, потому что форму легче проверить, чем представление ( вам не нужно создавать объект запроса), а также потому, что он инкапсулирует целые доменные логики c в одном месте (форме) вместо того, чтобы разбрасывать его между формой и представлением. Единственным недостатком является то, что вы теряете возможность передавать commit=False arg на form.save(), но, поскольку эта форма, очевидно, не имеет никакой другой цели, вы все равно не будете использовать эту функцию.

...