Django and related_name - django

first im so sorry with my english, im new with Django, im from php + codeigniter.
I have a problem with a related_name, the tables are fine, but the problem is that in the Select (DropDown) the data display is "bad", in this way: Tarifas_object:
Html code:
<option value="1">Tarifas object</option>
how ill display the correct data?
my model:
class Tarifas(models.Model):
recarga = models.CharField(max_length=7, help_text='Codigo de la tarifa')
precio = models.DecimalField(max_digits=7, decimal_places=2)
diligencias = models.PositiveIntegerField(max_length=3)
def __inicode__(self):
return self.precio
class Meta:
verbose_name_plural="Tarifas"
class Recarga(models.Model):
socio = models.ForeignKey(User)
fecha = models.DateField(auto_now_add=True)
#valor = models.DecimalField(max_digits=6, decimal_places=2,verbose_name='Valor de la recarga', help_text= "Introduzca valores numericos ej.: 150.00")
valor = models.ForeignKey(Tarifas, related_name='recarga_valor')
diligencias = models.IntegerField(max_length=3, verbose_name='Cantidad de diligencias recargadas')
tiponcf = models.IntegerField(max_length=1,choices=TIPO_NCF, verbose_name='Tipo de comprobante fiscal')
ncf = models.CharField(max_length=19,verbose_name='Numero de comprobante fiscal')
cajero = models.CharField(max_length=20)
tipotarj = models.CharField(choices=TIPOS_TARJETAS, max_length=20, verbose_name='Tipo de tarjeta')
numtarj = models.IntegerField(max_length=16, verbose_name='Numero de tarjeta')
seguridad = models.IntegerField(max_length=3)
forma_pago = models.CharField(max_length=10, verbose_name='Forma de pago')
banco = models.CharField(max_length=20)
numerock = models.IntegerField(max_length=8, verbose_name='Numero de cheque')
def __unicode__(self):
return u'%s %s %s %s' % (self.socio,self.diligencias, self.fecha)
class Meta:
ordering = ['socio']
Thanks guys.

If that's the straight copy and paste from your model, you've misspelled unicode on the Tarifas model.

Related

Ways to change dropdown choices in django-filter

I'm trying to change the dropdown values for the user field. I want to show the email addreses , instead of the nombre + apellido. Because in my models I have the str that returns nombre + apellido, those are the values displayed in the dropdown. How can I change those values without changing the str in the Tutor model? Tryed to do a CustomManager but didn't work.
MODEL:
class Tutor(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, primary_key=True)
nombre = models.CharField(max_length=50, blank=False, null=True)
apellido = models.CharField(max_length=50, blank=False, null=True)
biografia = models.TextField()
curriculum = models.FileField(upload_to="curriculums/", blank=True, null=True)
foto = models.ImageField(blank=True, null=True)
carrera = models.ManyToManyField(Carrera, blank=True)
linea_invest = models.ManyToManyField(Linea_Invest, blank=True)
correo = models.EmailField(blank=True, null=True)
numero_celular = models.CharField(max_length=20, blank=True, null=True)
class Meta:
verbose_name_plural = "Tutores"
verbose_name = "Tutor"
def __str__(self):
return '%s %s' % (self.nombre, self.apellido)
FILTER
class TutorFilter(django_filters.FilterSet):
nombre = CharFilter(field_name="nombre", label="Nombre",lookup_expr='icontains')
apellido = CharFilter(field_name="apellido", label="Apellido",lookup_expr='icontains')
carrera = ModelMultipleChoiceFilter(field_name= "carrera", queryset= Carrera.objects.all())
user = ModelChoiceFilter(field_name = "user", label = "correo", queryset = Tutor.objects.all())
class Meta:
model = Tutor
fields = ("nombre", "apellido", "carrera","user")
In your TutorFilter. Change
user = ModelChoiceFilter(field_name = "user", label = "correo", queryset = user.objects.all())
How I solved:
def get_tutores():
tutores = []
for tut in Tutor.objects.all():
tutores.append((tut.user.id,tut.user.email,))
return tutores
class TutorFilter(django_filters.FilterSet):
nombre = CharFilter(field_name="nombre", label="Nombre",lookup_expr='icontains')
apellido = CharFilter(field_name="apellido", label="Apellido",lookup_expr='icontains')
carrera = ModelMultipleChoiceFilter(field_name= "carrera", queryset= Carrera.objects.all())
user = ChoiceFilter( label = "correo", choices=get_tutores())
class Meta:
model = Tutor
fields = ("nombre", "apellido", "carrera","user")
See how I didn't need to change the str method in the model Tutor to display in the dropdown the tutor's emails as choices, because instead of using ModelChoiceFilter I changed to ChoiceFilter . Didn't know that you can call a function in the choices argument in the ChoiceFilter.

