Reputation: 625
I have a model Client
which uses a @receiver signal to update its fields whenever a User is created, so it creates a Client
profile.
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()
Is there a way to only run this if the user created belongs to the Clients group? Because if a user is created in the Employees group, I don't want to create a profile.
This is the view that creates the Client in the Clients group:
@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})
Upvotes: 0
Views: 65
Reputation: 77912
Doing it in the view (without signal):
@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})
Then you can choose to move all the code under user = form.save()
in the form's itself (I assume it's a custom 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
And your view becomes:
@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})
Both options are correct and functionnaly equivalent, but the second one is IMHO more maintainable - first because a form is easier to test than a view (you don't need to create a request object), and also because it encapsulate the whole domain logic in the same place (the form) instead of scattering it between the form and the view. The only downside is that you loose the ability to pass the commit=False
arg to form.save()
, but since this form has obviously no other purpose you wouldn't use this feature anyway.
Upvotes: 1