Guardar un registro para un model con relacion many-to-many

200 views
Skip to first unread message

Jhon Vargas

unread,
Oct 17, 2017, 6:44:17 PM10/17/17
to Django-es
Hola, estoy intentando crear un metodo para guardar un nuevo registro de alquiler, primeramente lo hice con el Generic AlquilerCreate y lo guarda sin problemas.
pero estoy haciendo mi propio metodo porque necesito enviarle el usuario sin necesidad de ponerlo en el formulario, ademas al campo hora inicio y hora fin calcularlo con respecto a lo que seleccionen en el Select. 

Obtengo el error:
Exception Value:
"<Alquiler: Alquiler object>" needs to have a value for field "id" before this many-to-many relationship can be used.

Tengo el proyecto en Github si quieren hecharle un vistazo


Espero su ayuda
Gracias de antemano!


ESTOS SON MIS MODELOS

class Vehiculo(models.Model):

    placa = models.CharField(primary_key=True,max_length=100)
    descripcion = models.CharField(max_length=100)
    marca = models.CharField(max_length=100)
    modelo = models.CharField(max_length=100)
    cilindrada = models.CharField(max_length=100)
    tipo = models.ForeignKey(Tipo)
    km_recorrido = models.DecimalField(max_digits=20,decimal_places=2,default=Decimal('0.00'))
    activo = models.BooleanField(default=True)
    def __str__(self):
        return self.descripcion


class Alquiler(models.Model):

    fecha = models.DateTimeField(auto_now_add = timezone.now())
    hora_inicio = models.TimeField()
    hora_fin = models.TimeField()
    cajero = models.ForeignKey(User)
    cliente = models.ForeignKey(Cliente)
    vehiculos = models.ManyToManyField(Vehiculo)
    class Meta:
        permissions = (
            ("add_alquileres", "Puede crear Alquileres"),
        )
    def __int__(self):
        return self.cliente
    def motos(self):
        return ', '.join([Vehiculo.descripcion for Vehiculo in self.vehiculos.all()])


ESTE ES MI FORMULARIO

TIEMPO = (
    ('15 MINUTOS','15 MINUTOS'),
    ('30 MINUTOS','30 MINUTOS'),
    ('1 HORA','1 HORAS'),
    ('2 HORAS','2 HORAS'),
)

class AlquilerForm(forms.ModelForm):

    tiempo = forms.CharField(widget=forms.Select(choices=TIEMPO, attrs={'class': 'form-control'}))

    class Meta:
        model = Alquiler
        fields = ('cliente','tiempo','vehiculos')
        widgets = {
            'cliente': forms.Select(attrs={'class': 'form-control'}),
            'vehiculos': forms.SelectMultiple(attrs={'class': 'form-control'}),
        }


Y ESTA ES MI VISTA

def Alquiler_crear(request):

    if request.method == 'POST':
        alquiler = Alquiler()
        cajero = request.user.username
        cliente = request.POST.get('cliente')
        vehiculos = request.POST.get('vehiculos')
        user_model = User()
        user_model.username = cajero
        cliente_model = Cliente()
        cliente_model.nombre = cliente
        alquiler.cajero = user_model
        alquiler.cliente =  cliente_model
        alquiler.vehiculos = vehiculos
        alquiler.save()
        messages.success(request, 'Alquiler creado.')
        return redirect(reverse_lazy('alquiler:alquiler_list'))
    else:
        form = AlquilerForm()
        context = {'form': form}
        return render(request, 'alquiler/alquiler_form.html',context)

Francisco Pandol

unread,
Oct 18, 2017, 7:43:19 AM10/18/17
to djan...@googlegroups.com
Yo creo que el problema es que no estás guardando los objetos de tipo vehiculos antes de agregarlos en la relación m2m de alquiler.
https://docs.djangoproject.com/en/1.11/topics/db/examples/many_to_many/

--
--
Ha recibido este mensaje porque está suscrito a Grupo "Grupo de Usuarios del Framework Django de habla hispana" de Grupos de Google.
Si quieres publicar en este grupo, envía un mensaje de correo
electrónico a djan...@googlegroups.com
Para anular la suscripción a este grupo, envíe un mensaje a django-es-unsubscribe@googlegroups.com
Para obtener más opciones, visita este grupo en http://groups.google.com.bo/group/django-es.
---
Has recibido este mensaje porque estás suscrito al grupo "Django-es" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a django-es+unsubscribe@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
Francisco Pandol

Jhon Vargas

unread,
Oct 19, 2017, 12:13:35 AM10/19/17
to Django-es
Viendo la documentacion que compartiste conmigo, no estoy creando el alquiler antes de de agregarles los objetos de tipo vehiculos como lo dice en la documentacion, tratare de aplicarlo
Gracias por la ayuda
Saludos!

Jhon Vargas

unread,
Oct 19, 2017, 1:07:48 AM10/19/17
to djan...@googlegroups.com
Bueno ahora que he aplicado eso me surge otro error
save() prohibited to prevent data loss due to unsaved related object 'cajero'.

crei que el request.user que le estaba enviando era el problema pero he cambiado mi form y mi view para que obtenga el usuario desde el formulario y tampoco lo he conseguido

Tengo el proyecto en Github si quieren hecharle un vistazo


TIEMPO = (
('15 MINUTOS','15 MINUTOS'),
('30 MINUTOS','30 MINUTOS'),
('1 HORA','1 HORAS'),
('2 HORAS','2 HORAS'),
)