Django: BooleanField return 'on' instead of true?

I have a BooleanField (ran_bug) in my Randomisation models that is displayed as a checkbox.
Click on the checkbox sould show 2 other fields that are not mandatory (ran_dem_nom and ran_dem_dat).
My problem is that, when I 'check' the checkbox, it return 'on' instead of true.
And I got an error when I try to registered data:
django.core.exceptions.ValidationError: ["'on' value must be either True, False, or None."]
models.py
class Randomisation(models.Model):
ran_ide = models.AutoField(primary_key=True)
pay_ide = models.ForeignKey(Pays, on_delete = models.CASCADE) # related country
ran_str_num = models.CharField("Logical numerotation", max_length=2, null=True, blank=True)
ran_bra = models.CharField("Arm", max_length=1, null=True, blank=True)
bra_lib = models.CharField("Arm label", max_length=50, null=True, blank=True)
ran_act = models.IntegerField("Activated line", null=True, blank=True)
pat = models.CharField("Patient number", max_length=12, unique=True, null=True, blank=True)
ran_nai = models.IntegerField("Patient birthdate (year)", blank=True)
ran_sex = models.IntegerField("Sex", null=True, blank=True)
ran_st1 = models.IntegerField("Stratification variable 1", blank=True)
ran_st2 = models.IntegerField("Stratification variable 2", blank=True)
ran_bug = models.BooleanField("Use of alternative randomization procedure?", null=True, blank=True)
ran_dem_nom = models.CharField("Name of the person asking for randomization", max_length=12, null=True, blank=True) # hide at pageload
ran_dem_dat = models.DateField("Date of demand", null=True, blank=True) # hide at pageload
ran_log = models.CharField("User", max_length=12, null=True, blank=True)
ran_dat = models.DateTimeField("Date", null=True, auto_now_add=True, blank=True)
forms.py
class RandomizationEditForm(forms.Form):
def __init__(self, request, *args, **kwargs):
super(RandomizationEditForm, self).__init__(*args, **kwargs)
self.user_country = Pays.objects.get(pay_ide = request.session.get('user_country'))
self.user_site_type = request.session.get('user_site_type')
PAYS = Pays.options_list(self.user_country,self.user_site_type,'fr')
SEXE = Thesaurus.options_list(2,'fr')
STRATE_1 = Thesaurus.options_list(3,'fr')
STRATE_2 = Thesaurus.options_list(4,'fr')
YES = [(None,''),(0,'Non'),(1,'Oui'),]
self.fields["pay_ide"] = forms.IntegerField(label = "Pays", initial=2, widget=forms.HiddenInput())
self.fields["pat"] = forms.CharField(label = "Numéro patient (XXX-0000)")
self.fields['pat'].widget.attrs.update({
'autocomplete': 'off'
})
self.fields["ran_nai"] = forms.IntegerField(label = "Date de naissance (année)", widget=forms.TextInput)
self.fields['ran_nai'].widget.attrs.update({
'autocomplete': 'off'
})
self.fields["ran_sex"] = forms.ChoiceField(label = "Sexe", widget=forms.Select, choices=SEXE)
self.fields["ran_st1"] = forms.ChoiceField(label = "Gravité de la maladie COVID-19", widget=forms.Select, choices=STRATE_1)
self.fields["ran_bug"] = forms.BooleanField(label = "Recours à la procédure de secours ?", required = False)
self.fields["ran_dem_nom"] = forms.CharField(label = "Nom de la personne qui demande la randomisation", required = False)
self.fields['ran_dem_nom'].widget.attrs.update({
'autocomplete': 'off'
})
self.fields["ran_dem_dat"] = forms.DateField(
# input_formats=settings.DATE_INPUT_FORMATS,
label = "Date de la demande",
initial = timezone.now(),
required = False,
)
self.fields['ran_dem_dat'].widget.attrs.update({
'autocomplete': 'off'
})
JS
$(function(){
$("#div_id_ran_dem_nom").hide();
$("#div_id_ran_dem_dat").hide();
});
// affichage des champs en fonction de la valeur sélectionnée dans la liste
$("#div_id_ran_bug").on("change", function(event){
console.log($("#id_ran_bug").val())
if ($("#id_ran_bug").is(":checked")){
$("#div_id_ran_dem_nom").show();
$("#div_id_ran_dem_dat").show();
}
else {
$("#div_id_ran_dem_nom").hide();
$("#div_id_ran_dem_dat").hide();
}
});
views.py
def randomization_edit(request):
if request.method == "POST":
form = RandomizationEditForm(request, data=request.POST or None)
if form.is_valid():
# Récupération des données permettant la randomisation
randomisation = Randomisation.objects.filter(Q(pay_ide=form.data.get('pay_ide')) & Q(ran_act=1) & Q(ran_st1=form.data.get('ran_st1')) & Q(pat=None)).first()
randomisation.pat = form.data.get('pat')
randomisation.ran_nai = form.data.get('ran_nai')
randomisation.ran_sex = form.data.get('ran_sex')
randomisation.ran_bug = form.data.get('ran_bug')
randomisation.ran_dem_nom = form.data.get('ran_dem_nom')
randomisation.ran_dem_dat = form.data.get('ran_dem_dat')
print('ran_bug',form.data.get('ran_bug'))
randomisation.ran_log = request.user.username
randomisation.ran_dat = timezone.now()
randomisation.save()
return redirect('randomization:confirmation', pk = randomisation.pk)
else:
form = RandomizationEditForm(request)
return render(request, 'randomization/edit.html', {'form': form})
OK, i resolve my problem: form.cleaned_data['ran_bug'] instead of form.data.get('ran_bug')

