How to extend the comments framework (django) by removing unnecessary fields? - python

I've been reading on the django docs about the comments framework and how to customize it (http://docs.djangoproject.com/en/1.1/ref/contrib/comments/custom/)
In that page, it shows how to add new fields to a form. But what I want to do is to remove unnecesary fields, like URL, email (amongst other minor mods.)
On that same doc page it says the way to go is to extend my custom comments class from BaseCommentAbstractModel, but that's pretty much it, I've come so far and now I'm at a loss. I couldn't find anything on this specific aspect.

I recently implemented the solution that Ofri mentioned, since I only wanted to accept a solitary "comment" field for a comment (like SO does, no "name", no "email" and no "url").
To customize the default comment form and list display, I created a "comments" directory in my root "templates" directory and overrode the two default comment templates.
My "/templates/comments/form.html" is:
{% load comments i18n %}
{% if user.is_authenticated %}
<form action="{% comment_form_target %}" method="post">
{% csrf_token %}
{% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %}
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
{% if field.name != "name" and field.name != "email" and field.name != "url" %}
{% if field.errors %}{{ field.errors }}{% endif %}
<p {% if field.errors %} class="error"{% endif %} {% ifequal field.name "honeypot" %} style="display:none;"{% endifequal %}>
{{ field }}
</p>
{% endif %}
{% endif %}
{% endfor %}
<input type="submit" name="post" class="submit-post" value="{% trans "Add Comment" %}" />
</form>
{% else %}
I'm sorry, but you must be logged in to submit comments.
{% endif %}
Which is only slightly different from the default comments form, primarily suppressing the display of the not-required "name", "email" and "url" inputs.
My "/templates/comments/list.html" is:
<div class="comment_start"></div>
{% for comment in comment_list %}
<div class="comment">
{{ comment.comment }}
(from {{ comment.user }} - {{ comment.submit_date|timesince }} ago)
</div>
{% endfor %}
On the page I want the form, I first call {% load comments %} and then {% render_comment_form for [object] %} to show the form, or {% render_comment_list for [object] %} to generate a list of the comments on the object (replace [object] with your appropriate object name).
This is working great for me, and still giving me all the other "free" stuff that comes with django comments (moderation, flagging, feeds, polymorphic associations, etc...)

A tidy summary of how to do this elegantly, through the actual comments framework subclassing approach, rather than hiding elements in a form/other untidy hacks, can be found Django Comments: Want to remove user URL, not expand the model. How to?
Essentially, you subclass the CommentForm, and change its get_comment_create_data(self) method, and then pop out the attributes you don't want (e.g. email, url, etc.)
J

You can try overriding the comment form with a custom template that only shows the fields you want.

Related

Adding content between form in Formset_Factory = Django

