Django save() method executed twice

Viewed 36

I,m developing a simple CRUD app. There are two main models: empleado (employee) and oficina (office or department). Each "empleado" belongs to a "oficina"

class empleado(models.Model):
"""Model definition for empleado."""

  apellidos = models.CharField('Apellidos', max_length=50, blank=False)
  nombres = models.CharField('Nombres', max_length=50, blank=False)
  full_name = models.CharField('Nombre completo', max_length=50, blank=True)
  dni = models.CharField('DNI', max_length=50, blank=False, unique=True)
  habilidades = models.ManyToManyField(habilidad, blank=False)
  area = models.ForeignKey(oficina, on_delete=models.CASCADE, blank=False, related_name = 'area_empleado')

The model for "oficina" has a field called "personal" that stores the number of employees in that department

class oficina(models.Model):
"""Model definition for oficina."""

  nombre = models.CharField('Nombre', max_length=50)
  nombre_corto = models.CharField('Nombre corto', max_length=50)
  personal = models.PositiveIntegerField(default = 0)

I used generic views to create new employees

class EmpleadoCreateView(CreateView):
  model = empleado
  template_name = "empleado/create.html"
  form_class = EmpleadoForm
  success_url = reverse_lazy('empleado_app:Lista de empleados') 

  def form_valid(self, form):
      emp = form.save(commit=False)
      emp.full_name = emp.nombres + ' ' + emp.apellidos
      emp.save()
      return super(EmpleadoCreateView, self).form_valid(form)

This is the EmpleadoForm class:

class EmpleadoForm(forms.ModelForm):
  """Form definition for Empleado."""

  class Meta:
      """Meta definition for Empleadoform."""

    model = empleado
    fields = ('apellidos',
                'nombres',
                'dni',
                'habilidades',
                'area',       
    )
    widgets ={
        'habilidades' : forms.CheckboxSelectMultiple()
    

In order to keep the number of employees updated, I use a couple of signals (for the "empleado" model):

def update_personal_dec(sender, instance, **kwargs):    
  instance.area.personal -= 1
  instance.area.save()

def update_personal_inc(sender, instance, **kwargs):    
  instance.area.personal += 1
  instance.area.save()

post_delete.connect(update_personal_dec, sender=empleado)
post_save.connect(update_personal_inc, sender=empleado)

When I delete an employee, everything works fine. However, when I create a new employee, it increases twice the number of employees (i.e. if a department has 7 employees (oficina.personal = 7), after I add one it has 9 (oficina.personal = 9)).

Any suggestions?

Thanks a lot!!!

1 Answers

The problem is in form_valid(). More precisely

emp.save()
return super(EmpleadoCreateView, self).form_valid(form)

In emp.save() OP is saving once. Then, return super().form_valid(form) saves again if the form is valid (which is the case when it creates twice).

I see OP is not including full_name in the list of fields. Now what OP only needs to do is simply override form_valid() to add full_name

def form_valid(self, form):
      form.instance.full_name = emp.nombres + ' ' + emp.apellidos
      return super(EmpleadoCreateView, self).form_valid(form)
Related