Changeset 1691
- Timestamp:
- 07/18/08 12:58:51 (20 months ago)
- Location:
- trunk/pylucid
- Files:
-
- 8 modified
-
media/PyLucid/internal_page/blog/display_blog.css (modified) (1 diff)
-
media/PyLucid/internal_page/blog/display_blog.html (modified) (2 diffs)
-
media/PyLucid/internal_page/blog/mod_comments.html (modified) (1 diff)
-
media/PyLucid/internal_page/blog/notify_mailtext.html (modified) (1 diff)
-
PyLucid/plugins_internal/blog/blog.py (modified) (23 diffs)
-
PyLucid/plugins_internal/blog/blog_cfg.py (modified) (3 diffs)
-
PyLucid/system/page_msg.py (modified) (5 diffs)
-
PyLucid/tools/newforms_utils.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/pylucid/media/PyLucid/internal_page/blog/display_blog.css
r1688 r1691 112 112 margin: 0px; 113 113 } 114 .comment .admin_info_line { 115 color:red; 116 line-height: 0px; 117 } 114 118 /* -------------------------------------------------------------------------- */ 115 119 #input_fields { -
trunk/pylucid/media/PyLucid/internal_page/blog/display_blog.html
r1688 r1691 2 2 {% if create_url %}<p><a href="{{ create_url }}" class="action_link">create a new blog entry</a></p>{% endif %} 3 3 4 {% if not entries %}no blog entry exists{% endif %} 4 5 {% for entry in entries %} 5 6 <fieldset class="entry"><legend class="headline"><a href="{{ entry.detail_url }}">{{ entry.headline }}</a></legend> … … 45 46 {{ comment.person_name }}{% if comment.homepage %}</a>{% endif %}: 46 47 </legend> 48 {% if not comment.is_public %} 49 <p class="admin_info_line">not public</p> 50 {% endif %} 47 51 48 52 <div class="admin_links"> 49 53 {% if comment.edit_url %}<a href="{{ comment.edit_url }}">edit</a>{% endif %} 54 {% if comment.delete_url %}<a href="{{ comment.delete_url }}" onClick="return confirm('Realy want to delete the comment entry?');">delete</a>{% endif %} 50 55 </div> 51 56 -
trunk/pylucid/media/PyLucid/internal_page/blog/mod_comments.html
r1688 r1691 3 3 {% for comment in comments %} 4 4 <li> 5 <a href="{{ comment.edit_url }}">{{ comment }}</a> 5 <a href="{{ comment.edit_url }}">edit</a> 6 {{ comment.content }} 7 {{ comment.blog_entry.headline }} 6 8 </li> 7 9 {% endfor %} -
trunk/pylucid/media/PyLucid/internal_page/blog/notify_mailtext.html
r1688 r1691 9 9 IP Address...: {{ comment_entry.ip_address }} 10 10 submit time..: {{ comment_entry.createtime }} 11 {% if is_spam %} 12 This comment is detected as SPAM. It is not saved into the database! 13 {% else %} 14 Edit this new comment: {{ edit_url }} 15 {% endif %} 11 12 --[submit messages]------------------------------------------------------------ 13 {% for line in submit_msg %} 14 {{ line }} 15 {% endfor %} 16 --[submit messages end]-------------------------------------------------------- 17 18 {% if edit_url %}Edit this new comment: {{ edit_url }}{% else %}This comment was not saved into the database.{% endif %} 19 16 20 --[comment content]------------------------------------------------------------ 17 21 {{ comment_entry.content }} -
trunk/pylucid/PyLucid/plugins_internal/blog/blog.py
r1688 r1691 32 32 from PyLucid.system.BasePlugin import PyLucidBasePlugin 33 33 from PyLucid.tools.content_processors import apply_markup 34 from PyLucid.tools.newforms_utils import StripedCharField 34 35 from PyLucid.tools.utils import escape_django_tags 36 from PyLucid.system.page_msg import PageMessages 35 37 from PyLucid.models.Page import MARKUPS 38 39 from PyLucid.plugins_internal.blog.blog_cfg import DONT_CHECK, REJECT_SPAM, \ 40 MODERATED 36 41 37 42 # Don't send mails, display them only. … … 50 55 ip_address = models.IPAddressField(_('ip address'),) 51 56 person_name = models.CharField( 52 _("person's name"), max_length=50 57 _("person's name"), max_length=50, 58 help_text=_("Your full name (will be published) (required)"), 53 59 ) 54 60 email = models.EmailField( 55 61 _('e-mail address'), 56 help_text=_("Only for internal use. "),62 help_text=_("Only for internal use. (will not be published) (required)"), 57 63 ) 58 64 homepage = models.URLField( … … 90 96 91 97 98 92 99 class BlogCommentForm(forms.ModelForm): 93 100 """ 94 Add a comment.101 Add a new comment. 95 102 """ 96 103 person_name = forms.CharField( … … 98 105 help_text=_("Your name."), 99 106 ) 100 content = forms.CharField(107 content = StripedCharField( 101 108 label = _('content'), min_length=5, max_length=3000, 102 109 help_text=_("Your comment to this blog entry."), … … 107 114 model = BlogComment 108 115 # Using a subset of fields on the form 109 fields = ('person_name', 'email', "homepage", "comment") 110 116 fields = ('person_name', 'email', "homepage") 117 118 119 class AdminCommentForm(BlogCommentForm): 120 """ 121 Form for editing a existing comment. Only for Admins 122 """ 123 class Meta: 124 model = BlogComment 125 fields = ( 126 'ip_address', 'person_name', 'email', "homepage", 127 "content", "is_public", 128 "createtime", "lastupdatetime", "createby", "lastupdateby" 129 ) 111 130 112 131 #______________________________________________________________________________ … … 244 263 245 264 265 246 266 class blog(PyLucidBasePlugin): 247 267 … … 251 271 super(blog, self).__init__(*args, **kwargs) 252 272 273 # Log info about handling blog comment submissions 274 self.submit_msg = PageMessages( 275 self.request, use_django_msg=False, html=False 276 ) 277 253 278 # Get the default preference entry. 254 279 self.preferences = self.get_preferences() … … 258 283 259 284 260 def _add_comment_ edit_url(self, comments):285 def _add_comment_admin_urls(self, comments): 261 286 for comment in comments: 262 287 comment.edit_url = self.URLs.methodLink( 263 288 "edit_comment", comment.id 289 ) 290 comment.delete_url = self.URLs.methodLink( 291 "delete_comment", comment.id 264 292 ) 265 293 … … 287 315 if self.request.user.is_staff: 288 316 comments = comments.all() 289 self._add_comment_ edit_url(comments)317 self._add_comment_admin_urls(comments) 290 318 else: 291 319 comments = comments.filter(is_public = True).all() … … 347 375 348 376 self.current_page.title += " - " + blog_entry.headline 349 350 377 351 378 if blog_entry.is_public != True: … … 363 390 #self.page_msg(self.request.POST) 364 391 if form.is_valid(): 365 ok = self._save_new_comment(blog_entry, form) 392 ok = self._save_new_comment( 393 blog_entry, clean_data = form.cleaned_data 394 ) 366 395 if ok: 367 396 return self._list_entries([blog_entry], full_comments=True) … … 437 466 blog_obj.save() 438 467 self.page_msg.green("New blog entry created.") 468 tags_string = form.cleaned_data["tags"] 439 469 else: 440 470 # Update a existing blog entry 471 tags_string = form.cleaned_data.pop("tags") 472 self.page_msg.green("Update existing blog entry.") 441 473 blog_obj.lastupdateby = self.request.user 442 474 for k,v in form.cleaned_data.iteritems(): 443 475 setattr(blog_obj, k, v) 444 self.page_msg.green("Update existing blog entry.") 445 446 tags_string = form.cleaned_data["tags"] 476 447 477 tag_objects, new_tags = BlogTag.objects.get_or_creates( 448 478 tags_string … … 525 555 # COMMENTS 526 556 527 def _send_notify(self, mail_title, blog_entry, is_spam,comment_entry):557 def _send_notify(self, mail_title, blog_entry, comment_entry): 528 558 """ 529 559 Send a email noitify for a submited blog comment. … … 534 564 self.URLs.methodLink("edit", blog_entry.id) 535 565 ), 536 "is_spam": is_spam,537 566 "comment_entry": comment_entry, 567 "submit_msg": self.submit_msg, 538 568 } 539 569 540 if not is_spam:570 if hasattr(comment_entry, "id"): 541 571 # Add edit link into the mail 542 572 email_context["edit_url"] = self.URLs.make_absolute_url( … … 554 584 555 585 send_mail_kwargs = { 586 "from_email": settings.DEFAULT_FROM_EMAIL, 556 587 "subject": "%s %s" % (settings.EMAIL_SUBJECT_PREFIX, mail_title), 557 588 # from_email = sender, … … 569 600 return 570 601 else: 571 send_mail(message = emailtext,**send_mail_kwargs) 572 573 def _check_spam(self, blog_entry, form_cleaned_data, content_lower): 574 """ 575 Check if the submitted comment is spam. 576 Display error messages and handle email notify. 577 """ 578 contains_spam = self._check_wordlist( 579 content_lower, pref_key = "spam_keywords" 580 ) 581 if not contains_spam: 582 # The submitted content contains no spam keyword 583 return False 584 585 self.page_msg.red("Sorry, your comment identify as spam.") 586 602 send_mail(message = emailtext, **send_mail_kwargs) 603 604 def _reject_spam_comment(self, blog_entry, clean_data): 605 """ 606 Reject a submited comment as spam: 607 1. Display page_msg 608 2. Handle email notify. 609 """ 587 610 if not self.preferences["spam_notify"]: 588 611 # Don't send spam notify email 589 return True612 return 590 613 591 614 # Add ID Adress for notify mail text 592 form_cleaned_data["ip_address"] = self.request.META.get('REMOTE_ADDR')593 form_cleaned_data["createtime"] = datetime.datetime.now()615 clean_data["ip_address"] = self.request.META.get('REMOTE_ADDR') 616 clean_data["createtime"] = datetime.datetime.now() 594 617 595 618 self._send_notify( 596 619 mail_title = _("blog comment as spam detected."), 597 blog_entry = blog_entry, is_spam = True, 598 comment_entry = form_cleaned_data 599 ) 600 return True 601 602 def _save_new_comment(self, blog_entry, form): 620 blog_entry = blog_entry, comment_entry = clean_data 621 ) 622 623 def _check_comment_submit(self, blog_entry, content): 624 """ 625 Check the submit of a new blog comment 626 """ 627 if self.request.user.is_staff: 628 # Don't check comments from staff users 629 self.submit_msg("comment submit by page member.") 630 return _("new blog comment from page member published.") 631 632 # Check the http referer, exception would be raised if something wrong 633 self._check_referer(blog_entry) 634 635 content_lower = content.lower() 636 637 # check SPAM keywords 638 spam_keyword = self._check_wordlist( 639 content_lower, pref_key = "spam_keywords" 640 ) 641 if spam_keyword: 642 raise RejectSpam( 643 "Comment contains SPAM keyword: '%s'" % spam_keyword 644 ) 645 646 # check mod_keywords 647 mod_keyword = self._check_wordlist( 648 content_lower, pref_key = "mod_keywords" 649 ) 650 if mod_keyword: 651 raise ModerateSubmit( 652 "Comment contains mod_keyword: '%s'" % mod_keyword 653 ) 654 655 656 657 def _save_new_comment(self, blog_entry, clean_data): 603 658 """ 604 659 Save a valid submited comment form into the database. … … 609 664 Send notify emails. 610 665 """ 611 content = form.cleaned_data["content"] 612 content = content.strip() 613 content_lower = content.lower() 614 615 if self.request.user.is_staff: 616 # Don't check comments from staff users 666 content = clean_data["content"] 667 668 try: 669 mail_title = self._check_comment_submit(blog_entry, content) 670 except RejectSpam, msg: 671 self.page_msg.red("Sorry, your comment identify as spam.") 672 self.submit_msg(msg) 673 # Display page_msg and handle email notify: 674 self._reject_spam_comment(blog_entry, clean_data) 675 return False 676 except ModerateSubmit, msg: 677 self.page_msg(_("Your comment must wait for authorization.")) 678 mail_title = _("Blog comment moderation needed.") 679 self.submit_msg(msg) 680 is_public = False 681 else: 682 self.submit_msg("Blog comment published.") 683 mail_title = _("Blog comment published.") 617 684 is_public = True 618 mail_title = _("new blog comment from page member published.")619 else:620 is_spam = self._check_spam(621 blog_entry, form.cleaned_data, content_lower622 )623 if is_spam != False:624 # Is spam: page_msg and notify was handled by _ckeck_spam()625 return False626 627 should_moderated = self._check_wordlist(628 content_lower, pref_key = "mod_keywords"629 )630 if should_moderated:631 self.page_msg(_("Your comment must wait for authorization."))632 mail_title = _("new blog comment waits for moderation.")633 is_public = False634 else:635 mail_title = _("blog comment published.")636 is_public = True637 685 638 686 content = escape_django_tags(content) … … 641 689 blog_entry = blog_entry, 642 690 ip_address = self.request.META.get('REMOTE_ADDR'), 643 person_name = form.cleaned_data["person_name"],644 email = form.cleaned_data["email"],645 homepage = form.cleaned_data["homepage"],691 person_name = clean_data["person_name"], 692 email = clean_data["email"], 693 homepage = clean_data["homepage"], 646 694 content = content, 647 695 is_public = is_public, … … 653 701 # Send a notify email 654 702 self._send_notify( 655 mail_title, blog_entry, is_spam=False,comment_entry=new_comment656 ) 657 658 self.page_msg.green(" comment saved.")703 mail_title, blog_entry, comment_entry=new_comment 704 ) 705 706 self.page_msg.green("Your comment saved.") 659 707 return True 660 708 … … 674 722 def _check_wordlist(self, content, pref_key): 675 723 """ 676 Simple check, if the content contains one keyword. 724 Simple check, if the content contains one of the keywords. 725 If a keyword found, returns it else returns None 677 726 """ 678 727 keywords = self._get_wordlist(pref_key) 679 728 for keyword in keywords: 680 729 if keyword in content: 681 return True 682 return False 683 684 def edit_comment(self, urlargs): 685 """ 686 Edit a comment (only for admins) 730 return keyword 731 732 def _check_referer(self, blog_entry): 733 """ 734 Check if the referer is ok. 735 raise RejectSpam() or ModerateSubmit() if referer is wrong. 736 """ 737 check_referer = self.preferences["check_referer"] 738 if check_referer == DONT_CHECK: 739 # We should not check the referer 740 return 741 742 referer = self.request.META["HTTP_REFERER"] 743 should_be = self.URLs.make_absolute_url( 744 self.URLs.methodLink("detail", blog_entry.id) 745 ) 746 self.submit_msg("http referer: '%s' - '%s'" % (referer, should_be)) 747 748 if referer == should_be: 749 # Referer is ok 750 return 751 752 msg = "Wrong http referer" 753 754 # Something wrong with the referer 755 if check_referer == REJECT_SPAM: 756 # We should it rejected as spam 757 raise RejectSpam(msg) 758 elif check_referer == MODERATED: 759 # We should moderate the comment 760 raise ModerateSubmit(msg) 761 else: 762 # Should never appear 763 raise AttributeError("Wrong check_referer value?!?") 764 765 def _delete_comment(self, comment_entry): 766 """ 767 Delete one comment entry. Display page_msg. 768 Used in delete_comment() and edit_comment(). 769 """ 770 old_id = comment_entry.id 771 comment_entry.delete() 772 self.page_msg.green(_("Comment entry %s deleted." % old_id)) 773 774 def delete_comment(self, urlargs): 775 """ 776 Delete a comment (only for admins) 687 777 """ 688 778 comment_entry = self._get_entry_from_url(urlargs, model=BlogComment) … … 691 781 return 692 782 693 CommentForm = forms.form_for_instance(comment_entry)694 695 783 blog_entry = comment_entry.blog_entry # ForeignKey("BlogEntry") 696 784 785 self._delete_comment(comment_entry) 786 787 return self._list_entries( 788 [blog_entry], context={}, full_comments=True 789 ) 790 791 792 def edit_comment(self, urlargs): 793 """ 794 Edit a comment (only for admins) 795 """ 796 comment_entry = self._get_entry_from_url(urlargs, model=BlogComment) 797 if not comment_entry: 798 # Wrong url, page_msg was send to the user 799 return 800 801 # CommentForm = AdminCommentForm 802 # 803 # 804 # CommentForm = forms.form_for_instance( 805 # instance=comment_entry#, form=BlogCommentForm 806 # ) 807 808 blog_entry = comment_entry.blog_entry # ForeignKey("BlogEntry") 809 697 810 if self.request.method == 'POST': 698 form = CommentForm(self.request.POST) 811 # form = CommentForm(self.request.POST) 812 form = AdminCommentForm(self.request.POST, instance=comment_entry) 699 813 #self.page_msg(self.request.POST) 700 814 if form.is_valid(): 701 815 if "delete" in self.request.POST: 702 comment_entry.delete() 703 self.page_msg.green("Comment deleted.") 816 self._delete_comment(comment_entry) 704 817 else: 705 818 form.save() 706 819 self.page_msg.green("Saved.") 707 return self._list_entries([blog_entry], context={}, full_comments=True) 820 return self._list_entries( 821 [blog_entry], context={}, full_comments=True 822 ) 708 823 else: 709 form = CommentForm() 824 # form = CommentForm() 825 form = AdminCommentForm(instance=comment_entry) 710 826 711 827 context = { … … 725 841 726 842 comments = BlogComment.objects.filter(is_public=False) 727 self._add_comment_edit_url(comments) 728 self.page_msg(comments) 843 self._add_comment_admin_urls(comments) 729 844 730 845 context = { … … 733 848 734 849 self._render_template("mod_comments", context)#, debug=2) 850 851 852 853 class WrongReferer(Exception): 854 """ 855 A comment submit was made with a wrong http referer information 856 """ 857 pass 858 859 class RejectSpam(Exception): 860 """ 861 A submission was identify as SPAM 862 """ 863 pass 864 865 class ModerateSubmit(Exception): 866 """ 867 A submitted comment should be moderated 868 """ 869 pass -
trunk/pylucid/PyLucid/plugins_internal/blog/blog_cfg.py
r1688 r1691 18 18 19 19 from PyLucid.models.Page import MARKUPS 20 21 DONT_CHECK = 0 22 REJECT_SPAM = 1 23 MODERATED = 2 24 25 ACTIONS = ( 26 (DONT_CHECK, _("don't check")), 27 (REJECT_SPAM, _("reject as spam")), 28 (MODERATED, _("hide, for later moderation")), 29 ) 20 30 21 31 class PreferencesForm(forms.Form): … … 93 103 ) 94 104 105 check_referer = forms.ChoiceField( 106 choices = ACTIONS, 107 initial = MODERATED, 108 help_text = _( 109 "What to do, if http referer contains not your domain?" 110 ), 111 ) 95 112 96 113 # Optional, this Plugin can't have multiple preferences … … 139 156 "must_admin": True, 140 157 }, 158 "delete_comment": { 159 "must_login": True, 160 "must_admin": True, 161 }, 141 162 "mod_comments": { 142 163 "must_login": True, -
trunk/pylucid/PyLucid/system/page_msg.py
r1634 r1691 2 2 3 3 """ 4 A small Wrapper aound djangos user messages system: 5 http://www.djangoproject.com/documentation/authentication/#messages 4 The PyLucid page message system 5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 6 7 enhanced features: 8 - easy callable to print a messages 9 - simple color output: self.page_msg.green() 10 - use pprint for dicts and lists 11 - special debug mode: Inserts informationen, where from the message has come. 7 A small Wrapper aound djangos user messages system. 12 8 13 In PyLucid modules/plugins, you can use the old system, but it use the django 14 messages to store the data: 15 self.page_msg("I am a new django user message in the old PyLucid style ;)") 16 self.page_msg.red("Alert!") 9 enhanced features: 10 - easy callable to print a messages 11 - simple color output: self.page_msg.green() 12 - use pprint for dicts and lists 13 - special debug mode: 14 Inserts informationen, where from the message has come. 15 16 Can also used in Plugin for storing internal messages. 17 18 Links 19 ~~~~~ 20 http://www.pylucid.org/_goto/134/plugin-output/ 21 http://www.djangoproject.com/documentation/authentication/#messages 17 22 18 23 19 Last commit info:20 ---------------------------------- 21 $LastChangedDate$22 $Rev$23 $Author$24 Last commit info: 25 ~~~~~~~~~~~~~~~~~ 26 $LastChangedDate$ 27 $Rev$ 28 $Author$ 24 29 25 Created by Jens Diemer 26 27 license: 28 GNU General Public License v2 or above 29 http://www.opensource.org/licenses/gpl-license.php 30 :copyleft: 2008 by the PyLucid team, see AUTHORS for more details. 31 :license: GNU GPL v3 or above, see LICENSE for more details. 30 32 """ 31 33 … … 43 45 class PageMessages(object): 44 46 """ 45 http://www.djangoproject.com/documentation/authentication/#messages47 The page message container. 46 48 """ 47 def __init__(self, request): 48 try: 49 self.messages = request.user.get_and_delete_messages() 50 except AttributeError: 51 # In the _install section we have no user 52 self.messages = [] 49 def __init__(self, request, use_django_msg=True, html=True): 50 self.html = html # Should we generate colored html output? 51 52 self.messages = [] 53 if use_django_msg: 54 try: 55 self.messages = request.user.get_and_delete_messages() 56 except AttributeError: 57 # In the _install section we have no user 58 pass 53 59 54 60 self.debug_mode = getattr(request, "debug", False) … … 80 86 81 87 def append_color_data(self, color, *msg): 82 msg = '<span style="color:%s;">%s</span>' % ( 83 color, self.prepare(*msg) 84 ) 88 if self.html: 89 msg = '<span style="color:%s;">%s</span>' % ( 90 color, self.prepare(*msg) 91 ) 92 else: 93 msg = self.prepare(*msg) 94 85 95 #~ self.request.user.message_set.create(message=msg) 86 96 msg = mark_safe(msg) # turn djngo auto-escaping off … … 130 140 for line in item: 131 141 line = self.encode_and_prepare(line) 132 result.append("%s<br />\n" % line) 142 if self.html: 143 result.append("%s<br />\n" % line) 144 else: 145 result.append("%s\n" % line) 133 146 else: 134 147 item = self.encode_and_prepare(item) … … 150 163 151 164 return escape(txt) 152 153 165 154 166 #________________________________________________________________ -
trunk/pylucid/PyLucid/tools/newforms_utils.py
r1675 r1691 84 84 85 85 86 class StripedCharField(forms.CharField): 87 """ 88 Same as forms.CharField but stripes the output. 89 90 >>> f = StripedCharField() 91 >>> f.clean('\\n\\n[\\nTEST\\n]\\n\\n') 92 u'[\\nTEST\\n]' 93 """ 94 def clean(self, value): 95 value = super(StripedCharField, self).clean(value) 96 return value.strip() 97 98 86 99 if __name__ == "__main__": 87 100 import doctest