4

I am trying to customize Django's comments form. Inside django.contrib.comments.forms I noticed that all the field forms are declared in the class CommentDetailForm, which is inherited from CommentSecurityForm. Then I think when I write the template tag {% get_comment_form for order as form %}, it's getting the class called CommentForm which inherits CommentDetailForm with a honeypot field.

I wanted to customize the comments form so that it only displays the comments field (and not the optional name, email, or URL fields). Those information will be given by the current logged in user. In fact, only logged in users with certain UserProfile.user_type (UserProfile has a foreign key to User) are allow to comment.

Any tips on how to achieve this? Looking at the source code of the Django's comments already scares me lol.

EDIT:

Here is how the comment template looks so far:

{% get_comment_form for order as form %}
    <form action = "{% comment_form_target %}" method = "post">
        {% csrf_token %}
        {{ form }}
        <input type = "submit" name = "submit" value = "Post">
    </form>

And the site looks like this

I want to hide Name, Email address, and URL.

hobbes3
  • 28,078
  • 24
  • 87
  • 116
  • `UserProfile` doesn't have a one-to-one with `User`? Also, if you're not worried about security, the simplest way is to just make the fields "hidden" in the template, and fill in the user etc. – agf Mar 27 '12 at 03:52
  • Well even if I do `{% render_comment_form for order %}` is there a way to hide it unless `User.profile` has a certain `user_type`? – hobbes3 Mar 27 '12 at 04:00
  • Oh you're right lol. Okay what about hiding the other fields? What do you mean make the fields "hidden" in the template? I will update my question to show you what I do right now. – hobbes3 Mar 27 '12 at 04:05

1 Answers1

3

You should be able to do all of this in the template:

{% ifequal User.profile.user_type "comment_type" %}
{% get_comment_form for order as form %}
  <form action="{% comment_form_target %}" method="post">
    {% csrf_token %}
    {% for field in form %}
    {% ifequal field.name "name" %}
        <input id="id_name" type="hidden" name="name" value="{{ user.username }}" />
    {% else %}{% ifequal field.name "email" %}
        <input type="hidden" name="email" value="{{ user.email }}" id="id_email" />
    {% else %}{{ field }}{% endifequal %}{% endifequal %}
    {% endfor %}    
        <input type="submit" name="submit" value="Post">
  </form>
{% endifequal %}
agf
  • 171,228
  • 44
  • 289
  • 238
  • I don't think I need to add the value for `name` or `email`. They are all optional. In fact, Django comments automatically does that (maybe somewhere in the `models.py`. How do I just *only* show the `comments` field (and yet still have the advantage of the hidden honeypot fields and the built-in security)? – hobbes3 Mar 27 '12 at 04:22
  • If you don't want to have a field at all, just do `{% ifequal field.name "name" %}{% else %} Handle the other fields here {% endifequal %}`. Just leave the main body of the `ifequal` blank. I'm not sure what I can add to what I included in the answer -- it allows you to control the form however you want. – agf Mar 27 '12 at 04:37
  • Okay I did it with `{% if field.name != "name" and field.name != "email" and field.name != "url" %}`, but is there a way to show it like `form.as_p`? I still want to add the honeypot field, but have Django hide it with `

    `. Or do I have to manually style it myself? In fact I would also like the `comment` field to be in `.as_p` format as well.

    – hobbes3 Mar 27 '12 at 06:05
  • I don't know what `form.as_p` is. – agf Mar 27 '12 at 06:07
  • [`Form.as_p`](https://docs.djangoproject.com/en/1.4/ref/forms/api/#django.forms.Form.as_p). When you do `{{ form }}`, it actually by default renders it as `form.as_p`. And Django automatically hides the `

    ` tag that wraps around the honeypot field.

    – hobbes3 Mar 27 '12 at 06:11
  • 2
    Nevermind, I figured it out by looking at the template `form.html` inside Django's comment framework under `django.contrib.comments`. Thanks for all your help! – hobbes3 Mar 27 '12 at 06:26
  • I'm going to have to actually use this on a site next week, so it helps me too :) – agf Mar 27 '12 at 06:28
  • One last question. Do you think it's better to write the custom html in the template with `{% get_comment_form for order as form %}` or override Django's `form.html` and just call `{% render_comment_form for order %}`? – hobbes3 Mar 27 '12 at 06:35
  • I don't actually know, but if it's sufficiently different it seems to me like it would be better to override the `form.html`. How would you do that? – agf Mar 27 '12 at 06:38
  • 1
    I'm using Django v1.4, but there is a similar example with [overriding the admin templates](https://docs.djangoproject.com/en/dev/intro/tutorial02/#customize-the-admin-look-and-feel) in the official Django tutorials. Basically you setup your `TEMPLATE_DIR` inside `settings.py` (I used `os.path.join( os.path.dirname( __file__ ), '..', 'templates' ).replace( '\\', '/' ),`), then inside your `template` folder, create another folder of the app whose template you want to override, then inside that folder add your template with the same name as the the one you want to override (`form.html`). – hobbes3 Mar 27 '12 at 06:42
  • 1
    So mine looks like `mysite/templates/comments/form.html`. I hope that helps! Remember in Django v1.4, my settings are in `mysite/mysite/settings.py`. That's why there is a `..` in my `os.path.dirname()` above. – hobbes3 Mar 27 '12 at 06:43
  • I'm not a fan of this approach, as its a "trust the user/browser" approach where the hidden fields are copying from the profile, but theres no guaranteed that what is sent back actually matches the user. It'd be too easy to spoof the post request and drop comments with false identies on unauthorized comment feeds – Shayne Jul 18 '21 at 15:13