Django: 'UNIQUE constraint failed'

I have override init in RandomisationFOrm and have an error I did not have before
I understand the error: in my models Randomization ran_num field is UNIQUE
and when I try to save a form when I call randomisation_edit view with the same ran_num it raise error
but before overriding __init__, this error was manage by Django itself
I try to add validation as below but raise another error: 'RandomisationForm' object has no attribute 'clean_data' -> I do the same for other field without this error...
def clean_ran_num(self):
data = self.clean_data['ran_num']
if data == 'CIV-CO-001':
raise forms.validationError('test')
return data
I try to add validation in the global 'clean' method but it do not apply...
I do not understand...
models.py
class Randomisation(models.Model):
# ran_num = models.CharField("Patient code", max_length=10, unique=True, null=True, blank=True,validators=[validate_patient_code])
ran_ide = models.AutoField(primary_key=True)
ran_num = models.CharField("Patient code", max_length=10, unique=True, null=True, blank=True)
ran_dat = models.DateField("Date of randomization", null=True, blank=True)
ran_inv = models.CharField("Investigator", max_length=20, null=True, blank=True)
ran_pro = models.IntegerField("Procedure used to randomized", null=True, blank=True)
ran_pro_per = models.CharField("if telephone, name of the person reached on the phone", max_length=20, null=True, blank=True)
ran_crf_inc = models.IntegerField("Was the CRF inclusion 2 Eligibility fulfilled?", null=True, blank=True)
ran_tbc = models.IntegerField("Is TB diagnosis possible, probable or definite?", null=True, blank=True)
ran_crf_eli = models.IntegerField("Was the CRF Inclusion 2 Eligibility fulffiled?", null=True, blank=True)
ran_cri = models.IntegerField("Is the conclusion All criteria fulfilled for randomisation", null=True, blank=True)
ran_sta = models.IntegerField("British Medical Council Staging (worst stage reported between first symptoms and now)", null=True, blank=True)
ran_vih = models.IntegerField("HIV/AIDS status", null=True, blank=True)
ran_bra = models.IntegerField("TB treatment assigned", null=True, blank=True)
ran_med = models.CharField("Batch number", max_length=6, null=True, blank=True)
ran_log_dat = models.DateTimeField("Date", null=True, blank=True)
ran_log = models.CharField("Name of the person who performs randomisation on site", max_length=10, null=True, blank=True)
forms.py
class RandomisationForm(forms.ModelForm):
# surcharge méthode constructeur (__init__) pour avoir accès aux variables de sessions
# https://stackoverflow.com/questions/3778148/django-form-validation-including-the-use-of-session-data
def __init__(self, request, *args, **kwargs):
self.request = request
super(RandomisationForm, self).__init__(*args, **kwargs)
# vérification que le numéro patient saisi correspond bien au site actuellement sélectionné
# i.e. profil 'International'
def clean(self):
data = self.cleaned_data['ran_num']
if data[4:6] != self.request.session.get('selected_site'):
raise ValidationError(_('Patient code is different from the selected site'))
TYPES = [
(None, ''),
(1, _('On-line')),
(2, _('Telephon')),
]
YESNO = [
(None, ''),
(1, _('Yes')),
(0, _('No')),
]
TB = [
(None, ''),
(1, _('Possible')),
(2, _('Probable')),
(3, _('Definite')),
]
SEVERITY = [
(None, ''),
(1, _('Mild')),
(2, _('Severe')),
]
HIV = [
(None, ''),
(0, _('Negative')),
(1, _('Positive')),
]
ran_dat = forms.DateField(
label = _("Date of randomization"),
initial = datetime.datetime.now,
required = True,
)
ran_num = forms.CharField(label = _("Patient number"), required=True) # ajout
ran_inv = forms.CharField(label = _("Investigator"), required=True)
ran_pro = forms.ChoiceField(label = _("Type"), widget=forms.Select, choices=TYPES)
ran_pro_per = forms.CharField(label = _("if telephone, name of the person reached on the phone"), required=False)
ran_crf_inc = forms.ChoiceField(label = _("Was the CRF inclusion 1 TB diagnosis fulfilled?"), widget = forms.Select, choices = YESNO)
ran_crf_eli = forms.ChoiceField(label = _("Was the CRF Inclusion 2 Eligibility fulffiled?"), widget = forms.Select, choices = YESNO)
ran_tbc = forms.ChoiceField(label = _("Is TB diagnosis possible, probable or definite?"), widget = forms.Select, choices = TB)
ran_cri = forms.ChoiceField(label = _("Is the conclusion All criteria fulfilled for randomisation"), widget=forms.Select, choices = YESNO)
ran_sta = forms.ChoiceField(label = _("British Medical Council Staging (worst stage reported between first symptoms and now)"), widget = forms.Select, choices = SEVERITY)
ran_vih = forms.ChoiceField(label = _("HIV/AIDS status"), widget = forms.Select, choices = HIV)
class Meta:
model = Randomisation
# Tous les champs sauf les champs de log et les champs TB treatment et Drug batch number
fields = ('ran_num','ran_dat','ran_inv','ran_pro','ran_pro_per','ran_crf_inc','ran_tbc','ran_crf_eli','ran_cri','ran_sta','ran_vih',)
def clean_ran_crf_inc(self):
data = self.cleaned_data['ran_crf_inc']
if int(data) == 0:
raise forms.ValidationError(_("This criteria is mandatory for randomization"))
return data
def clean_ran_crf_eli(self):
data = self.cleaned_data['ran_crf_eli']
if int(data) == 0:
raise forms.ValidationError(_("This criteria is mandatory for randomization"))
return data
def clean_ran_cri(self):
data = self.cleaned_data['ran_cri']
if int(data) == 0:
raise forms.ValidationError_(("This criteria is mandatory for randomization"))
return data
views.py
def randomisation_edit(request):
if request.method == "POST":
form = RandomisationForm(request, data=request.POST or None)
if form.is_valid():
randomisation = form.save()
# randomisation
rand = Randomiser(randomisation.ran_num, randomisation.ran_vih, randomisation.ran_sta)
# Mise à jour de la base de données -> Patient code pour rendre indisponible la ligne
# pour une prochaine randomisation
# ListeRandomisation
# 1.Récupération de la ligne dans la liste de rando
bras = rand['bras']
# 2.Mise à jour de la ligne dans la liste de rando
patient = ListeRandomisation.objects.get(ran_ide = bras)
patient.ran_dis = randomisation.ran_num # pat
patient.save()
# Medicament
# 1.Récupération de la ligne dans la liste de correspondance médicament
medicament = rand['medicament']
# 2.Mise à jour de la ligne dans la liste de correspondance médicament
medicament = Medicament.objects.get(med_ide = medicament)
medicament.ran_dis = randomisation.ran_num # pat
medicament.save()
# mise à jour de la variable de session can_randomize
request.session['can_randomize'] = is_randomizable(medicament.ran_dis)
# Mise à jour de la table Randomisation avec le bras et le numéro de boite attribués
randomisation.ran_bra = patient.ran_bra
randomisation.ran_med = medicament.med_num
randomisation.ran_log_dat = datetime.now()
randomisation.ran_log = request.user.username
randomisation.save()
return redirect('randomization:confirmation', pk = randomisation.pk)
else:
form = RandomisationForm(request)
return render(request, 'randomization/randomisation_edit.html', {'form': form})
When you override the Form.clean method you have to call super(RandomisationForm, self).clean() or you will loose the unique constraint checks.
From the docs:
https://docs.djangoproject.com/en/3.0/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other
The call to super().clean() in the example code ensures that any validation logic in parent classes is maintained. If your form inherits another that doesn’t return a cleaned_data dictionary in its clean() method (doing so is optional), then don’t assign cleaned_data to the result of the super() call and use self.cleaned_data instead:

How to update a FloatField: Django

I'm trying to update field in my models with the newly calculated value from my view and when I try to update my field using total.objects.update(total=total) this is what i get 'decimal.Decimal' object has no attribute 'objects'.
I also have some other questions, I'm currently calculating the total field from initial values inputted when the item is created, using the save() method. is this a good idea ? or is there a better way of doing this? the reason I'm currently doing this is because i display the a list of items with their initial values.
Over all I'm trying to make a tools inventory system. I also have some other concerns.
How can I use this view on multiple items types? the model items is an abstract model that contains all common fields,and every tool type inherits this model and will be using the same operations, calculate the new cantidad_existente and update the total fields. Is there a better way?
my views.py
def calcular_nueva_cantidad(ce, up):
total = ce + up
return total
class updateForm(forms.Form):
update = forms.IntegerField()
def actualizar_cantidad(request, pk):
# trae de la base de datos el valor de la cantidad existente
cantidad_existente = Cortadores.objects.filter(pk=pk).values('cantidad_existente')
c = cantidad_existente.values_list('cantidad_existente', flat=True)
ce= c[0]
# trae de la base de datos el valor de precio_unitario
precio_unitario = Cortadores.objects.filter(pk=pk).values('precio_unitario')
p = precio_unitario.values_list('precio_unitario', flat=True)
pu =p[0]
# trae de la base de datos el valor de la total
total = Cortadores.objects.filter(pk=pk).values('total')
print(F'el precio unitario es {total} ----------------------------------------------------')
if request.method =='POST':
form = updateForm(request.POST)
if form.is_valid():
up = form.cleaned_data['update']
nce = calcular_nueva_cantidad(up, ce)
total = nce * pu
print(F' el nuevo total es {total} -----------------------')
# nce.save()
cantidad_existente.update(cantidad_existente=nce)
total.objects.update(total=total)
return render(request, 'inventario/cortadores.html', {'nce':nce})
else:
# Redirect to fail page after POST
return HttpResponse('')
else:
form = updateForm()
return render(request, 'inventario/update-cortador.html', {'form':form, 'cantidad_existente':cantidad_existente })
my models.py
class Item(models.Model):
description = models.CharField(max_length=30,)
numero_parte = models.CharField(max_length=30)
proveedor = models.ForeignKey(Proveedor, on_delete=models.CASCADE)
cantidad_existente = models.PositiveIntegerField()
update = models.PositiveIntegerField(blank=True, default=0)
cantidad_minima = models.PositiveIntegerField()
precio_unitario = models.DecimalField(max_digits=5, decimal_places=2)
total = models.FloatField(blank=True)
asignado_a = models.ForeignKey(Empleados, on_delete=models.CASCADE, blank=True, null=True)
anaquel = models.CharField(max_length=2, choices=ANAQUEL, blank=True, null=True)
posicion_en_x = models.CharField(max_length=2, blank=True, null=True)
posicion_en_y = models.CharField(max_length=2, blank=True, null=True)
activo = models.BooleanField()
class Meta:
abstract = True
def save(self,*args,**kwargs):
self.total = self.cantidad_existente * self.precio_unitario
super().save(*args,**kwargs)
class Cortadores(Item):
tipo = models.ForeignKey(Tipos_Cortadores,on_delete=models.CASCADE)
material = models.ForeignKey(Materiales, on_delete=models.CASCADE)
filos = models.CharField(max_length=5, choices=GABILANES)
diametro = models.ForeignKey(Diametros, on_delete=models.CASCADE)
longitud = models.ForeignKey(Longitud, on_delete=models.CASCADE)
desbaste = models.CharField(max_length=1, choices=DESBASTE)
class Meta:
verbose_name_plural = "Cortadores"
def get_absolute_url(self):
return reverse('inventario:cortadores-list', kwargs={'id': self.id})
def __str__(self):
return '%s %s %s %s %s %s' % ( str(self.tipo), str(self.material), str(self.filos), str(self.diametro),
self.longitud, self.desbaste
)
The error is that you have two variables called total. Just rename one of them.
total = Cortadores.objects.filter(pk=pk).values('total')
...
new_value = nce * pu
total.objects.update(total=new_value)
There is a error, you changing you queryset to flaot value, and then trying to use queryset functions on it, so you should use other variable in total and not your own queryset
total = Cortadores.objects.filter(pk=pk).values('total')
total = nce * pu // This line replace your queryset to float
total.objects.update(total=total)
You should use something like that
qs_total = Cortadores.objects.filter(pk=pk).values('total')
total = calcular_nuevo_total(nce, pu)
for value in qs_total:
value.total=total
value.save()
To use it as generic like you want use pass the class reference as parameter and use it to call your query set
def something(__class__):
class.objects.all()
EDIT: Making a generic method to use with any class
from .models import Cortadores, OtherModelExample
def generic_update_noreturn(__class__, pk, total)
qs= __class__.objects.filter(pk=pk).values('total')
for value in qs:
value.total=total
value.save()
return qs
def generic_update_noreturn(__class__, pk, total)
__class__.objects.filter(pk=pk).values('total')update(total=total)
def actualizar_cantidad(request, pk):
...
total = calcular_nuevo_total(nce, pu)
updated_cortadores=generic_update(Cortadores, pk, total)
updated_otherexample=generic_update(OtherModelExample, total, pu)
generic_update_noreturn(Cortadores, pk, total)

