Code

Changes between Version 6 and Version 7 of UsingFreeComment


Ignore:
Timestamp:
06/17/06 19:30:59 (8 years ago)
Author:
tyson@…
Comment:

Completely rewritten for comprehensiveness. Surely I've missed a few things, though.

Legend:

Unmodified
Added
Removed
Modified
  • UsingFreeComment

    v6 v7  
    1 == Using the FreeComment application integrated to Django. == 
    2  
    3 If you are using your own views and not Django's built-in generic views, you'll need to import FreeComment in views.py: 
    4  
    5 {{{ 
    6 #!python 
    7 from django.contrib.comments.models import FreeComment 
    8 }}} 
    9  
    10 Edit your settings.py 
     1= Using Django's Free Comments = 
     2 
     3Django includes some basic commenting functionality that can save you a ton of time if you want to allow users to add comments to objects such as blog entries or photos. Django's free comments are flexible enough that they can be used on pretty much anything. 
     4 
     5== Set Up == 
     6 
     7The first thing you'll need to do is add Django's comment packages to your INSTALLED_APPS in "settings.py": 
     8 
    119{{{ 
    1210#!python 
     
    1614) 
    1715}}} 
    18 In your html template you can use the comment system. 
    19 Remember a comment is going to be link to an entry id , for any of your model, it could be a blog post or a recipe. 
    20 Add this to your template file 
    21 {{{ 
    22 {% load comments %} 
    23 }}} 
    24  
    25 to display the comments for the current entry wich is a recipe object '''r'''. 
    26 '''recettes''' is the app name 
    27 '''recipe''' the model in models.py 
    28 {{{ 
    29 {% get_free_comment_list for recettes.recipe r.id as comment_list %} 
    30 {% if comment_list %} 
    31     {% for comment in comment_list %} 
    32          {{ comment.person_name }} 
    33          {{ comment.submit_date|date:"j F, Y" }}  
    34          {{ comment.submit_date|date:"P" }} 
    35          {{ comment.comment|escape|urlizetrunc:40|linebreaks }}  
    36     {% endfor %} 
     16 
     17If you're using custom views and not generic views, you'll need to add the following to the top of the relevant "urls.py" file. Generic views already include FreeComment, so you don't have to import it yourself. 
     18 
     19{{{ 
     20#!python 
     21from django.contrib.comments.models import FreeComment 
     22}}} 
     23 
     24Add the following URL pattern to your site-wide "urls.py" file: 
     25 
     26{{{ 
     27#!python 
     28urlpatterns = patterns('', 
     29        [...] 
     30        (r'^comments/', include('django.contrib.comments.urls.comments')), 
     31} 
     32}}} 
     33 
     34In any template file in which you want to access comments, you'll have to load the comments packages before you access them with: 
     35 
     36{{{ 
     37{% load comments.comments %} 
     38}}} 
     39 
     40Below that, you're free to access the comments. 
     41 
     42== Adding Comment Counts to List and Archive Pages == 
     43 
     44The only data you need to access an object's comments is that object's id. If you have that, you can get the comments themselves, comment count, and other info. 
     45 
     46=== django.views.generic.list_detail.object_list === 
     47 
     48In an object_list template, you can do the following to add the comment count to each of the blog entry listings. The following example assumes you have an app named "blog" with a class called "entry", which has fields called "title", "summary", and has a method called "get_absolute_url" which returns an absolute path to that entry's detail page. 
     49 
     50{{{ 
     51<ul> 
     52        {% for object in object_list %} 
     53                {% get_free_comment_count for blog.entry object.id as comment_count %} 
     54                <li> 
     55                        <h2><a href="{{ object.url }}">{{ object.title }}</a></h2> 
     56                        <p class="description">{{ object.summary}}</p> 
     57                        <p class="details"><a href="{{ object.get_absolute_url }}">{{ comment_count }} Comments</a></p> 
     58                </li> 
     59        {% endfor %} 
     60</ul> 
     61}}} 
     62 
     63=== django.views.generic.date_based.archive_index === 
     64 
     65An archive_index generic view works almost exactly the same, except you're iterating through objects from the "latest" collection instead of the "object_list" collection: 
     66 
     67{{{ 
     68<ul> 
     69        {% for object in latest %} 
     70                {% get_free_comment_count for blog.entry object.id as comment_count %} 
     71                [...] 
     72        {% endfor %} 
     73</ul> 
     74}}} 
     75 
     76In the date-based archives such as archive_year or archive_month, the collection you iterate through is called "object_list". archive_index is the only generic view with "latest". 
     77 
     78== Adding Comments to Detail Pages == 
     79 
     80Typically, you'll allow users to add comments through the detail page for an object. It's possible to allow them to do it elsewhere, but for simplicity's sake, this example only shows how to do it on detail pages. For any of the "detail" generic views such as django.views.generic.list_detail.object_detail or django.views.generic.date_based.object_detail, you'll have the object's id as "object.id", so getting the comment count is the same: 
     81 
     82{{{ 
     83{% get_free_comment_count for Blog.entry object.id as comment_count %} 
     84}}} 
     85 
     86To get the list of comments, you call the following, which puts the list of comments in "comment_list": 
     87 
     88{{{ 
     89{% get_free_comment_list for blog.entry object.id as comment_list %} 
     90}}} 
     91 
     92Each comment object in comment_list has the following bits of data: 
     93 
     94 * '''comment.person_name''' - The comment poster's name. 
     95 * '''comment.submit_date''' - The date and time the poster submitted the comment. You can pipe this through the "date" filter to format the date. (Shown in the example below) 
     96 * '''comment.comment''' - The actual comment text. Don't forget to escape this to prevent code-injection attacks with the "escape" filter. (Shown in the example below) 
     97 * '''comment.is_public''' - Whether or not the comment is public. (TODO: How do we set a comment's public or non-public status?) 
     98 * '''comment.ip_address''' - The comment author's IP address. 
     99 * '''comment.approved''' - Whether or not this comment has been approved by a staff member. (TODO: Where is this set or modified?) 
     100 
     101And the following built-in methods: 
     102 
     103 * '''comment.get_absolute_url''' - Returns an absolute URL to this comment by way of the content object's detail page. If a comment is attached to a blog entry located at "/blog/some-slug", this URL will look something like "/blog/some-slug/#c4", where "4" is the comments id number. 
     104 * '''comment.get_content_object''' - Returns the object that this comment is a comment on. 
     105 
     106As of this writing, the free comments don't allow for you to specify other bits of data to be included, such as the comment poster's e-mail address or URL. This may be changed in the future. 
     107 
     108=== Example === 
     109 
     110{{{ 
     111{% get_free_comment_count for blog.entry object.id as comment_count %} 
     112 
     113<h2><a href="{{ object.url }}">{{ object.title }}</a></h2> 
     114 
     115<em>{{ object.description }}</em> 
     116 
     117<div class="article_menu"> 
     118        <b>Added on {{ object.add_date|date:"F j, Y" }}</b>  
     119        <a href="{{ object.get_absolute_url }}#comments">{{ comment_count }} Comment{{ comment_count|pluralize }}</a> 
     120</div> 
     121 
     122{% get_free_comment_list for blog.entry object.id as comment_list %} 
     123 
     124<h2 id="comments">Comments</h2> 
     125{% for comment in comment_list %} 
     126        <div class="comment_{% cycle odd,even %}" id="c{{ comment.id }}"> 
     127                <span class="comnum"><a id="c{{ comment.id }}" href="#c{{ comment.id }}">#{{ forloop.counter }}</a></span> 
     128                <p><b>{{ comment.person_name }}</b> commented, on {{ comment.submit_date|date:"F j, Y" }} at {{ comment.submit_date|date:"P" }}:</p> 
     129                {{ comment.comment|escape|urlizetrunc:40|linebreaks }} 
     130        </div> 
     131{% endfor %} 
     132 
     133<h2>Post a comment</h2> 
     134{% free_comment_form for blog.entry object.id %} 
     135}}} 
     136 
     137== Free Comment Templates == 
     138 
     139Django has internal default templates for the various bits of comments-related code. (NOTE: Actually, I lied. Once [http://code.djangoproject.com/ticket/2177 these patches] are applied, it will. Until then, you'll have to specify your own templates for "free_preview.html" and "posted.html".) 
     140 
     141You can override any of these built in templates by creating a "comments/" folder in your templates folder with any or all of the following files: 
     142 
     143=== Post Comment Form (freeform.html) === 
     144 
     145This template holds the form code that is used by the user to post a comment. In the above example, this is included like so: 
     146 
     147{{{ 
     148<h2>Post a comment</h2> 
     149{% free_comment_form for blog.entry object.id %} 
     150}}} 
     151 
     152==== Example ==== 
     153 
     154{{{ 
     155{% if display_form %} 
     156        <form action="/comments/postfree/" method="post"> 
     157                <p>Your name: <input type="text" id="id_person_name" name="person_name" /></p> 
     158                <p>Comment:<br /><textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p> 
     159                <input type="hidden" name="options" value="{{ options }}" /> 
     160                <input type="hidden" name="target" value="{{ target }}" /> 
     161                <input type="hidden" name="gonzo" value="{{ hash }}" /> 
     162                <p><input type="submit" name="preview" value="Preview comment" /></p> 
     163        </form> 
    37164{% endif %} 
    38165}}} 
    39166 
    40 Here is a larger example where you cycle throught 2 colors to display the comments. 
    41  
    42 {{{ 
    43 {% get_free_comment_list for recettes.recipe r.id as comment_list %} 
    44 {% get_free_comment_count for recettes.recipe r.id as comment_count %} 
    45 {% if comment_list %} 
    46         <h3>Comments ({{comment_count}})</h3> 
    47         <br /> 
    48         {% for comment in comment_list %} 
    49                 <div class="{% cycle comment_even,comment_odd %}"  id="c{{forloop.counter}}"> 
    50                 <div class="comment_content"> 
    51                         <span class="comnum"><a id="{{forloop.counter}}" href="#c{{forloop.counter}}">#{{forloop.counter}}</a></span> 
    52                 <p>by<b> {{ comment.person_name }}</b>, the{{ comment.submit_date|date:"j F, Y" }} at {{ comment.submit_date|date:"P" }}</p> 
    53                 {{ comment.comment|escape|urlizetrunc:40|linebreaks }}  
    54         </div> 
    55         </div></div> 
    56         </div> 
    57         {% endfor %} 
     167=== Preview (free_preview.html) === 
     168 
     169This template is called when an user previews their comment. 
     170 
     171==== Example ==== 
     172 
     173{{{ 
     174<h1>Preview your comment</h1> 
     175 
     176<form action="../postfree/" method="post"> 
     177        {% if comment_form.has_errors %} 
     178            <p><strong style="color: red;">Please correct the following errors.</strong></p> 
     179        {% else %} 
     180            <div class="comment"> 
     181            {{ comment.comment|escape|urlizetrunc:"40"|linebreaks }} 
     182            <p class="date small">Posted by <strong>{{ comment.person_name }}</strong></p> 
     183            </div> 
     184 
     185            <p><input type="submit" name="post" value="Post public comment" /></p> 
     186 
     187            <h1>Or edit it again</h1> 
     188        {% endif %} 
     189 
     190        {% if comment_form.person_name.errors %} 
     191            {{ comment_form.person_name.html_error_list }} 
     192        {% endif %} 
     193 
     194        <p><label for="id_person_name">Your name:</label> {{ comment_form.person_name }}</p> 
     195 
     196        {% if comment_form.comment.errors %} 
     197                {{ comment_form.comment.html_error_list }} 
     198        {% endif %} 
     199 
     200        <p> 
     201                <label for="id_person_name">Comment:</label> 
     202                <br /> 
     203                {{ comment_form.comment }} 
     204        </p> 
     205         
     206        <input type="hidden" name="options" value="{{ options }}" /> 
     207        <input type="hidden" name="target" value="{{ target }}" /> 
     208        <input type="hidden" name="gonzo" value="{{ hash }}" /> 
     209         
     210        <p> 
     211                <input type="submit" name="preview" value="Preview revised comment" /> 
     212        </p> 
     213</form> 
     214}}} 
     215 
     216=== Posted Message (posted.html) === 
     217 
     218This template is shown after a user successfully posts a comment. You can access the comment object as "object". 
     219 
     220==== Example ==== 
     221 
     222{{{ 
     223<h1>Comment posted successfully</h1> 
     224 
     225<p>Thanks for contributing.</p> 
     226 
     227{% if object %} 
     228        <ul> 
     229                <li><a href="{{ object.get_absolute_url }}">View your comment</a></li> 
     230        </ul> 
    58231{% endif %} 
    59232}}} 
    60233 
    61 We have to append a submit comment form to this. 
    62  
    63 {{{ 
    64 Add a comment 
    65 {% free_comment_form for recettes.recipe r.id %}  
    66 }}} 
    67  
    68  
    69 To use our own comments template, create a comments folder into your template folder location. 
    70 In my case /home/greg/projects/cefinban/templates/comments 
    71 There you could  put your own '''freeform.html''', '''free_preview.html''', '''posted.html'''. 
    72 freeform.html is located in /django/contrib/comments/template/comments  
    73  
    74 freeform.html 
    75 {{{ 
    76 {% load i18n %} 
    77 {% if display_form %} 
    78 <form action="/comments/postfree/" method="post"> 
    79 <p>{% trans "Your name:" %} <input type="text" id="id_person_name" name="person_name" /></p> 
    80 <p>{% trans "Comment:" %}<br /><textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p> 
    81 <input type="hidden" name="options" value="{{ options }}" /> 
    82 <input type="hidden" name="target" value="{{ target }}" /> 
    83 <input type="hidden" name="gonzo" value="{{ hash }}" /> 
    84 <p><input type="submit" name="preview" value="{% trans "Preview comment" %}" /><input type="submit" name="post" value="{% trans "Submit" %}" /></p> 
    85 </form> 
    86 {% endif %} 
    87 }}} 
    88  
    89  
    90  
    91  
    92  
    93  
    94  
    95  
    96  
    97  
    98  
     234== Other Examples == 
     235 
     236=== List Recent Comments === 
     237 
     238The following code lists all the recent comments on your site, regardless of app. 
     239 
     240{{{ 
     241<h1>Recent comments</h1> 
     242 
     243<p> 
     244        {% if has_previous %} 
     245                <a href="?page={{ previous }}">Previous</a> |  
     246        {% endif %} 
     247         
     248        Page {{ page }} of {{ pages }}  
     249         
     250        {% if has_next %} 
     251                | <a href="?page={{ next }}">Next</a> 
     252        {% endif %} 
     253</p> 
     254 
     255{% for comment in object_list %} 
     256        <div class="comment" id="c{{ comment.id }}"> 
     257            <h3> 
     258                        <a href="{{ comment.get_absolute_url }}"> 
     259                                {{ comment.person_name }}  
     260                                <span class="small quiet"> 
     261                                        {{ comment.submit_date|date:"F j, Y" }} at {{ comment.submit_date|date:"P" }} 
     262                                </span> 
     263                        </a> 
     264                </h3> 
     265            {{ comment.comment|escape|urlizetrunc:"40"|linebreaks }} 
     266        </div> 
     267{% endfor %} 
     268 
     269<p> 
     270        {% if has_previous %} 
     271                <a href="?page={{ previous }}">Previous</a> |  
     272        {% endif %} 
     273         
     274        Page {{ page }} of {{ pages }}  
     275         
     276        {% if has_next %} 
     277                | <a href="?page={{ next }}">Next</a> 
     278        {% endif %} 
     279</p> 
     280}}}