Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render form will always render default template #140

Open
codematsing opened this issue May 15, 2024 · 4 comments
Open

Render form will always render default template #140

codematsing opened this issue May 15, 2024 · 4 comments

Comments

@codematsing
Copy link

codematsing commented May 15, 2024

Issue

I found that using the templatetag render_form will ignore the form renderer I declared in forms.py when I implement my project as follows:

from formset.renderers.bootstrap import FormRenderer as BootstrapFormRenderer
class Form(ModelForm):
    default_renderer = BootstrapFormRenderer(
        field_css_classes='row mb-3',
        label_css_classes='col-sm-3',
        control_css_classes='col-sm-9',
    )
    class Meta:
         model = ...
         fields = "__all__"

and template:

<django-formset endpoint="{{ request.path }}" csrf-token="{{ csrf_token }}">
  {% render_form form %}
  <div class="offset-sm-3">
    <button type="button" click="submit -> proceed" class="btn btn-primary">Submit</button>
    <button type="button" click="reset" class="ms-2 btn btn-warning">Reset to initial</button>
  </div>
</django-formset>

Clarification

I'm not sure if this is correct since I'm still checking this out:

https://github.com/jrief/django-formset/blob/e12c947a519ce84510b15df07030ac2c77df2a39/formset/templatetags/formsetify.py#L49C1-L52C66

def render_form(context, form, *args, **kwargs):
    get_token(context['request'])  # ensures that the CSRF-Cookie is set
    form = _formsetify(form, *args, **kwargs)
    # shouldnt this:
    return form.render(template_name='formset/default/form.html')
    # be this:
     return form.render()

It's causing rendering issues on my project since my ModelForm.default_renderer is bootstrap-based renderer,
while {% render_form form %} forces to use formset/default/form.html instead of formset/bootstrap/form.html

@jrief
Copy link
Owner

jrief commented May 15, 2024

I would have to step through with the debugger, but usually you would use the Bootstrap Renderer class to render your forms. And here https://github.com/jrief/django-formset/blob/e12c947a519ce84510b15df07030ac2c77df2a39/formset/renderers/bootstrap.py#L17C39-L17C66 the default template is mapped to one specific to Bootstrap.

@codematsing
Copy link
Author

codematsing commented May 15, 2024

I agree to the reference. It is what I use, but when I check the rendered html, each field group follows
formset/default/field_group.html instead of formset/bootstrap/field.group.html

... which in turn, fails to create the inline formatting of labels and inputs as referenced here

This is due to the implementation of formset/default/field_group.html having no separate div classes for label and input, which formset/bootstrap/field_group.html wraps widget field inside a div element

So I'm not sure if the templatetags.formsetify.render_form should be adjusted, or, default/field_group.html needs a div class similar to bootstrap/field_group.html

@jrief
Copy link
Owner

jrief commented May 15, 2024

Can you please create a small example. Take the examples in testapp as blueprint.

@codematsing
Copy link
Author

codematsing commented May 16, 2024

Investigatory diff:

image

<!-- snippet -->
<div role="group" class="dj-required row mb-3">
   <label for="id_name" class="col-sm-3">Team name:</label><input type="text" name="name" maxlength="50" required="" form="id_customrendererteamform" id="id_name" class="form-control">
   <div role="alert" class="dj-field-errors">
      <meta name="error-messages" value_missing="This field is required." too_long="Ensure this value has at most 50 characters." bad_input="Null characters are not allowed.">
      <ul class="dj-errorlist">
         <li class="dj-placeholder"></li>
      </ul>
   </div>
   <div class="dj-help-text">The name of the team</div>
</div>

Overridden diff:

image

<!-- snippet -->
<div role="group" class="row mb-3 dj-required">
   <label for="id_name" class="col-sm-3">
   Team name:</label>
   <div class="col-sm-9">
      <input type="text" name="name" maxlength="50" required="" form="id_customrendererteamform" id="id_name" class="form-control">
      <div role="alert" class="dj-field-errors">
         <meta name="error-messages" value_missing="This field is required." too_long="Ensure this value has at most 50 characters." bad_input="Null characters are not allowed.">
         <ul class="dj-errorlist">
            <li class="dj-placeholder"></li>
         </ul>
      </div>
      <div class="form-text text-muted">The name of the team</div>
   </div>
</div>

Some Notes:

  • I had to externally import bootstrap cdn since I had issues loading static files when trying to run webapp (It's kind of irrelevant to the investigation but provides us with needed visual cues)
  • Implementation assumes having a CreateView inheriting native django CreateView that:
    • takes in form_class with override of default_renderer=BootstrapFormRenderer
    • overrides template that uses {% render_form form %}
  • I also tried using {{form}} instead of {% render_form form %}. Doing so will partially render the form correctly except for field_css_clases but will raise 422 on submit, consequently, will to fail to create an instance. I'm not sure if it's an implementation issue or a limitation (which is why render_form is needed)
  • I find that 84b9e1c works for my usecase but I'm not sure if it's all encompassing solution or would affect implementation

Hopefully implementation is readable enough!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants