Use django formset for only a few specific fields
I am relatively new to django (about 3 months using it) and ran into the following problem at work. I have a model with several fields, and they asked me that of those fields, 4 specifically should be able to dynamically add another register, that is, if i register something in one of those fields, there should be the option to do it again indefinitely. I understand that this can be achieved using formset but all the examples I find are using all the fields of the model and not just a few. Any ideas on what I can do?
this is the model
class Mercancia(SafeDeleteModel):
_safedelete_policy = SOFT_DELETE_CASCADE
id = models.AutoField(primary_key=True)
factura = models.ForeignKey("Factura", on_delete=models.CASCADE)
desc_mercancia = models.CharField(max_length=256, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'La descripción de la mercancia no acepta caracteres especiales.')])
comercio = models.ForeignKey("ClaveComercio", on_delete=models.CASCADE)
tipo_moneda = models.ForeignKey("Moneda", on_delete=models.CASCADE)
cantidad_comerc = models.DecimalField(max_digits=30, decimal_places=0)
valor_unitario = models.DecimalField(max_digits=22, decimal_places=6, validators=[MinValueValidator(0)])
valor_total = models.DecimalField(max_digits=22, decimal_places=6, validators=[MinValueValidator(0)])
valor_total_dolares = models.DecimalField(max_digits=20, decimal_places=4, validators=[MinValueValidator(0)])
marca = models.CharField(blank = True, max_length=35, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'El modelo solo permite valores alfanuméricos.')])
modelo = models.CharField(blank = True, max_length=50, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'El modelo solo permite valores alfanuméricos.')])
submodelo = models.CharField(blank=True, max_length=50, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'El submodelo solo permite valores alfanuméricos.')])
numero_serie = models.CharField(blank = True, max_length=25, validators=[RegexValidator(r'^[0-9a-zA-Z\s]*$', 'El numero de serie solo permite valores alfanuméricos.')])
history = HistoricalRecords()
created_by = models.ForeignKey('catalogos_modular.User', related_name='+', on_delete=models.CASCADE)
updated_by = models.ForeignKey('catalogos_modular.User', related_name='+', on_delete=models.CASCADE, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True, null=True)
class Meta:
# verbose_name = "Mercancia"
# verbose_name_plural = "Mercancias"
db_table = "fac_mercancia"
ordering = ['-id']
view
class CreateMercancia(CreateView):
model = Mercancia
template_name = "mercancias/create.html"
form_class = MercanciaForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["mercancia"] = self.model.objects.filter(factura=self.kwargs['pk']).values()
moneda = Moneda.objects.all()
for merch in context['mercancia']:
for mon in moneda:
if merch['tipo_moneda_id'] == mon.id:
merch['tipo_moneda_id'] = mon.name
context["id_anterior"] = self.kwargs['pk']
return context
def get_form_kwargs(self, *args, **kwargs):
form_kwargs = super().get_form_kwargs(*args, **kwargs)
user = self.request.user
form_kwargs['user'] = user
return form_kwargs
def get_success_url(self):
return reverse_lazy('facturas:createMercancias', kwargs={'pk':self.kwargs['pk']})
form
class MercanciaForm(forms.ModelForm):
class Meta:
model = Mercancia
fields = '__all__'
exclude = ('created_by','updated_by','is_deleted','deleted_at')
widgets = {
'desc_mercancia': forms.TextInput(attrs={'placeholder': 'Descripcion de la mercancia'}),
'tipo_moneda': forms.Select(),
'cantidad_comerc': forms.NumberInput(attrs={'placeholder': 'Cantidad de unidades de comercialización'}),
'valor_unitario': forms.TextInput(attrs={'placeholder': 'Valor unitario'}),
'valor_total': forms.TextInput(attrs={'placeholder': 'Valor total'}),
'valor_total_dolares': forms.TextInput(attrs={'placeholder': 'Valor total en dolares'}),
'marca': forms.TextInput(attrs={'placeholder': 'Marca'}),
'modelo': forms.TextInput(attrs={'placeholder': 'Modelo'}),
'submodelo': forms.TextInput(attrs={'placeholder': 'Submodelo'}),
'numero_serie': forms.TextInput(attrs={'placeholder': 'Número de serie'}),
'consecutivo_merc' : forms.TextInput(attrs={'readonly': 'readonly'}),
}
labels = {
'desc_mercancia':'Descripción',
'comercio':'Clave medida de comercialización',
'tipo_moneda':'Tipo de moneda',
'cantidad_comerc':'Cantidad de unidades de comercialización',
'valor_unitario':'Valor unitario',
'valor_total':'Valor total',
'valor_total_dolares':'Valor total en dolares',
'marca':'Marca',
'modelo':'Modelo',
'submodelo':'Submodelo',
'numero_serie':'Número de serie',
'clave_medida_comer':'Clave medida comer.'
}
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super().__init__(*args, **kwargs)
def save(self, commit=True):
self.instance.created_by = self.user
self.instance.updated_by = self.user
if self.instance.id is not None:
self.instance.updated_by = self.user
return super().save(commit=commit)
template create.html
{% load crispy_forms_tags %}
<section class="clean-block clean-form dark" style="overflow-x: auto; ">
<div class="container" >
<div class="row" style="margin-right: 0px;margin-left: 0px;">
<div class="col-md-12"
style="margin-bottom: 25px;padding-left: 5%;font-size: 21px;margin-top: 26px;">
{% if hiddentable != True %}
<a class="anone" href="{% url 'facturas:createPersona' id_anterior %}">
<i class="fa fa-arrow-left" style="color: #6F7271"></i>
<span style="color: #6F7271"> Volver</span>
</a>
{% else %}
<a class="anone" href="{% url 'facturas:editFactura' id_anterior %}">
<i class="fa fa-arrow-left" style="color: #6F7271"></i>
<span style="color: #6F7271"> Volver</span>
</a>
{% endif %}
</div>
</div>
<div class="block-heading" style="padding-top: 0px;">
<h2 class="text_color">
Agregar mercancia
<br>
</h2>
</div>
<form action="" class="tipo_documento" role="form" method="post"
enctype="multipart/form-data" id="factura_form" style="border-top: 2px solid #691C32; width: 1400px; overflow-x: auto;">
{% csrf_token %}
<h3 style="padding-bottom: 12px;">Datos de la mercancia</h3>
<div class="first_container">
<!-- Start: Id de factura -->
<div class="form-group mb-3" hidden>
<input class="form-control" type="text" name="factura" value={{id_anterior}} readonly></input>
</div>
<!-- End: Id de factura -->
<div class="form-group mb-3" >
<strong>{{form.desc_mercancia |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.comercio |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.tipo_moneda |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.cantidad_comerc |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.valor_unitario |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.valor_total |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.valor_total_dolares |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.marca |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.modelo |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.submodelo |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<strong>{{form.numero_serie |as_crispy_field}}</strong>
</div>
<div class="form-group mb-3" >
<button onClick="this.form.submit(); this.disabled=true; this.value='Sending…'; " id="submit_button" class="btn btn-primary" type="submit" style="background-color: #691C32; border: none;">Guardar</button>
</div>
</div>
{% if hiddentable != True %}
<!-- Start: Tabla personas-->
<div class="mb-3 mt-0" id="lista_personas">
<div class="table_tittle">
<p>Lista de mercancias</p>
</div>
<div class="table_nav_container">
<div class="table_nav2">
<div class="number_page" id="number_page">1</div>
<button type="button" class="back_beggin" id="first_one">< <</button>
<button type="button" class="back_one" id="back_one"><</button>
<div class="current_page" id="current_page">1</div>
<button type="button" class="next_one" id="next_one">></button>
<button type="button" class="last_one" id="last_one">> ></button>
<select class="select_number" name="" id="number_show_select">
<option value="5" selected="selected">5</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="25">25</pption>
</select>
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<div class="table-responsive shadow" style="border-radius: 20px;border-style: none;">
<table id="ipi-table" class="table table-striped table-borderless table tablesorter">
<thead class="thead-dark">
<tr>
<th class="text-center">ID Mercancia</th>
<th class="text-center">ID Documento</th>
<th class="text-center">Descripción</th>
<th class="text-center">Clave de la unidad de medida de comercializacion</th>
<th class="text-center">Tipo moneda</th>
<th class="text-center">Cantidad unidades de comercializacion</th>
<th class="text-center">Valor unitario</th>
<th class="text-center">Valor total</th>
<th class="text-center">Valor total dolares</th>
<th class="text-center">Marca</th>
<th class="text-center">Modelo</th>
<th class="text-center">Submodelo</th>
<th class="text-center">Número de serie</th>
<th class="text-center filter-false sorter-false">Acciones</th>
</tr>
</thead>
<tbody id="mercancias_table" class="text-center" hx-get="{% url 'facturas:listaMercancias' id_anterior %}" hx-trigger="load, merchListChanged from:body">
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endif %}
<!-- End: Tabla personas-->
<hr>
{% if hiddentable != True %}
<a class="btn btn-primary" href="{% url 'facturas:createUsuarioFactura' id_anterior %}" style="background-color: #691C32; border: none;">Siguiente</a>
{% endif %}
</form>
</div>
</section>
{% endblock %}
Note: variable names are in spanish
Note: the fieds that matter are marca, modelo, submodelo, numero_serie