Removing labels from dynamic django crispy formset

I have a dynamic formset to allow users to add a variable number of entries. This is implemented using GitHub - elo80ka/django-dynamic-formset: A jQuery plugin that allows you dynamically add new forms to a rendered django formset., and outlined below

When a user adds multiple rows it displays as:

I would however like the labels to either be 1. removed entirely, or 2. only be present for the first row or 3. be within the entry box as opposed to above it?

models.py

class Patient(TimeStampedModel):
    # get a unique id for each patient - could perhaps use this as slug if needed
    patient_id = models.UUIDField(primary_key=True, unique=True, default=uuid.uuid4, editable=False)
    
class PastMed(TimeStampedModel):
     medication = models.CharField(
        “Medication”, max_length=20, default=‘unspecified’)

	dose = models.IntegerField("Dose (mg)", default=0)

patient = models.ForeignKey(Patient, on_delete=models.CASCADE)

forms.py

PastmedFormSet = inlineformset_factory(
    Patient, PastMed, fields=(“medication”, “dose”), extra=1)

views.py

class PatientAddView(LoginRequiredMixin,TemplateView):
    model = Patient
    template_name = "../templates/add.html"

    def get(self, *args, **kwargs):
        pastmed_formset = PastmedFormSet(queryset=PastMed.objects.none())
        return self.render_to_response({'pastmed_formset': pastmed_formset})

add.html

<script type="text/javascript" src="{% static 'js/jquery/dist/jquery.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery.formset.js' %}"></script>
<script type="text/javascript">
    $(function() {
        
        $('#pastmeds_table tbody tr').formset({
            prefix: 'pastmed_set'
        })
    });
</script>

    <div class="form-group">
    <table id="pastmeds_table" border="0" cellpadding="0" cellspacing="5">
        <tbody>
        {% for form in pastmed_formset %}
            <tr id="{{ form.prefix }}-row"></tr>
                <td>
                    {% for fld in form.hidden_fields %}{{ fld }}{% endfor %}
                    {% if form.instance.pk %}{{ form.DELETE }}{% endif %}
                    <div class="row">
                        <div class="col-3">
                            {{ medication|as_crispy_field}}
                        </div>
                        <div class="col-3">
                            {{ form.dose|as_crispy_field }}
                        </div>
                    </div>
                </td>
            
            </tr>
            {% endfor %}
        </tbody>
    </table> 
    </div>

I’m not sure how much you can do with it when using the filter. (See crispy filter — django-crispy-forms 1.11.1 documentation), but there are some things you can try.

You could try removing the labels (setting those attributes to None) in your form. (You can pass the labels parameter through your call to inlineformset_factory.
See - Creating forms from models | Django documentation | Django, which leads you to Model Form Functions | Django documentation | Django, finally ending up at Model Form Functions | Django documentation | Django)

You might be able to override the field.html template, but that’s going to affect every crispy field you use.

You could also look at the source for as_crispy_field, and using that as your guide, create your own filter that uses a different template - that would give you a more targeted approach.

Or you could just convert to using the {% crispy %} tag, and define a helper for your form that handles labels as needed.

Many thanks @KenWhitesell

I have taken your advice and switched to using a helper, and have been able to remove the labels using form_show_labels = False . I wondered though if there was a quick way to move the label to inside of the entry box?

That’s a widget-specific issue - generally referred to as the “placeholder” attribute. You can add a placeholder to a field. See the discussion at EmailField placeholder in django form?

@robmcc
try use this before your helper

for key, field in self.fields.items():
field.widget.attrs.update({‘placeholder’: field.label})
field.label = ‘’