Reusable views method for multiple model classes Django

Guys I want to create a tools inventory app.
I have this method that will do the exact same thing on all tools types. What I want to know is how can I use this method dynamically selecting what models to use (maybe how to pass a model class as an argument).
It's currently working only for one type of tool. My models.py has an abstract model that has all common fields for all tools and then various models that inherit it for tool specific fields (e.i. End mills, Drill-bits, pliers, screwdrivers, etc all inherit common filed from my abstract model).
def calcular_nueva_cantidad(ce, up, get_link):
if get_link == 'incremento':
total = ce + up
else:
total = -(ce - up)
return total
def calcular_nuevo_total(nce, pu):
total = nce * pu
return total
# crea el formulario para la actualizacion de cantidad existente
class updateForm(forms.Form):
update = forms.IntegerField()
def actualizar_cantidad(request, pk, model ):
# trae de la base de datos el valor de la cantidad_existente
cantidad_existente = model.objects.filter(pk=pk).values('cantidad_existente')
c = cantidad_existente.values_list('cantidad_existente', flat=True)
ce = c[0]
# trae de la base de datos el valor de la precio_unitario
precio_unitario = model.objects.filter(pk=pk).values('precio_unitario')
p = precio_unitario.values_list('precio_unitario', flat=True)
pu = p[0]
# trae de la base de datos el valor de la total
qs_total = model.objects.filter(pk=pk).values('total')
if request.method =='POST':
form = updateForm(request.POST)
if form.is_valid():
# Obtiene el name de urls para el link segun sea el caso
get_link = resolve(request.path_info).url_name
get_linkwargs = resolve(request.path_info).kwargs
print(F'========>{get_link, get_linkwargs }<=========')
up = form.cleaned_data['update']
# Calcula el nuevo valor de cantidad existente
nce = calcular_nueva_cantidad(up, ce, get_link)
# Actualiza la nueva cantidad existente
cantidad_existente.update(cantidad_existente=nce)
# Calcula el nuevo valor de cantidad existente
s_total = calcular_nuevo_total(nce, pu)
# Actualiza la nueva cantidad existente
qs_total.update(total=s_total)
# Obteiene item id del tipo de cortador asi puede regresar a la pantalla del listado
pp = model.objects.filter(pk=pk).values('tipo')
ppp = pp.values_list('tipo', flat=True)
pk = ppp[0]
return HttpResponseRedirect(reverse('inventario:cortadores-list', args=(pk, )))
else:
# Redirect to fail page after POST
return HttpResponse('')
else:
form = updateForm()
return render(request, 'inventario/update.html', {'form':form})
This is my abstract class in my models.py
class Item(models.Model):
description = models.CharField(max_length=30,)
numero_parte = models.CharField(max_length=30)
proveedor = models.ForeignKey(Proveedor, on_delete=models.CASCADE)
cantidad_existente = models.PositiveIntegerField()
update = models.PositiveIntegerField(blank=True, default=0)
cantidad_minima = models.PositiveIntegerField()
precio_unitario = models.DecimalField(max_digits=7, decimal_places=2)
total = models.DecimalField(max_digits=7, decimal_places=2, blank=True)
asignado_a = models.ForeignKey(Empleados, on_delete=models.CASCADE, blank=True, null=True)
anaquel = models.CharField(max_length=2, choices=ANAQUEL, blank=True, null=True)
posicion_en_x = models.CharField(max_length=2, blank=True, null=True)
posicion_en_y = models.CharField(max_length=2, blank=True, null=True)
activo = models.BooleanField()
class Meta:
abstract = True
def save(self,*args,**kwargs):
self.total = self.cantidad_existente * self.precio_unitario
super().save(*args,**kwargs)
These two classes inherit from Item
class Cortadores(Item):
tipo = models.ForeignKey(Tipos_Cortadores,on_delete=models.CASCADE)
material = models.ForeignKey(Materiales, on_delete=models.CASCADE)
filos = models.CharField(max_length=5, choices=GABILANES)
diametro = models.ForeignKey(Diametros, on_delete=models.CASCADE)
longitud = models.ForeignKey(Longitud, on_delete=models.CASCADE)
desbaste = models.CharField(max_length=1, choices=DESBASTE)
class Meta:
verbose_name_plural = "Cortadores"
def get_absolute_url(self):
return reverse('inventario:cortadores-list', kwargs={'id': self.tipo.id})
def __str__(self):
return '%s %s %s %s %s %s' % ( str(self.tipo), str(self.material), str(self.filos), str(self.diametro),
self.longitud, self.desbaste
)
class Tornillos(Item):
tipo = models.CharField(max_length=10, choices=TIPO_TORNILLO)
paso = models.ForeignKey(Paso_Tornillo, on_delete=models.CASCADE)
material = models.ForeignKey(Materiales, on_delete=models.CASCADE)
longitud = models.ForeignKey(Longitud, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "Tornillos"
def get_absolute_url(self):
return reverse('inventario:lista-herramientas-mecanicas')#, kwargs={'pk': self.pk})
def __str__(self):
return '%s %s %s %s' % (str(self.tipo), str(self.paso), str(self.material), str(self.longitud))
I made a class for every tool type that I own. I only included these two classes for simplicity and not fill the post with a lot of code.
If you still can change the design of your tables, you could use multi-table-inheritance instead of the abstract-base-class you are using now.
That would mean that you will have one model Item (which will be an actual database table) and then other models that inherit from this model (their database tables will only hold the new fields, but not repeat any fields).
For that change you only need to remove abstract = True from Item.Meta; you should not need to change other parts form your models. Of course, you will have to drop your tables and run migrations again (will destroy your current data).
As I said, this is only an option if you can still change your database tables significantly.
With this setup, you can query your Item model directly for the common fields. There are some subtleties you have to be careful about, but read the docs I linked to see if it solves your issue.