class AlquilerForm(forms.ModelForm):

tiempo = forms.CharField(widget=forms.Select(choices=TIEMPO, attrs={'class': 'form-control'}))

class Meta:
model = Alquiler
        fields = ('cliente','cajero','tiempo','vehiculos')

widgets = {
'cliente': forms.Select(attrs={'class': 'form-control'}),
            'cajero': forms.Select(attrs={'class': 'form-control'}),
            'vehiculos': forms.SelectMultiple(attrs={'class': 'form-control'}),
}
def Alquiler_crear(request):

if request.method == 'POST':
alquiler = Alquiler()
        cajero = request.POST.get('cajero')

cliente = request.POST.get('cliente')
vehiculos = request.POST.get('vehiculos')
user_model = User()
user_model.username = cajero
cliente_model = Cliente()
cliente_model.nombre = cliente
        alquiler.hora_inicio = "00:00"
alquiler.hora_fin = "00:00"
        alquiler.cajero = user_model
alquiler.cliente = cliente_model
        alquiler.save()
alquiler.vehiculos = vehiculos

messages.success(request, 'Alquiler creado.')
return redirect(reverse_lazy('alquiler:alquiler_list'))
else:
form = AlquilerForm()
context = {'form': form}
return render(request, 'alquiler/alquiler_form.html',context)


Libre de virus. www.avast.com

--
--
Ha recibido este mensaje porque está suscrito a Grupo "Grupo de Usuarios del Framework Django de habla hispana" de Grupos de Google.
Si quieres publicar en este grupo, envía un mensaje de correo
electrónico a djan...@googlegroups.com
Para anular la suscripción a este grupo, envíe un mensaje a django-es-unsubscribe@googlegroups.com
Para obtener más opciones, visita este grupo en http://groups.google.com.bo/group/django-es.
---
Has recibido este mensaje porque estás suscrito a un tema del grupo "Django-es" de Grupos de Google.
Para cancelar la suscripción a este tema, visita https://groups.google.com/d/topic/django-es/rfG2eKavg2k/unsubscribe.
Para cancelar la suscripción a este grupo y a todos sus temas, envía un correo electrónico a django-es+unsubscribe@googlegroups.com.

Jhónatan Mosquera

unread,
Oct 19, 2017, 10:12:26 AM10/19/17
to djan...@googlegroups.com
No estas usando los datos del POST, lo que haces en user_model=User() es instanciar un nuevo objecto de tipo cliente y no seleccionar uno ya creado,  intenta asi:
------------------------------------------------
AlquilerMotos/apps/Alquiler/views.py
------------------------------------------------
# importa esto en el inicio
from datetime import datetime, timedelta
from .forms import AlquilerCreateForm
...
# reemplaza tu vista

def Alquiler_crear(request):
    if request.method == 'POST':
        POST = request.POST.copy()
        POST['cajero'] = request.user.id
        inicio = datetime.strptime(POST['hora_inicio'], "%H:%M")
        fin = inicio + timedelta(minutes = int(POST['tiempo']))
        hora_fin = "%s:%s"%(fin.hour, fin.minute)
        POST['hora_fin'] = hora_fin
        form = AlquilerCreateForm(POST)
        if form.is_valid():
            form.save()
            messages.success(request, 'Alquiler creado.')
            return redirect(reverse_lazy('alquiler:alquiler_list'))
        else:
            messages.error(request, 'Verifique la informacion.')
            form = AlquilerForm(POST)
            context = {'form': form}
            return render(request, 'alquiler/alquiler_form.html',context)
    else:
        form = AlquilerForm()
        context = {'form': form}
        return render(request, 'alquiler/alquiler_form.html',context)

------------------------------------------------
AlquilerMotos/apps/Alquiler/forms.py
------------------------------------------------
...
#reemplaza tu choices TIEMPO y formulario AlquilerForm, añade el form AlquilerCreateForm
TIEMPO = (
    ('15','15 MINUTOS'),
    ('30','30 MINUTOS'),
    ('60','1 HORAS'),
    ('120','2 HORAS'),
)

class AlquilerForm(forms.ModelForm):
    tiempo = forms.CharField(widget=forms.Select(choices=TIEMPO, attrs={'class': 'form-control'}))
    class Meta:
        model = Alquiler
        fields = ( 'cliente','tiempo', 'hora_inicio','vehiculos')
        widgets = {
            'hora_inicio': forms.TimeInput(attrs={'class': 'form-control','placeholder':'ingrese en formato 00:00'},format="00:00"),
            # 'hora_fin': forms.TimeInput(attrs={'class': 'form-control'},format="00:00:00"),
            # 'cajero': forms.Select(attrs={'class': 'form-control'}),
            'cliente': forms.Select(attrs={'class': 'form-control'}),
            'vehiculos': forms.SelectMultiple(attrs={'class': 'form-control'}),
        }

class AlquilerCreateForm(forms.ModelForm):
    class Meta:
        model = Alquiler
        fields = ( 'cajero', 'cliente', 'hora_inicio', 'hora_fin','vehiculos')

Has recibido este mensaje porque estás suscrito al grupo "Django-es" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a django-es+unsubscribe@googlegroups.com.

Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
----
Jhónatan Mosquera Tabra
Reply all
Reply to author
Forward
0 new messages