I am working on a django application and more specifically, a formset (group of forms). I have the form set amount set the number of objects retrieved by a query set. What I want to do is make a change to the form set so that in between each of the forms in the formset, include a name for a user related to the form set. What is happening right now is that it is print the entire formset then the names that I want to move to be placed in between each of the forms in the formset.
** updated **.
Now what is happening is that between each of the different forms that are being iterated, It is displaying all of the objects that are being displayed. My issue is that I only want the first object in the list to print before the first form, second objects to display before the second form. and so on...
Sample of what is happening:
Add expense - restructured group
Please complete the form below
josh
lifter
omar
Amount: 0
Description: expense
josh
lifter
omar
Amount: 0
Description: expense
josh
lifter
omar
Amount: 0
Description: expense
submit
I want it to just display the first name for first form and so on. Here is the code:
{% extends "base.html" %}
{% block content %}
<h2>Add expense - {{ currentGroup.name }}</h2>
{% if message %}
<p>{{message}}</p>
{% endif %}
<form action="." method="POST">
{% csrf_token %}
{{ form.management_form }}
{% for f in form %}
{% for expense in expenses %}
<p>{{ expense.user.username }}</p>
{% endfor %}
{{ f.as_p }}
{% endfor %}
<input type="submit" name="submit" value="submit">
</form>
{% endblock %}
You can iterate form var in template and can add information between form but make sure you have to add {{ form.management_form }} also in form like below code
<form action="." method="POST">
{% csrf_token %}
{{ form.management_form }}
{% for f in form %}
{# Add whatever information you want to show between forms #}
{{ f.as_p }}
{% endfor %}
{% for expense in expenses %}
<p>{{ expense.user.username }}</p>
{% endfor %}
<input type="submit" name="submit" value="submit">
</form>

how to make the change_password template in flask-user to extend a different template based on user-roles

i have this code for change_password.html in flask-user:
{% extends 'admin.html' %}
{% block content %}
{% from "flask_user/_macros.html" import render_field, render_submit_field %}
<h1>{%trans%}Change password{%endtrans%}</h1>
<form action="" method="POST" class="form" role="form">
{{ form.hidden_tag() }}
{{ render_field(form.old_password, tabindex=10) }}
{{ render_field(form.new_password, tabindex=20) }}
{% if user_manager.enable_retype_password %}
{{ render_field(form.retype_password, tabindex=30) }}
{% endif %}
{{ render_submit_field(form.submit, tabindex=90) }}
</form>
{% endblock %}
I would like the template to extend two different templates namely employee.html and admin.html based on user roles. that is if the user is an employee, then the template extends employee.html and admin.html is extended if the user is an admin. how do i achieve this?
According to the Jinja's documentation there must be only one extends statement, that should be placed on the top of the file. To overcome this limitation you may join your two templates into the one, and switch between them using if statement inside the new template.

Render Flask wtforms RadioField lines/buttons in an ordered list

I would like to know if it's possible to have Flask WTForms RadioField render the list of radio buttons in an ordered list instead of an unordered list. My current jinja2 template is as follows:
{% extends "base.html.j2" %}
{% block content %}
<form action="/test" method="POST">
{% if test_form.errors %}
{{ test_form.errors }}
{% endif %}
{{ test_form.csrf_token }}
{% for qa in test_form.question_attempts %}
<div class="well">
<div>
{{ qa.label }}
</div>
<div>
{{ qa }}
</div>
</div>
{% endfor %}
{{ test_form.submitfield(class="btn btn-success") }}
</form>
{% endblock %}
Where the qa variable is the RadioField input.
EDIT:
To clarify, the test_form contains a list of RadioFields, which are the question_attempts. What I would like to do is have each qa render the radio buttons and associated radio button text in an ordered list rather than an unordered list.
When reviewing the WTForms documentation I had initially missed the part underneath the RadioFields description which describes how the list of radio buttons are rendered by default. I'll show it below:
{% for subfield in form.radio %}
<tr>
<td>{{ subfield }}</td>
<td>{{ subfield.label }}</td>
</tr>
{% endfor %}
This ends up rendering the radio buttons and associated text in an unordered list. Since I'm making an app where users can take a test, I wanted to render the answer choices in a list of "A. B. etc." This was fairly easy to do - I just needed to explicitly specify how the radio fields in my question_attempt form needed to be rendered. I'll show my updated code below:
{% extends "base.html.j2" %}
{% block content %}
<form action="/test" method="POST">
{% if test_form.errors %}
{{ test_form.errors }}
{% endif %}
{{ test_form.csrf_token }}
{% for qa in test_form.question_attempts %}
<div class="well">
<div>
{{ qa.label }}
</div>
<div>
<ol type="A">
{% for subfield in qa.answer_selection %}
<li>
{{ subfield }}
{{ subfield.label }}
</li>
{% endfor %}
</ol>
{{ qa.question_id }}
</div>
</div>
{% endfor %}
{{ test_form.submitfield(class="btn btn-success") }}
</form>
{% endblock %}
Now the form renders the radio button fields in and ordered list!
While explicitly writing the template will give you more control for how the fields are rendered, you then need to make sure that each component of the form is rendered in the template. Otherwise data from those fields will not be included in the posted data. This will be obvious for fields that require user input (as you won't see them), but can cause problems if you're using hidden fields for housekeeping data.

CSS for Flask wtforms

I have a the following code for a Form that I have in my Flask application using Wtforms. I use FieldList to use two fields for one part.
class A(Form)
additional = FieldList(FormField(Additional), 'Additional', min_entries=1)
submit = SubmitField('Submit')
class Additional(Form):
choices = [('Funding Mechanism', 'Funding Mechanism'), ('Study Section Name', 'Study Section Name')]
critera = SelectField('Additional Criteria', choices=choices)
input = StringField()
The template uses wtf.quick_form:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Grants - Find Grant{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Specify</h1>
</div>
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
{% endblock %}
Currently the forms render in a squished and overlapping way like so:
How can I change the code so that it is formated in one line like below? It is a screenshot of #Niklas in Stockholm 's form from his question.
Thank you!
Since your form class A is calling class Additional as a FormField and only adding submit to the field, i added the submit button the Additional form itself and then called it in the view.
In the template, use
{{ wtf.quick_form(form, form_type="inline") }}
It outputs the page like this:
The form_type argument adds the .form-inline to the class attribute.
This is just a hack, surely your form will have more inputs than this, for that, you'll be writing the whole form template yourself.
The issue is that {{ wtf.quick_form(form) }} is calling wtf.form_field() on your FieldList additional in A instead of calling it on additional's subfields. Because of this, I don't think you will be able to use wtf.quick_form() on your particular form.
Instead, try templating your form like this:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Grants - Find Grant{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Specify</h1>
</div>
<div class="col-md-4">
<form class="form form-horizontal" method="post" role="form">
{{ form.hidden_tag() }}
{{ wtf.form_errors(form, hiddens="only") }}
{% for subfield in form.additional %}
{{ wtf.form_field(subfield) }}
{% endfor %}
{{ wtf.form_field(form.submit) }}
</form>
</div>
{% endblock %}
You can read more about wtf.form_field() on the Flask-Bootstrap documentation site.

'for' loop through form fields and excluding one of the fields with 'if'

The problem I'm struggling with is as follows:
I have:
{% for field in form %}
{{ field }}
{% end for %}
What I want is to put an 'if' statement to exclude a field which .label or whatever is provided. Like:
{% for field in form%}
{% if field == title %}
{% else %}
{{ field }}
{% endif %}
{% endfor %}
Is it possible? I have to many fields to write them one by one and only one or two to exclude.
Thank you for any tips.
BR,
Czlowiekwidmo.
Yes, this should be possible:
{% for field in form %}
{% ifnotequal field.label title %}
{{ field }}
{% endifnotequal %}
{% endfor %}
Django's template tags offer ifequal and ifnotequal variants, and you can test the field.label against either a context variable, or a string.
You might be a lot happier creating a subclass of the form, excluding the offending field.
See http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#form-inheritance
class SmallerForm( MyForm ):
class Meta(MyForm.Meta):
exclude = [ title ]
{% for field in form %}
{% if field.name != 'field_name' %}
{{ field }}
{% endif %}
{% endfor %}

Categories