diff options
author | luxagraf <sng@luxagraf.net> | 2017-10-14 11:36:20 -0500 |
---|---|---|
committer | luxagraf <sng@luxagraf.net> | 2017-10-14 11:36:20 -0500 |
commit | bd1adb4927695ed0ce3ac94d90c68bd61e440275 (patch) | |
tree | f014fa16a64eb55e62ecb92c62a4e8186cd318a4 /app/lib/django_comments_old | |
parent | cbadfff80be33b4ec67da57585451884c6378380 (diff) |
updated comments app and added caption to photo list view
Diffstat (limited to 'app/lib/django_comments_old')
-rw-r--r-- | app/lib/django_comments_old/__init__.py | 91 | ||||
-rw-r--r-- | app/lib/django_comments_old/admin.py | 87 | ||||
-rw-r--r-- | app/lib/django_comments_old/akismet.py | 105 | ||||
-rw-r--r-- | app/lib/django_comments_old/feeds.py | 32 | ||||
-rw-r--r-- | app/lib/django_comments_old/forms.py | 197 | ||||
-rw-r--r-- | app/lib/django_comments_old/managers.py | 22 | ||||
-rw-r--r-- | app/lib/django_comments_old/models.py | 204 | ||||
-rw-r--r-- | app/lib/django_comments_old/moderation.py | 357 | ||||
-rw-r--r-- | app/lib/django_comments_old/signals.py | 21 | ||||
-rw-r--r-- | app/lib/django_comments_old/templatetags/__init__.py | 0 | ||||
-rw-r--r-- | app/lib/django_comments_old/templatetags/comments.py | 334 | ||||
-rw-r--r-- | app/lib/django_comments_old/urls.py | 18 | ||||
-rw-r--r-- | app/lib/django_comments_old/views/__init__.py | 0 | ||||
-rw-r--r-- | app/lib/django_comments_old/views/comments.py | 140 | ||||
-rw-r--r-- | app/lib/django_comments_old/views/moderation.py | 165 | ||||
-rw-r--r-- | app/lib/django_comments_old/views/utils.py | 71 |
16 files changed, 0 insertions, 1844 deletions
diff --git a/app/lib/django_comments_old/__init__.py b/app/lib/django_comments_old/__init__.py deleted file mode 100644 index 225b195..0000000 --- a/app/lib/django_comments_old/__init__.py +++ /dev/null @@ -1,91 +0,0 @@ -from django.conf import settings -from django.core import urlresolvers -from django.core.exceptions import ImproperlyConfigured -from importlib import import_module - -DEFAULT_COMMENTS_APP = 'django_comments' - -def get_comment_app(): - """ - Get the comment app (i.e. "django_comments") as defined in the settings - """ - # Make sure the app's in INSTALLED_APPS - comments_app = get_comment_app_name() - if comments_app not in settings.INSTALLED_APPS: - raise ImproperlyConfigured("The COMMENTS_APP (%r) "\ - "must be in INSTALLED_APPS" % settings.COMMENTS_APP) - - # Try to import the package - try: - package = import_module(comments_app) - except ImportError as e: - raise ImproperlyConfigured("The COMMENTS_APP setting refers to "\ - "a non-existing package. (%s)" % e) - - return package - -def get_comment_app_name(): - """ - Returns the name of the comment app (either the setting value, if it - exists, or the default). - """ - return getattr(settings, 'COMMENTS_APP', DEFAULT_COMMENTS_APP) - -def get_model(): - from django_comments.models import Comment - """ - Returns the comment model class. - """ - if get_comment_app_name() != DEFAULT_COMMENTS_APP and hasattr(get_comment_app(), "get_model"): - return get_comment_app().get_model() - else: - return Comment - -def get_form(): - from django_comments.forms import CommentForm - """ - Returns the comment ModelForm class. - """ - if get_comment_app_name() != DEFAULT_COMMENTS_APP and hasattr(get_comment_app(), "get_form"): - return get_comment_app().get_form() - else: - return CommentForm - -def get_form_target(): - """ - Returns the target URL for the comment form submission view. - """ - if get_comment_app_name() != DEFAULT_COMMENTS_APP and hasattr(get_comment_app(), "get_form_target"): - return get_comment_app().get_form_target() - else: - return urlresolvers.reverse("django_comments.views.comments.post_comment") - -def get_flag_url(comment): - """ - Get the URL for the "flag this comment" view. - """ - if get_comment_app_name() != DEFAULT_COMMENTS_APP and hasattr(get_comment_app(), "get_flag_url"): - return get_comment_app().get_flag_url(comment) - else: - return urlresolvers.reverse("django_comments.views.moderation.flag", - args=(comment.id,)) - -def get_delete_url(comment): - """ - Get the URL for the "delete this comment" view. - """ - if get_comment_app_name() != DEFAULT_COMMENTS_APP and hasattr(get_comment_app(), "get_delete_url"): - return get_comment_app().get_delete_url(comment) - else: - return urlresolvers.reverse("django_comments.views.moderation.delete", - args=(comment.id,)) - -def get_approve_url(comment): - """ - Get the URL for the "approve this comment from moderation" view. - """ - if get_comment_app_name() != DEFAULT_COMMENTS_APP and hasattr(get_comment_app(), "get_approve_url"): - return get_comment_app().get_approve_url(comment) - else: - return urlresolvers.reverse("django_comments.views.moderation.approve", - args=(comment.id,)) diff --git a/app/lib/django_comments_old/admin.py b/app/lib/django_comments_old/admin.py deleted file mode 100644 index 8a5c063..0000000 --- a/app/lib/django_comments_old/admin.py +++ /dev/null @@ -1,87 +0,0 @@ -from __future__ import unicode_literals - -from django.contrib import admin -from django.contrib.auth import get_user_model -from django.utils.translation import ugettext_lazy as _, ungettext - -from django_comments.models import Comment -from django_comments import get_model -from django_comments.views.moderation import perform_flag, perform_approve, perform_delete - - -class UsernameSearch(object): - """The User object may not be auth.User, so we need to provide - a mechanism for issuing the equivalent of a .filter(user__username=...) - search in CommentAdmin. - """ - def __str__(self): - return 'user__%s' % get_user_model().USERNAME_FIELD - - -class CommentsAdmin(admin.ModelAdmin): - fieldsets = ( - (None, - {'fields': ('content_type', 'object_pk', 'site')} - ), - (_('Content'), - {'fields': ('user', 'user_name', 'user_email', 'user_url', 'comment')} - ), - (_('Metadata'), - {'fields': ('submit_date', 'ip_address', 'is_public', 'is_removed')} - ), - ) - - list_display = ('name', 'content_type', 'object_pk', 'ip_address', 'submit_date', 'is_public', 'is_removed') - list_filter = ('submit_date', 'site', 'is_public', 'is_removed') - date_hierarchy = 'submit_date' - ordering = ('-submit_date',) - raw_id_fields = ('user',) - search_fields = ('comment', UsernameSearch(), 'user_name', 'user_email', 'user_url', 'ip_address') - actions = ["flag_comments", "approve_comments", "remove_comments"] - - def get_actions(self, request): - actions = super(CommentsAdmin, self).get_actions(request) - # Only superusers should be able to delete the comments from the DB. - if not request.user.is_superuser and 'delete_selected' in actions: - actions.pop('delete_selected') - if not request.user.has_perm('django_comments.can_moderate'): - if 'approve_comments' in actions: - actions.pop('approve_comments') - if 'remove_comments' in actions: - actions.pop('remove_comments') - return actions - - def flag_comments(self, request, queryset): - self._bulk_flag(request, queryset, perform_flag, - lambda n: ungettext('flagged', 'flagged', n)) - flag_comments.short_description = _("Flag selected comments") - - def approve_comments(self, request, queryset): - self._bulk_flag(request, queryset, perform_approve, - lambda n: ungettext('approved', 'approved', n)) - approve_comments.short_description = _("Approve selected comments") - - def remove_comments(self, request, queryset): - self._bulk_flag(request, queryset, perform_delete, - lambda n: ungettext('removed', 'removed', n)) - remove_comments.short_description = _("Remove selected comments") - - def _bulk_flag(self, request, queryset, action, done_message): - """ - Flag, approve, or remove some comments from an admin action. Actually - calls the `action` argument to perform the heavy lifting. - """ - n_comments = 0 - for comment in queryset: - action(request, comment) - n_comments += 1 - - msg = ungettext('1 comment was successfully %(action)s.', - '%(count)s comments were successfully %(action)s.', - n_comments) - self.message_user(request, msg % {'count': n_comments, 'action': done_message(n_comments)}) - -# Only register the default admin if the model is the built-in comment model -# (this won't be true if there's a custom comment app). -if get_model() is Comment: - admin.site.register(Comment, CommentsAdmin) diff --git a/app/lib/django_comments_old/akismet.py b/app/lib/django_comments_old/akismet.py deleted file mode 100644 index daa4281..0000000 --- a/app/lib/django_comments_old/akismet.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/python - -__version__ = "0.3" -__date__ = "2005-12-01" -__author__ = "David Lynch (kemayo AT Google's mail service DOT com)" -__copyright__ = "Copyright 2005, David Lynch" -__license__ = "New BSD" -__history__ = """ -0.3 - 20051205 - Cleaned up __post. -0.2 - 20051201 - Added documentation, and tweaked the circumstances where an error - will be thrown. -0.1 - 20051201 - Initial release. Everything pretty much works. Probably. -""" - -import http.client -from urllib.parse import urlencode - -USERAGENT = "" -AKISMET_URL = "rest.akismet.com" -AKISMET_PORT = 80 - - -class AkismetError(Exception): - def __init__(self, response, statuscode): - self.response = response - self.statuscode = statuscode - - def __str__(self): - return repr(self.value) - - -def __post(request, host, path, port=80): - connection = http.client.HTTPConnection(host, port) - connection.request("POST", path, request, { - "User-Agent": "%s | %s/%s" % (USERAGENT, "Akistmet.py", __version__), - "Content-type": "application/x-www-form-urlencoded" - }) - response = connection.getresponse() - return response.read(), response.status - - -def verify_key(key, blog): - """Find out whether a given WordPress.com API key is valid. - Required parameters: - key: A WordPress.com API key. - blog: URL of the front page of the site comments will be submitted to. - Returns True if a valid key, False if invalid. - """ - response, status = __post("key=%s&blog=%s" % (key, blog), AKISMET_URL, "/1.1/verify-key", AKISMET_PORT) - if response == "valid": - return True - elif response == "invalid": - return False - else: - raise AkismetError(response, status) - - -def comment_check(key, blog, user_ip, user_agent, **other): - """Submit a comment to find out whether Akismet thinks that it's spam. - Required parameters: - key: A valid WordPress.com API key, as tested with verify_key(). - blog: URL of the front page of the site the comment will appear on. - user_ip: IP address of the being which submitted the comment. - user_agent: User agent reported by said being. - Suggested "other" keys: "permalink", "referrer", "comment_type", "comment_author", - "comment_author_email", "comment_author_url", "comment_content", and any other HTTP - headers sent from the client. - More detail on what should be submitted is available at: - http://akismet.com/development/api/ - Returns True if spam, False if ham. Throws an AkismetError if the server says - anything unexpected. - """ - request = {'blog': blog, 'user_ip': user_ip, 'user_agent': user_agent} - request.update(other) - response, status = __post(urlencode(request), "%s.%s" % (key, AKISMET_URL), "/1.1/comment-check", AKISMET_PORT) - if response == "true": - return True - elif response == "false": - return False - else: - raise AkismetError(response, status) - - -def submit_spam(key, blog, user_ip, user_agent, **other): - """Report a false negative to Akismet. - Same arguments as comment_check. - Doesn't return anything. Throws an AkismetError if the server says anything. - """ - request = {'blog': blog, 'user_ip': user_ip, 'user_agent': user_agent} - request.update(other) - response, status = __post(urlencode(request), "%s.%s" % (key, AKISMET_URL), "/1.1/submit-spam", AKISMET_PORT) - if status != 200 or response != "": - raise AkismetError(response, status) - - -def submit_ham(key, blog, user_ip, user_agent, **other): - """Report a false positive to Akismet. - Same arguments as comment_check. - Doesn't return anything. Throws an AkismetError if the server says anything. - """ - request = {'blog': blog, 'user_ip': user_ip, 'user_agent': user_agent} - request.update(other) - response, status = __post(urlencode(request), "%s.%s" % (key, AKISMET_URL), "/1.1/submit-ham", AKISMET_PORT) - if status != 200 or response != "": - raise AkismetError(response, status) diff --git a/app/lib/django_comments_old/feeds.py b/app/lib/django_comments_old/feeds.py deleted file mode 100644 index 0b8ce5b..0000000 --- a/app/lib/django_comments_old/feeds.py +++ /dev/null @@ -1,32 +0,0 @@ -from django.contrib.syndication.views import Feed -from django.contrib.sites.models import get_current_site -from django.utils.translation import ugettext as _ - -import django_comments - -class LatestCommentFeed(Feed): - """Feed of latest comments on the current site.""" - - def __call__(self, request, *args, **kwargs): - self.site = get_current_site(request) - return super(LatestCommentFeed, self).__call__(request, *args, **kwargs) - - def title(self): - return _("%(site_name)s comments") % dict(site_name=self.site.name) - - def link(self): - return "http://%s/" % (self.site.domain) - - def description(self): - return _("Latest comments on %(site_name)s") % dict(site_name=self.site.name) - - def items(self): - qs = django_comments.get_model().objects.filter( - site__pk = self.site.pk, - is_public = True, - is_removed = False, - ) - return qs.order_by('-submit_date')[:40] - - def item_pubdate(self, item): - return item.submit_date diff --git a/app/lib/django_comments_old/forms.py b/app/lib/django_comments_old/forms.py deleted file mode 100644 index b9249c0..0000000 --- a/app/lib/django_comments_old/forms.py +++ /dev/null @@ -1,197 +0,0 @@ -import time -from django import forms -from django.forms.utils import ErrorDict -from django.conf import settings -from django.contrib.contenttypes.models import ContentType -from django.utils.crypto import salted_hmac, constant_time_compare -from django.utils.encoding import force_text -from django.utils.text import get_text_list -from django.utils import timezone -from django.utils.translation import ungettext, ugettext, ugettext_lazy as _ - -from django_comments.models import Comment - -COMMENT_MAX_LENGTH = getattr(settings,'COMMENT_MAX_LENGTH', 3000) - -class CommentSecurityForm(forms.Form): - """ - Handles the security aspects (anti-spoofing) for comment forms. - """ - content_type = forms.CharField(widget=forms.HiddenInput) - object_pk = forms.CharField(widget=forms.HiddenInput) - timestamp = forms.IntegerField(widget=forms.HiddenInput) - security_hash = forms.CharField(min_length=40, max_length=40, widget=forms.HiddenInput) - - def __init__(self, target_object, data=None, initial=None): - self.target_object = target_object - if initial is None: - initial = {} - initial.update(self.generate_security_data()) - super(CommentSecurityForm, self).__init__(data=data, initial=initial) - - def security_errors(self): - """Return just those errors associated with security""" - errors = ErrorDict() - for f in ["honeypot", "timestamp", "security_hash"]: - if f in self.errors: - errors[f] = self.errors[f] - return errors - - def clean_security_hash(self): - """Check the security hash.""" - security_hash_dict = { - 'content_type' : self.data.get("content_type", ""), - 'object_pk' : self.data.get("object_pk", ""), - 'timestamp' : self.data.get("timestamp", ""), - } - expected_hash = self.generate_security_hash(**security_hash_dict) - actual_hash = self.cleaned_data["security_hash"] - if not constant_time_compare(expected_hash, actual_hash): - raise forms.ValidationError("Security hash check failed.") - return actual_hash - - def clean_timestamp(self): - """Make sure the timestamp isn't too far (> 2 hours) in the past.""" - ts = self.cleaned_data["timestamp"] - """ - if time.time() - ts > (2 * 60 * 60): - raise forms.ValidationError("Timestamp check failed") - """ - return ts - - def generate_security_data(self): - """Generate a dict of security data for "initial" data.""" - timestamp = int(time.time()) - security_dict = { - 'content_type' : str(self.target_object._meta), - 'object_pk' : str(self.target_object._get_pk_val()), - 'timestamp' : str(timestamp), - 'security_hash' : self.initial_security_hash(timestamp), - } - return security_dict - - def initial_security_hash(self, timestamp): - """ - Generate the initial security hash from self.content_object - and a (unix) timestamp. - """ - - initial_security_dict = { - 'content_type' : str(self.target_object._meta), - 'object_pk' : str(self.target_object._get_pk_val()), - 'timestamp' : str(timestamp), - } - return self.generate_security_hash(**initial_security_dict) - - def generate_security_hash(self, content_type, object_pk, timestamp): - """ - Generate a HMAC security hash from the provided info. - """ - info = (content_type, object_pk, timestamp) - key_salt = "django.contrib.forms.CommentSecurityForm" - value = "-".join(info) - return salted_hmac(key_salt, value).hexdigest() - -class CommentDetailsForm(CommentSecurityForm): - """ - Handles the specific details of the comment (name, comment, etc.). - """ - name = forms.CharField(label=_("Name"), max_length=50) - email = forms.EmailField(label=_("Email address")) - url = forms.URLField(label=_("URL"), required=False) - comment = forms.CharField(label=_('Comment'), widget=forms.Textarea, - max_length=COMMENT_MAX_LENGTH) - - def get_comment_object(self): - """ - Return a new (unsaved) comment object based on the information in this - form. Assumes that the form is already validated and will throw a - ValueError if not. - - Does not set any of the fields that would come from a Request object - (i.e. ``user`` or ``ip_address``). - """ - if not self.is_valid(): - raise ValueError("get_comment_object may only be called on valid forms") - - CommentModel = self.get_comment_model() - new = CommentModel(**self.get_comment_create_data()) - new = self.check_for_duplicate_comment(new) - - return new - - def get_comment_model(self): - """ - Get the comment model to create with this form. Subclasses in custom - comment apps should override this, get_comment_create_data, and perhaps - check_for_duplicate_comment to provide custom comment models. - """ - return Comment - - def get_comment_create_data(self): - """ - Returns the dict of data to be used to create a comment. Subclasses in - custom comment apps that override get_comment_model can override this - method to add extra fields onto a custom comment model. - """ - return dict( - content_type = ContentType.objects.get_for_model(self.target_object), - object_pk = force_text(self.target_object._get_pk_val()), - user_name = self.cleaned_data["name"], - user_email = self.cleaned_data["email"], - user_url = self.cleaned_data["url"], - comment = self.cleaned_data["comment"], - submit_date = timezone.now(), - site_id = settings.SITE_ID, - is_public = True, - is_removed = False, - ) - - def check_for_duplicate_comment(self, new): - """ - Check that a submitted comment isn't a duplicate. This might be caused - by someone posting a comment twice. If it is a dup, silently return the *previous* comment. - """ - possible_duplicates = self.get_comment_model()._default_manager.using( - self.target_object._state.db - ).filter( - content_type = new.content_type, - object_pk = new.object_pk, - user_name = new.user_name, - user_email = new.user_email, - user_url = new.user_url, - ) - for old in possible_duplicates: - if old.submit_date.date() == new.submit_date.date() and old.comment == new.comment: - return old - - return new - - def clean_comment(self): - """ - If COMMENTS_ALLOW_PROFANITIES is False, check that the comment doesn't - contain anything in PROFANITIES_LIST. - """ - comment = self.cleaned_data["comment"] - if settings.COMMENTS_ALLOW_PROFANITIES == False: - bad_words = [w for w in settings.PROFANITIES_LIST if w in comment.lower()] - if bad_words: - raise forms.ValidationError(ungettext( - "Watch your mouth! The word %s is not allowed here.", - "Watch your mouth! The words %s are not allowed here.", - len(bad_words)) % get_text_list( - ['"%s%s%s"' % (i[0], '-'*(len(i)-2), i[-1]) - for i in bad_words], ugettext('and'))) - return comment - -class CommentForm(CommentDetailsForm): - honeypot = forms.CharField(required=False, - label=_('If you enter anything in this field '\ - 'your comment will be treated as spam')) - - def clean_honeypot(self): - """Check that nothing's been entered into the honeypot.""" - value = self.cleaned_data["honeypot"] - if value: - raise forms.ValidationError(self.fields["honeypot"].label) - return value diff --git a/app/lib/django_comments_old/managers.py b/app/lib/django_comments_old/managers.py deleted file mode 100644 index bc0fc5f..0000000 --- a/app/lib/django_comments_old/managers.py +++ /dev/null @@ -1,22 +0,0 @@ -from django.db import models -from django.contrib.contenttypes.models import ContentType -from django.utils.encoding import force_text - -class CommentManager(models.Manager): - - def in_moderation(self): - """ - QuerySet for all comments currently in the moderation queue. - """ - return self.get_query_set().filter(is_public=False, is_removed=False) - - def for_model(self, model): - """ - QuerySet for all comments for a particular model (either an instance or - a class). - """ - ct = ContentType.objects.get_for_model(model) - qs = self.get_query_set().filter(content_type=ct) - if isinstance(model, models.Model): - qs = qs.filter(object_pk=force_text(model._get_pk_val())) - return qs diff --git a/app/lib/django_comments_old/models.py b/app/lib/django_comments_old/models.py deleted file mode 100644 index 6ba1f30..0000000 --- a/app/lib/django_comments_old/models.py +++ /dev/null @@ -1,204 +0,0 @@ -from django.conf import settings -try: - from django.contrib.contenttypes.fields import GenericForeignKey -except ImportError: - from django.contrib.contenttypes.generic import GenericForeignKey -from django.contrib.contenttypes.models import ContentType -from django.contrib.sites.models import Site -from django.core import urlresolvers -from django.db import models -from django.utils.translation import ugettext_lazy as _ -from django.utils import timezone -from django.utils.encoding import python_2_unicode_compatible - -from django_comments.managers import CommentManager - -COMMENT_MAX_LENGTH = getattr(settings, 'COMMENT_MAX_LENGTH', 3000) - - -class BaseCommentAbstractModel(models.Model): - """ - An abstract base class that any custom comment models probably should - subclass. - """ - - # Content-object field - content_type = models.ForeignKey(ContentType, - verbose_name=_('content type'), - related_name="content_type_set_for_%(class)s") - object_pk = models.TextField(_('object ID')) - content_object = GenericForeignKey(ct_field="content_type", fk_field="object_pk") - - # Metadata about the comment - site = models.ForeignKey(Site) - - class Meta: - abstract = True - - def get_content_object_url(self): - """ - Get a URL suitable for redirecting to the content object. - """ - return urlresolvers.reverse( - "comments-url-redirect", - args=(self.content_type_id, self.object_pk) - ) - - -@python_2_unicode_compatible -class Comment(BaseCommentAbstractModel): - """ - A user comment about some object. - """ - - # Who posted this comment? If ``user`` is set then it was an authenticated - # user; otherwise at least user_name should have been set and the comment - # was posted by a non-authenticated user. - user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'), - blank=True, null=True, related_name="%(class)s_comments") - user_name = models.CharField(_("user's name"), max_length=50, blank=True) - user_email = models.EmailField(_("user's email address"), blank=True) - user_url = models.URLField(_("user's URL"), blank=True) - - comment = models.TextField(_('comment'), max_length=COMMENT_MAX_LENGTH) - - # Metadata about the comment - submit_date = models.DateTimeField(_('date/time submitted'), default=None) - ip_address = models.GenericIPAddressField(_('IP address'), unpack_ipv4=True, blank=True, null=True) - is_public = models.BooleanField(_('is public'), default=True, - help_text=_('Uncheck this box to make the comment effectively ' \ - 'disappear from the site.')) - is_removed = models.BooleanField(_('is removed'), default=False, - help_text=_('Check this box if the comment is inappropriate. ' \ - 'A "This comment has been removed" message will ' \ - 'be displayed instead.')) - - # Manager - objects = CommentManager() - - class Meta: - db_table = "django_comments" - ordering = ('submit_date',) - permissions = [("can_moderate", "Can moderate comments")] - verbose_name = _('comment') - verbose_name_plural = _('comments') - - def __str__(self): - return "%s: %s..." % (self.name, self.comment[:50]) - - def save(self, *args, **kwargs): - if self.submit_date is None: - self.submit_date = timezone.now() - super(Comment, self).save(*args, **kwargs) - - def _get_userinfo(self): - """ - Get a dictionary that pulls together information about the poster - safely for both authenticated and non-authenticated comments. - - This dict will have ``name``, ``email``, and ``url`` fields. - """ - if not hasattr(self, "_userinfo"): - userinfo = { - "name": self.user_name, - "email": self.user_email, - "url": self.user_url - } - if self.user_id: - u = self.user - if u.email: - userinfo["email"] = u.email - - # If the user has a full name, use that for the user name. - # However, a given user_name overrides the raw user.username, - # so only use that if this comment has no associated name. - if u.get_full_name(): - userinfo["name"] = self.user.get_full_name() - elif not self.user_name: - userinfo["name"] = u.get_username() - self._userinfo = userinfo - return self._userinfo - userinfo = property(_get_userinfo, doc=_get_userinfo.__doc__) - - def _get_name(self): - return self.userinfo["name"] - - def _set_name(self, val): - if self.user_id: - raise AttributeError(_("This comment was posted by an authenticated "\ - "user and thus the name is read-only.")) - self.user_name = val - name = property(_get_name, _set_name, doc="The name of the user who posted this comment") - - def _get_email(self): - return self.userinfo["email"] - - def _set_email(self, val): - if self.user_id: - raise AttributeError(_("This comment was posted by an authenticated "\ - "user and thus the email is read-only.")) - self.user_email = val - email = property(_get_email, _set_email, doc="The email of the user who posted this comment") - - def _get_url(self): - return self.userinfo["url"] - - def _set_url(self, val): - self.user_url = val - url = property(_get_url, _set_url, doc="The URL given by the user who posted this comment") - - def get_absolute_url(self, anchor_pattern="#c%(id)s"): - return self.get_content_object_url() + (anchor_pattern % self.__dict__) - - def get_as_text(self): - """ - Return this comment as plain text. Useful for emails. - """ - d = { - 'user': self.user or self.name, - 'date': self.submit_date, - 'comment': self.comment, - 'domain': self.site.domain, - 'url': self.get_absolute_url() - } - return _('Posted by %(user)s at %(date)s\n\n%(comment)s\n\nhttp://%(domain)s%(url)s') % d - - -@python_2_unicode_compatible -class CommentFlag(models.Model): - """ - Records a flag on a comment. This is intentionally flexible; right now, a - flag could be: - - * A "removal suggestion" -- where a user suggests a comment for (potential) removal. - - * A "moderator deletion" -- used when a moderator deletes a comment. - - You can (ab)use this model to add other flags, if needed. However, by - design users are only allowed to flag a comment with a given flag once; - if you want rating look elsewhere. - """ - user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'), related_name="comment_flags") - comment = models.ForeignKey(Comment, verbose_name=_('comment'), related_name="flags") - flag = models.CharField(_('flag'), max_length=30, db_index=True) - flag_date = models.DateTimeField(_('date'), default=None) - - # Constants for flag types - SUGGEST_REMOVAL = "removal suggestion" - MODERATOR_DELETION = "moderator deletion" - MODERATOR_APPROVAL = "moderator approval" - - class Meta: - db_table = 'django_comment_flags' - unique_together = [('user', 'comment', 'flag')] - verbose_name = _('comment flag') - verbose_name_plural = _('comment flags') - - def __str__(self): - return "%s flag of comment ID %s by %s" % \ - (self.flag, self.comment_id, self.user.get_username()) - - def save(self, *args, **kwargs): - if self.flag_date is None: - self.flag_date = timezone.now() - super(CommentFlag, self).save(*args, **kwargs) diff --git a/app/lib/django_comments_old/moderation.py b/app/lib/django_comments_old/moderation.py deleted file mode 100644 index ebb29da..0000000 --- a/app/lib/django_comments_old/moderation.py +++ /dev/null @@ -1,357 +0,0 @@ -""" -A generic comment-moderation system which allows configuration of -moderation options on a per-model basis. - -To use, do two things: - -1. Create or import a subclass of ``CommentModerator`` defining the - options you want. - -2. Import ``moderator`` from this module and register one or more - models, passing the models and the ``CommentModerator`` options - class you want to use. - - -Example -------- - -First, we define a simple model class which might represent entries in -a Weblog:: - - from django.db import models - - class Entry(models.Model): - title = models.CharField(maxlength=250) - body = models.TextField() - pub_date = models.DateField() - enable_comments = models.BooleanField() - -Then we create a ``CommentModerator`` subclass specifying some -moderation options:: - - from django_comments.moderation import CommentModerator, moderator - - class EntryModerator(CommentModerator): - email_notification = True - enable_field = 'enable_comments' - -And finally register it for moderation:: - - moderator.register(Entry, EntryModerator) - -This sample class would apply two moderation steps to each new -comment submitted on an Entry: - -* If the entry's ``enable_comments`` field is set to ``False``, the - comment will be rejected (immediately deleted). - -* If the comment is successfully posted, an email notification of the - comment will be sent to site staff. - -For a full list of built-in moderation options and other -configurability, see the documentation for the ``CommentModerator`` -class. - -""" - -import datetime - -from django.conf import settings -from django.core.mail import send_mail -from django.db.models.base import ModelBase -from django.template import Context, loader -from django.contrib.sites.shortcuts import get_current_site -from django.utils import timezone - -import django_comments -from django_comments import signals - -class AlreadyModerated(Exception): - """ - Raised when a model which is already registered for moderation is - attempting to be registered again. - - """ - pass - -class NotModerated(Exception): - """ - Raised when a model which is not registered for moderation is - attempting to be unregistered. - - """ - pass - -class CommentModerator(object): - """ - Encapsulates comment-moderation options for a given model. - - This class is not designed to be used directly, since it doesn't - enable any of the available moderation options. Instead, subclass - it and override attributes to enable different options:: - - ``auto_close_field`` - If this is set to the name of a ``DateField`` or - ``DateTimeField`` on the model for which comments are - being moderated, new comments for objects of that model - will be disallowed (immediately deleted) when a certain - number of days have passed after the date specified in - that field. Must be used in conjunction with - ``close_after``, which specifies the number of days past - which comments should be disallowed. Default value is - ``None``. - - ``auto_moderate_field`` - Like ``auto_close_field``, but instead of outright - deleting new comments when the requisite number of days - have elapsed, it will simply set the ``is_public`` field - of new comments to ``False`` before saving them. Must be - used in conjunction with ``moderate_after``, which - specifies the number of days past which comments should be - moderated. Default value is ``None``. - - ``close_after`` - If ``auto_close_field`` is used, this must specify the - number of days past the value of the field specified by - ``auto_close_field`` after which new comments for an - object should be disallowed. Default value is ``None``. - - ``email_notification`` - If ``True``, any new comment on an object of this model - which survives moderation will generate an email to site - staff. Default value is ``False``. - - ``enable_field`` - If this is set to the name of a ``BooleanField`` on the - model for which comments are being moderated, new comments - on objects of that model will be disallowed (immediately - deleted) whenever the value of that field is ``False`` on - the object the comment would be attached to. Default value - is ``None``. - - ``moderate_after`` - If ``auto_moderate_field`` is used, this must specify the number - of days past the value of the field specified by - ``auto_moderate_field`` after which new comments for an - object should be marked non-public. Default value is - ``None``. - - Most common moderation needs can be covered by changing these - attributes, but further customization can be obtained by - subclassing and overriding the following methods. Each method will - be called with three arguments: ``comment``, which is the comment - being submitted, ``content_object``, which is the object the - comment will be attached to, and ``request``, which is the - ``HttpRequest`` in which the comment is being submitted:: - - ``allow`` - Should return ``True`` if the comment should be allowed to - post on the content object, and ``False`` otherwise (in - which case the comment will be immediately deleted). - - ``email`` - If email notification of the new comment should be sent to - site staff or moderators, this method is responsible for - sending the email. - - ``moderate`` - Should return ``True`` if the comment should be moderated - (in which case its ``is_public`` field will be set to - ``False`` before saving), and ``False`` otherwise (in - which case the ``is_public`` field will not be changed). - - Subclasses which want to introspect the model for which comments - are being moderated can do so through the attribute ``_model``, - which will be the model class. - - """ - auto_close_field = None - auto_moderate_field = None - close_after = None - email_notification = False - enable_field = None - moderate_after = None - - def __init__(self, model): - self._model = model - - def _get_delta(self, now, then): - """ - Internal helper which will return a ``datetime.timedelta`` - representing the time between ``now`` and ``then``. Assumes - ``now`` is a ``datetime.date`` or ``datetime.datetime`` later - than ``then``. - - If ``now`` and ``then`` are not of the same type due to one of - them being a ``datetime.date`` and the other being a - ``datetime.datetime``, both will be coerced to - ``datetime.date`` before calculating the delta. - - """ - if now.__class__ is not then.__class__: - now = datetime.date(now.year, now.month, now.day) - then = datetime.date(then.year, then.month, then.day) - if now < then: - raise ValueError("Cannot determine moderation rules because date field is set to a value in the future") - return now - then - - def allow(self, comment, content_object, request): - """ - Determine whether a given comment is allowed to be posted on - a given object. - - Return ``True`` if the comment should be allowed, ``False - otherwise. - - """ - if self.enable_field: - if not getattr(content_object, self.enable_field): - return False - if self.auto_close_field and self.close_after is not None: - close_after_date = getattr(content_object, self.auto_close_field) - if close_after_date is not None and self._get_delta(timezone.now(), close_after_date).days >= self.close_after: - return False - return True - - def moderate(self, comment, content_object, request): - """ - Determine whether a given comment on a given object should be - allowed to show up immediately, or should be marked non-public - and await approval. - - Return ``True`` if the comment should be moderated (marked - non-public), ``False`` otherwise. - - """ - if self.auto_moderate_field and self.moderate_after is not None: - moderate_after_date = getattr(content_object, self.auto_moderate_field) - if moderate_after_date is not None and self._get_delta(timezone.now(), moderate_after_date).days >= self.moderate_after: - return True - return False - - def email(self, comment, content_object, request): - """ - Send email notification of a new comment to site staff when email - notifications have been requested. - - """ - if not self.email_notification: - return - recipient_list = [manager_tuple[1] for manager_tuple in settings.MANAGERS] - t = loader.get_template('comments/comment_notification_email.txt') - c = Context({ 'comment': comment, - 'content_object': content_object }) - subject = '[%s] New comment posted on "%s"' % (get_current_site(request).name, - content_object) - message = t.render(c) - send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, recipient_list, fail_silently=True) - -class Moderator(object): - """ - Handles moderation of a set of models. - - An instance of this class will maintain a list of one or more - models registered for comment moderation, and their associated - moderation classes, and apply moderation to all incoming comments. - - To register a model, obtain an instance of ``Moderator`` (this - module exports one as ``moderator``), and call its ``register`` - method, passing the model class and a moderation class (which - should be a subclass of ``CommentModerator``). Note that both of - these should be the actual classes, not instances of the classes. - - To cease moderation for a model, call the ``unregister`` method, - passing the model class. - - For convenience, both ``register`` and ``unregister`` can also - accept a list of model classes in place of a single model; this - allows easier registration of multiple models with the same - ``CommentModerator`` class. - - The actual moderation is applied in two phases: one prior to - saving a new comment, and the other immediately after saving. The - pre-save moderation may mark a comment as non-public or mark it to - be removed; the post-save moderation may delete a comment which - was disallowed (there is currently no way to prevent the comment - being saved once before removal) and, if the comment is still - around, will send any notification emails the comment generated. - - """ - def __init__(self): - self._registry = {} - self.connect() - - def connect(self): - """ - Hook up the moderation methods to pre- and post-save signals - from the comment models. - - """ - signals.comment_will_be_posted.connect(self.pre_save_moderation, sender=django_comments.get_model()) - signals.comment_was_posted.connect(self.post_save_moderation, sender=django_comments.get_model()) - - def register(self, model_or_iterable, moderation_class): - """ - Register a model or a list of models for comment moderation, - using a particular moderation class. - - Raise ``AlreadyModerated`` if any of the models are already - registered. - - """ - if isinstance(model_or_iterable, ModelBase): - model_or_iterable = [model_or_iterable] - for model in model_or_iterable: - if model in self._registry: - raise AlreadyModerated("The model '%s' is already being moderated" % model._meta.module_name) - self._registry[model] = moderation_class(model) - - def unregister(self, model_or_iterable): - """ - Remove a model or a list of models from the list of models - whose comments will be moderated. - - Raise ``NotModerated`` if any of the models are not currently - registered for moderation. - - """ - if isinstance(model_or_iterable, ModelBase): - model_or_iterable = [model_or_iterable] - for model in model_or_iterable: - if model not in self._registry: - raise NotModerated("The model '%s' is not currently being moderated" % model._meta.module_name) - del self._registry[model] - - def pre_save_moderation(self, sender, comment, request, **kwargs): - """ - Apply any necessary pre-save moderation steps to new - comments. - - """ - model = comment.content_type.model_class() - if model not in self._registry: - return - content_object = comment.content_object - moderation_class = self._registry[model] - - # Comment will be disallowed outright (HTTP 403 response) - if not moderation_class.allow(comment, content_object, request): - return False - - if moderation_class.moderate(comment, content_object, request): - comment.is_public = False - - def post_save_moderation(self, sender, comment, request, **kwargs): - """ - Apply any necessary post-save moderation steps to new - comments. - - """ - model = comment.content_type.model_class() - if model not in self._registry: - return - self._registry[model].email(comment, comment.content_object, request) - -# Import this instance in your own code to use in registering -# your models for moderation. -moderator = Moderator() diff --git a/app/lib/django_comments_old/signals.py b/app/lib/django_comments_old/signals.py deleted file mode 100644 index 079afaf..0000000 --- a/app/lib/django_comments_old/signals.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -Signals relating to comments. -""" -from django.dispatch import Signal - -# Sent just before a comment will be posted (after it's been approved and -# moderated; this can be used to modify the comment (in place) with posting -# details or other such actions. If any receiver returns False the comment will be -# discarded and a 400 response. This signal is sent at more or less -# the same time (just before, actually) as the Comment object's pre-save signal, -# except that the HTTP request is sent along with this signal. -comment_will_be_posted = Signal(providing_args=["comment", "request"]) - -# Sent just after a comment was posted. See above for how this differs -# from the Comment object's post-save signal. -comment_was_posted = Signal(providing_args=["comment", "request"]) - -# Sent after a comment was "flagged" in some way. Check the flag to see if this -# was a user requesting removal of a comment, a moderator approving/removing a -# comment, or some other custom user flag. -comment_was_flagged = Signal(providing_args=["comment", "flag", "created", "request"]) diff --git a/app/lib/django_comments_old/templatetags/__init__.py b/app/lib/django_comments_old/templatetags/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/app/lib/django_comments_old/templatetags/__init__.py +++ /dev/null diff --git a/app/lib/django_comments_old/templatetags/comments.py b/app/lib/django_comments_old/templatetags/comments.py deleted file mode 100644 index 5ff156b..0000000 --- a/app/lib/django_comments_old/templatetags/comments.py +++ /dev/null @@ -1,334 +0,0 @@ -from django import template -from django.template.loader import render_to_string -from django.conf import settings -from django.contrib.contenttypes.models import ContentType -from django.utils.encoding import smart_text - -import django_comments - -register = template.Library() - - -class BaseCommentNode(template.Node): - """ - Base helper class (abstract) for handling the get_comment_* template tags. - Looks a bit strange, but the subclasses below should make this a bit more - obvious. - """ - - @classmethod - def handle_token(cls, parser, token): - """Class method to parse get_comment_list/count/form and return a Node.""" - tokens = token.split_contents() - if tokens[1] != 'for': - raise template.TemplateSyntaxError("Second argument in %r tag must be 'for'" % tokens[0]) - - # {% get_whatever for obj as varname %} - if len(tokens) == 5: - if tokens[3] != 'as': - raise template.TemplateSyntaxError("Third argument in %r must be 'as'" % tokens[0]) - return cls( - object_expr = parser.compile_filter(tokens[2]), - as_varname = tokens[4], - ) - - # {% get_whatever for app.model pk as varname %} - elif len(tokens) == 6: - if tokens[4] != 'as': - raise template.TemplateSyntaxError("Fourth argument in %r must be 'as'" % tokens[0]) - return cls( - ctype = BaseCommentNode.lookup_content_type(tokens[2], tokens[0]), - object_pk_expr = parser.compile_filter(tokens[3]), - as_varname = tokens[5] - ) - - else: - raise template.TemplateSyntaxError("%r tag requires 4 or 5 arguments" % tokens[0]) - - @staticmethod - def lookup_content_type(token, tagname): - try: - app, model = token.split('.') - return ContentType.objects.get_by_natural_key(app, model) - except ValueError: - raise template.TemplateSyntaxError("Third argument in %r must be in the format 'app.model'" % tagname) - except ContentType.DoesNotExist: - raise template.TemplateSyntaxError("%r tag has non-existant content-type: '%s.%s'" % (tagname, app, model)) - - def __init__(self, ctype=None, object_pk_expr=None, object_expr=None, as_varname=None, comment=None): - if ctype is None and object_expr is None: - raise template.TemplateSyntaxError("Comment nodes must be given either a literal object or a ctype and object pk.") - self.comment_model = django_comments.get_model() - self.as_varname = as_varname - self.ctype = ctype - self.object_pk_expr = object_pk_expr - self.object_expr = object_expr - self.comment = comment - - def render(self, context): - qs = self.get_query_set(context) - context[self.as_varname] = self.get_context_value_from_queryset(context, qs) - return '' - - def get_query_set(self, context): - ctype, object_pk = self.get_target_ctype_pk(context) - if not object_pk: - return self.comment_model.objects.none() - - qs = self.comment_model.objects.filter( - content_type = ctype, - object_pk = smart_text(object_pk), - site__pk = settings.SITE_ID, - ) - - # The is_public and is_removed fields are implementation details of the - # built-in comment model's spam filtering system, so they might not - # be present on a custom comment model subclass. If they exist, we - # should filter on them. - field_names = [f.name for f in self.comment_model._meta.fields] - if 'is_public' in field_names: - qs = qs.filter(is_public=True) - if getattr(settings, 'COMMENTS_HIDE_REMOVED', True) and 'is_removed' in field_names: - qs = qs.filter(is_removed=False) - - return qs - - def get_target_ctype_pk(self, context): - if self.object_expr: - try: - obj = self.object_expr.resolve(context) - except template.VariableDoesNotExist: - return None, None - return ContentType.objects.get_for_model(obj), obj.pk - else: - return self.ctype, self.object_pk_expr.resolve(context, ignore_failures=True) - - def get_context_value_from_queryset(self, context, qs): - """Subclasses should override this.""" - raise NotImplementedError - -class CommentListNode(BaseCommentNode): - """Insert a list of comments into the context.""" - def get_context_value_from_queryset(self, context, qs): - return list(qs) - -class CommentCountNode(BaseCommentNode): - """Insert a count of comments into the context.""" - def get_context_value_from_queryset(self, context, qs): - return qs.count() - -class CommentFormNode(BaseCommentNode): - """Insert a form for the comment model into the context.""" - - def get_form(self, context): - obj = self.get_object(context) - if obj: - return django_comments.get_form()(obj) - else: - return None - - def get_object(self, context): - if self.object_expr: - try: - return self.object_expr.resolve(context) - except template.VariableDoesNotExist: - return None - else: - object_pk = self.object_pk_expr.resolve(context, - ignore_failures=True) - return self.ctype.get_object_for_this_type(pk=object_pk) - - def render(self, context): - context[self.as_varname] = self.get_form(context) - return '' - -class RenderCommentFormNode(CommentFormNode): - """Render the comment form directly""" - - @classmethod - def handle_token(cls, parser, token): - """Class method to parse render_comment_form and return a Node.""" - tokens = token.split_contents() - if tokens[1] != 'for': - raise template.TemplateSyntaxError("Second argument in %r tag must be 'for'" % tokens[0]) - - # {% render_comment_form for obj %} - if len(tokens) == 3: - return cls(object_expr=parser.compile_filter(tokens[2])) - - # {% render_comment_form for app.models pk %} - elif len(tokens) == 4: - return cls( - ctype = BaseCommentNode.lookup_content_type(tokens[2], tokens[0]), - object_pk_expr = parser.compile_filter(tokens[3]) - ) - - def render(self, context): - ctype, object_pk = self.get_target_ctype_pk(context) - if object_pk: - template_search_list = [ - "comments/%s/%s/form.html" % (ctype.app_label, ctype.model), - "comments/%s/form.html" % ctype.app_label, - "comments/form.html" - ] - context.push() - formstr = render_to_string(template_search_list, {"form" : self.get_form(context)}, context) - context.pop() - return formstr - else: - return '' - -class RenderCommentListNode(CommentListNode): - """Render the comment list directly""" - - @classmethod - def handle_token(cls, parser, token): - """Class method to parse render_comment_list and return a Node.""" - tokens = token.split_contents() - if tokens[1] != 'for': - raise template.TemplateSyntaxError("Second argument in %r tag must be 'for'" % tokens[0]) - - # {% render_comment_list for obj %} - if len(tokens) == 3: - return cls(object_expr=parser.compile_filter(tokens[2])) - - # {% render_comment_list for app.models pk %} - elif len(tokens) == 4: - return cls( - ctype = BaseCommentNode.lookup_content_type(tokens[2], tokens[0]), - object_pk_expr = parser.compile_filter(tokens[3]) - ) - - def render(self, context): - ctype, object_pk = self.get_target_ctype_pk(context) - if object_pk: - template_search_list = [ - "comments/%s/%s/list.html" % (ctype.app_label, ctype.model), - "comments/%s/list.html" % ctype.app_label, - "comments/list.html" - ] - qs = self.get_query_set(context) - context.push() - liststr = render_to_string(template_search_list, { - "comment_list" : self.get_context_value_from_queryset(context, qs) - }, context) - context.pop() - return liststr - else: - return '' - -# We could just register each classmethod directly, but then we'd lose out on -# the automagic docstrings-into-admin-docs tricks. So each node gets a cute -# wrapper function that just exists to hold the docstring. - -@register.tag -def get_comment_count(parser, token): - """ - Gets the comment count for the given params and populates the template - context with a variable containing that value, whose name is defined by the - 'as' clause. - - Syntax:: - - {% get_comment_count for [object] as [varname] %} - {% get_comment_count for [app].[model] [object_id] as [varname] %} - - Example usage:: - - {% get_comment_count for event as comment_count %} - {% get_comment_count for calendar.event event.id as comment_count %} - {% get_comment_count for calendar.event 17 as comment_count %} - - """ - return CommentCountNode.handle_token(parser, token) - -@register.tag -def get_comment_list(parser, token): - """ - Gets the list of comments for the given params and populates the template - context with a variable containing that value, whose name is defined by the - 'as' clause. - - Syntax:: - - {% get_comment_list for [object] as [varname] %} - {% get_comment_list for [app].[model] [object_id] as [varname] %} - - Example usage:: - - {% get_comment_list for event as comment_list %} - {% for comment in comment_list %} - ... - {% endfor %} - - """ - return CommentListNode.handle_token(parser, token) - -@register.tag -def render_comment_list(parser, token): - """ - Render the comment list (as returned by ``{% get_comment_list %}``) - through the ``comments/list.html`` template - - Syntax:: - - {% render_comment_list for [object] %} - {% render_comment_list for [app].[model] [object_id] %} - - Example usage:: - - {% render_comment_list for event %} - - """ - return RenderCommentListNode.handle_token(parser, token) - -@register.tag -def get_comment_form(parser, token): - """ - Get a (new) form object to post a new comment. - - Syntax:: - - {% get_comment_form for [object] as [varname] %} - {% get_comment_form for [app].[model] [object_id] as [varname] %} - """ - return CommentFormNode.handle_token(parser, token) - -@register.tag -def render_comment_form(parser, token): - """ - Render the comment form (as returned by ``{% render_comment_form %}``) through - the ``comments/form.html`` template. - - Syntax:: - - {% render_comment_form for [object] %} - {% render_comment_form for [app].[model] [object_id] %} - """ - return RenderCommentFormNode.handle_token(parser, token) - -@register.simple_tag -def comment_form_target(): - """ - Get the target URL for the comment form. - - Example:: - - <form action="{% comment_form_target %}" method="post"> - """ - return django_comments.get_form_target() - -@register.simple_tag -def get_comment_permalink(comment, anchor_pattern=None): - """ - Get the permalink for a comment, optionally specifying the format of the - named anchor to be appended to the end of the URL. - - Example:: - {% get_comment_permalink comment "#c%(id)s-by-%(user_name)s" %} - """ - - if anchor_pattern: - return comment.get_absolute_url(anchor_pattern) - return comment.get_absolute_url() - diff --git a/app/lib/django_comments_old/urls.py b/app/lib/django_comments_old/urls.py deleted file mode 100644 index fb8f972..0000000 --- a/app/lib/django_comments_old/urls.py +++ /dev/null @@ -1,18 +0,0 @@ -from django.conf.urls import url -from .views import comments, moderation -from django.contrib.contenttypes.views import shortcut - -urlpatterns = [ - url(r'^post/$', comments.post_comment, name='comments-post-comment'), - url(r'^posted/$', comments.comment_done, name='comments-comment-done'), - url(r'^flag/(\d+)/$', moderation.flag, name='comments-flag'), - url(r'^flagged/$', moderation.flag_done, name='comments-flag-done'), - url(r'^delete/(\d+)/$', moderation.delete, name='comments-delete'), - url(r'^deleted/$', moderation.delete_done, name='comments-delete-done'), - url(r'^approve/(\d+)/$', moderation.approve, name='comments-approve'), - url(r'^approved/$', moderation.approve_done, name='comments-approve-done'), -] - -urlpatterns += [ - url(r'^cr/(\d+)/(.+)/$', shortcut, name='comments-url-redirect'), -] diff --git a/app/lib/django_comments_old/views/__init__.py b/app/lib/django_comments_old/views/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/app/lib/django_comments_old/views/__init__.py +++ /dev/null diff --git a/app/lib/django_comments_old/views/comments.py b/app/lib/django_comments_old/views/comments.py deleted file mode 100644 index b44babf..0000000 --- a/app/lib/django_comments_old/views/comments.py +++ /dev/null @@ -1,140 +0,0 @@ -from __future__ import absolute_import - -from django import http -from django.conf import settings -from django.core.exceptions import ObjectDoesNotExist, ValidationError -from django.db import models -from django.shortcuts import render_to_response -from django.template import RequestContext -from django.template.loader import render_to_string -from django.utils.html import escape -from django.views.decorators.csrf import csrf_protect -from django.views.decorators.http import require_POST -try: - from django.apps import apps -except ImportError: - from django.db import models as apps - -import django_comments -from django_comments import signals -from django_comments.views.utils import next_redirect, confirmation_view - -class CommentPostBadRequest(http.HttpResponseBadRequest): - """ - Response returned when a comment post is invalid. If ``DEBUG`` is on a - nice-ish error message will be displayed (for debugging purposes), but in - production mode a simple opaque 400 page will be displayed. - """ - def __init__(self, why): - super(CommentPostBadRequest, self).__init__() - if settings.DEBUG: - self.content = render_to_string("comments/400-debug.html", {"why": why}) - - -@require_POST -def post_comment(request, next=None, using=None): - """ - Post a comment. - - HTTP POST is required. If ``POST['submit'] == "preview"`` or if there are - errors a preview template, ``comments/preview.html``, will be rendered. - """ - # Fill out some initial data fields from an authenticated user, if present - data = request.POST.copy() - if request.user.is_authenticated(): - if not data.get('name', ''): - data["name"] = request.user.get_full_name() or request.user.get_username() - if not data.get('email', ''): - data["email"] = request.user.email - - # Look up the object we're trying to comment about - ctype = data.get("content_type") - object_pk = data.get("object_pk") - if ctype is None or object_pk is None: - return CommentPostBadRequest("Missing content_type or object_pk field.") - try: - model = apps.get_model(*ctype.split(".", 1)) - target = model._default_manager.using(using).get(pk=object_pk) - except TypeError: - return CommentPostBadRequest( - "Invalid content_type value: %r" % escape(ctype)) - except AttributeError: - return CommentPostBadRequest( - "The given content-type %r does not resolve to a valid model." % \ - escape(ctype)) - except ObjectDoesNotExist: - return CommentPostBadRequest( - "No object matching content-type %r and object PK %r exists." % \ - (escape(ctype), escape(object_pk))) - except (ValueError, ValidationError) as e: - return CommentPostBadRequest( - "Attempting go get content-type %r and object PK %r exists raised %s" % \ - (escape(ctype), escape(object_pk), e.__class__.__name__)) - - # Do we want to preview the comment? - preview = "preview" in data - - # Construct the comment form - form = django_comments.get_form()(target, data=data) - - # Check security information - if form.security_errors(): - return CommentPostBadRequest( - "The comment form failed security verification: %s" % \ - escape(str(form.security_errors()))) - - # If there are errors or if we requested a preview show the comment - if form.errors or preview: - template_list = [ - # These first two exist for purely historical reasons. - # Django v1.0 and v1.1 allowed the underscore format for - # preview templates, so we have to preserve that format. - "comments/%s_%s_preview.html" % (model._meta.app_label, model._meta.model_name), - "comments/%s_preview.html" % model._meta.app_label, - # Now the usual directory based template hierarchy. - "comments/%s/%s/preview.html" % (model._meta.app_label, model._meta.model_name), - "comments/%s/preview.html" % model._meta.app_label, - "comments/preview.html", - ] - return render_to_response( - template_list, { - "comment": form.data.get("comment", ""), - "form": form, - "next": data.get("next", next), - }, - RequestContext(request, {}) - ) - - # Otherwise create the comment - comment = form.get_comment_object() - comment.ip_address = request.META.get("REMOTE_ADDR", None) - if request.user.is_authenticated(): - comment.user = request.user - - # Signal that the comment is about to be saved - responses = signals.comment_will_be_posted.send( - sender=comment.__class__, - comment=comment, - request=request - ) - - for (receiver, response) in responses: - if response == False: - return CommentPostBadRequest( - "comment_will_be_posted receiver %r killed the comment" % receiver.__name__) - - # Save the comment and signal that it was saved - comment.save() - signals.comment_was_posted.send( - sender=comment.__class__, - comment=comment, - request=request - ) - - return next_redirect(request, fallback=next or 'comments-comment-done', - c=comment._get_pk_val()) - -comment_done = confirmation_view( - template="comments/posted.html", - doc="""Display a "comment was posted" success page.""" -) diff --git a/app/lib/django_comments_old/views/moderation.py b/app/lib/django_comments_old/views/moderation.py deleted file mode 100644 index b35626a..0000000 --- a/app/lib/django_comments_old/views/moderation.py +++ /dev/null @@ -1,165 +0,0 @@ -from __future__ import absolute_import - -from django import template -from django.conf import settings -from django.contrib.auth.decorators import login_required, permission_required -from django.shortcuts import get_object_or_404, render_to_response -from django.views.decorators.csrf import csrf_protect - -import django_comments -from django_comments import signals -from django_comments.views.utils import next_redirect, confirmation_view - -@csrf_protect -@login_required -def flag(request, comment_id, next=None): - """ - Flags a comment. Confirmation on GET, action on POST. - - Templates: :template:`comments/flag.html`, - Context: - comment - the flagged `comments.comment` object - """ - comment = get_object_or_404(django_comments.get_model(), pk=comment_id, site__pk=settings.SITE_ID) - - # Flag on POST - if request.method == 'POST': - perform_flag(request, comment) - return next_redirect(request, fallback=next or 'comments-flag-done', - c=comment.pk) - - # Render a form on GET - else: - return render_to_response('comments/flag.html', - {'comment': comment, "next": next}, - template.RequestContext(request) - ) - -@csrf_protect -@permission_required("django_comments.can_moderate") -def delete(request, comment_id, next=None): - """ - Deletes a comment. Confirmation on GET, action on POST. Requires the "can - moderate comments" permission. - - Templates: :template:`comments/delete.html`, - Context: - comment - the flagged `comments.comment` object - """ - comment = get_object_or_404(django_comments.get_model(), pk=comment_id, site__pk=settings.SITE_ID) - - # Delete on POST - if request.method == 'POST': - # Flag the comment as deleted instead of actually deleting it. - perform_delete(request, comment) - return next_redirect(request, fallback=next or 'comments-delete-done', - c=comment.pk) - - # Render a form on GET - else: - return render_to_response('comments/delete.html', - {'comment': comment, "next": next}, - template.RequestContext(request) - ) - -@csrf_protect -@permission_required("django_comments.can_moderate") -def approve(request, comment_id, next=None): - """ - Approve a comment (that is, mark it as public and non-removed). Confirmation - on GET, action on POST. Requires the "can moderate comments" permission. - - Templates: :template:`comments/approve.html`, - Context: - comment - the `comments.comment` object for approval - """ - comment = get_object_or_404(django_comments.get_model(), pk=comment_id, site__pk=settings.SITE_ID) - - # Delete on POST - if request.method == 'POST': - # Flag the comment as approved. - perform_approve(request, comment) - return next_redirect(request, fallback=next or 'comments-approve-done', - c=comment.pk) - - # Render a form on GET - else: - return render_to_response('comments/approve.html', - {'comment': comment, "next": next}, - template.RequestContext(request) - ) - -# The following functions actually perform the various flag/aprove/delete -# actions. They've been broken out into separate functions to that they -# may be called from admin actions. - -def perform_flag(request, comment): - """ - Actually perform the flagging of a comment from a request. - """ - flag, created = django_comments.models.CommentFlag.objects.get_or_create( - comment = comment, - user = request.user, - flag = django_comments.models.CommentFlag.SUGGEST_REMOVAL - ) - signals.comment_was_flagged.send( - sender = comment.__class__, - comment = comment, - flag = flag, - created = created, - request = request, - ) - -def perform_delete(request, comment): - flag, created = django_comments.models.CommentFlag.objects.get_or_create( - comment = comment, - user = request.user, - flag = django_comments.models.CommentFlag.MODERATOR_DELETION - ) - comment.is_removed = True - comment.save() - signals.comment_was_flagged.send( - sender = comment.__class__, - comment = comment, - flag = flag, - created = created, - request = request, - ) - - -def perform_approve(request, comment): - flag, created = django_comments.models.CommentFlag.objects.get_or_create( - comment = comment, - user = request.user, - flag = django_comments.models.CommentFlag.MODERATOR_APPROVAL, - ) - - comment.is_removed = False - comment.is_public = True - comment.save() - - signals.comment_was_flagged.send( - sender = comment.__class__, - comment = comment, - flag = flag, - created = created, - request = request, - ) - -# Confirmation views. - -flag_done = confirmation_view( - template = "comments/flagged.html", - doc = 'Displays a "comment was flagged" success page.' -) -delete_done = confirmation_view( - template = "comments/deleted.html", - doc = 'Displays a "comment was deleted" success page.' -) -approve_done = confirmation_view( - template = "comments/approved.html", - doc = 'Displays a "comment was approved" success page.' -) diff --git a/app/lib/django_comments_old/views/utils.py b/app/lib/django_comments_old/views/utils.py deleted file mode 100644 index 314ab8c..0000000 --- a/app/lib/django_comments_old/views/utils.py +++ /dev/null @@ -1,71 +0,0 @@ -""" -A few bits of helper functions for comment views. -""" - -import textwrap -try: - from urllib.parse import urlencode -except ImportError: # Python 2 - from urllib import urlencode - -from django.http import HttpResponseRedirect -from django.shortcuts import render_to_response, resolve_url -from django.template import RequestContext -from django.core.exceptions import ObjectDoesNotExist -from django.utils.http import is_safe_url - -import django_comments - -def next_redirect(request, fallback, **get_kwargs): - """ - Handle the "where should I go next?" part of comment views. - - The next value could be a - ``?next=...`` GET arg or the URL of a given view (``fallback``). See - the view modules for examples. - - Returns an ``HttpResponseRedirect``. - """ - next = request.POST.get('next') - if not is_safe_url(url=next, host=request.get_host()): - next = resolve_url(fallback) - - if get_kwargs: - if '#' in next: - tmp = next.rsplit('#', 1) - next = tmp[0] - anchor = '#' + tmp[1] - else: - anchor = '' - - joiner = ('?' in next) and '&' or '?' - next += joiner + urlencode(get_kwargs) + anchor - return HttpResponseRedirect(next) - -def confirmation_view(template, doc="Display a confirmation view."): - """ - Confirmation view generator for the "comment was - posted/flagged/deleted/approved" views. - """ - def confirmed(request): - comment = None - if 'c' in request.GET: - try: - comment = django_comments.get_model().objects.get(pk=request.GET['c']) - except (ObjectDoesNotExist, ValueError): - pass - return render_to_response(template, - {'comment': comment}, - context_instance=RequestContext(request) - ) - - confirmed.__doc__ = textwrap.dedent("""\ - %s - - Templates: :template:`%s`` - Context: - comment - The posted comment - """ % (doc, template) - ) - return confirmed |