Skip to content
This repository has been archived by the owner on Jan 7, 2021. It is now read-only.

Commit

Permalink
Initial refactoring
Browse files Browse the repository at this point in the history
misc
----

* Rename app
* Remove previews
* Restrict commenting to users
* Remove CommentDetailsForm
* Replace UsernameSearch() with USERNAME_FIELD
* Add get_user_display()
* Add safe_comment template filter
* Add 0004_commentary migration

settings
--------

* Remove COMMENTS_ALLOW_PROFANITIES
* Remove COMMENTS_MAX_LENGTH
* Add COMMENTS_ALLOW_HTML
* Add COMMENTS_WIDGET

Comment
-------

* Add is_editable_by
* Add is_removable_by
* Add Meta.index_together

CommentAbstractModel
--------------------

* Remove user_{name,email,url}
* Remove ip_address
* Rename comment -> body
* Add edit_date
* Add parent
* Add is_edited
* Add user_display

CommentsAdmin
-------------

* Remove fieldsets

CommentForm
-----------

* Remove get_comment_model()
* Remove get_comment_create_data()
* Remove clean_comment()
* Rename check_for_duplicate_comment() -> _prevent_duplicates()

CommentManager
--------------

* Add top_level()

LatestCommentFeed
-----------------

* Remove link()
* Add item_updateddate()
* Add item_author_name()
  • Loading branch information
ObserverOfTime committed Oct 4, 2019
1 parent 02474a0 commit 2998675
Show file tree
Hide file tree
Showing 226 changed files with 1,346 additions and 1,435 deletions.
19 changes: 19 additions & 0 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Security Policy

## Supported Versions

| Version | Supported |
|:---------:|:------------------:|
| 2.0.x | :heavy_check_mark: |
| <2.0.x | :x: |

## Reporting a Vulnerability

* Do not create issues to report security vulnerabilities.
* Instead, please e-mail one of the maintainers at [[email protected]](mailto:[email protected]) or [[email protected]](mailto:[email protected]).
* Do not include any confidential information in the e-mail.
* Provide your GitHub username (if available), so that we can invite you to collaborate on a [security advisory][advisories] on GitHub.

[advisories]: https://help.github.com/en/articles/about-maintainer-security-advisories

<!-- vim:set wrap brk=\ !*-+;,? lbr: -->
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.egg-info
.tox/
docs/_build
.venv/
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ matrix:
- python: 3.7
env: TOXENV=py37-django-master
allow_failures:
- env: TOXENV=py35-django-master
- env: TOXENV=py36-django-master
- env: TOXENV=py37-django-master
install:
- pip install tox
- pip install tox
script:
- tox
- tox
9 changes: 0 additions & 9 deletions .tx/config

This file was deleted.

6 changes: 5 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
History
=======

2.0.0 (upcoming)
----------------

* Forked and rebranded into ``django-commentary``.

1.9.1 (2019-02-20)
------------------

Expand Down Expand Up @@ -80,7 +85,6 @@ History

* Fixed migrations not working when installed as an egg.


1.6.0 (2016-04-29)
------------------

Expand Down
1 change: 1 addition & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Copyright (c) 2019, MangAdventure
Copyright (c) 2013, Django Software Foundation and individual contributors

All rights reserved.
Expand Down
4 changes: 2 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ include HISTORY.rst
include LICENSE.txt
recursive-include docs *
recursive-include tests *
recursive-include django_comments/templates *
recursive-include django_comments/locale *
recursive-include commentary/templates *
recursive-include commentary/locale *
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
32 changes: 22 additions & 10 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
===========================
Django "excontrib" Comments
===========================
=================
Django Commentary
=================

.. image:: https://img.shields.io/pypi/v/django-contrib-comments.svg
:target: https://pypi.python.org/pypi/django-contrib-comments
.. image:: https://img.shields.io/pypi/v/django-commentary.svg?label=PyPI&logo=pypi
:target: https://pypi.python.org/pypi/django-commentary
:alt: PyPI

.. image:: https://img.shields.io/travis/django/django-contrib-comments.svg
:target: http://travis-ci.org/django/django-contrib-comments
.. image:: https://img.shields.io/travis/mangadventure/django-commentary?label=Travis&logo=travis
:target: https://travis-ci.org/mangadventure/django-commentary
:alt: Travis CI

Django used to include a comments framework; since Django 1.6 it's been
separated to a separate project. This is that project.
This is a fork of `django-contrib-comments`__ with the following changes:

* |c| Only users can post comments.
* |c| Previews have been removed.
* |c| Posting a comment redirects to the comment page.
* |u| Post/flag/approve/delete redirect back to the page.
* |u| Users can edit and delete their own comments.
* |u| Comments are threaded.

This framework can be used to attach comments to any model, so you can use it
for comments on blog entries, photos, book chapters, or anything else.

For details, `consult the documentation`__.

__ https://django-contrib-comments.readthedocs.io/
__ https://github.com/django/django-contrib-comments
__ https://django-commentary.readthedocs.io

.. |u| unicode:: U+2610
.. |c| unicode:: U+2611
119 changes: 119 additions & 0 deletions commentary/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from importlib import import_module

from django.apps import apps
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.urls import reverse
from django.utils.module_loading import import_string


def _get_setting(setting, default):
return getattr(settings, 'COMMENTS_' + setting, default)


COMMENTS_TIMEOUT = _get_setting('TIMEOUT', 360) # 1h
COMMENTS_ALLOW_HTML = _get_setting('ALLOW_HTML', False)
COMMENTS_HIDE_REMOVED = _get_setting('HIDE_REMOVED', True)
COMMENTS_WIDGET = _get_setting('WIDGET', 'django.forms.Textarea')

if isinstance(COMMENTS_WIDGET, str):
COMMENTS_WIDGET = import_string(COMMENTS_WIDGET)

DEFAULT_COMMENTS_APP = 'commentary'


def get_comment_app():
"""
Get the comment app (i.e. "commentary") as defined in the settings
"""
# Make sure the app's in INSTALLED_APPS
comments_app = _get_setting('APP', DEFAULT_COMMENTS_APP)
if not apps.is_installed(comments_app):
raise ImproperlyConfigured(
'The COMMENTS_APP (%r) must be in INSTALLED_APPS' % 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-existent package. (%s)' % e
)

return package


def _check_attr(attr):
app = get_comment_app()
return app.__name__ != DEFAULT_COMMENTS_APP and hasattr(app, attr)


def get_model():
"""
Returns the comment model class.
"""
if _check_attr('get_model'):
return get_comment_app().get_model()
else:
from commentary.models import Comment
return Comment


def get_form():
from commentary.forms import CommentForm
"""
Returns the comment ModelForm class.
"""
if _check_attr('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 _check_attr('get_form_target'):
return get_comment_app().get_form_target()
else:
return reverse('comments-post-comment')


def get_flag_url(comment):
"""
Get the URL for the "flag this comment" view.
"""
if _check_attr('get_flag_url'):
return get_comment_app().get_flag_url(comment)
else:
return reverse('comments-flag', args=(comment.id,))


def get_delete_url(comment):
"""
Get the URL for the "delete this comment" view.
"""
if _check_attr('get_delete_url'):
return get_comment_app().get_delete_url(comment)
else:
return reverse('comments-delete', args=(comment.id,))


def get_approve_url(comment):
"""
Get the URL for the "approve this comment from moderation" view.
"""
if _check_attr('get_approve_url'):
return get_comment_app().get_approve_url(comment)
else:
return reverse('comments-approve', args=(comment.id,))


def get_user_display(user):
"""Get the full name or username to display for a user."""
if _check_attr('get_user_display'):
return get_comment_app().get_user_display(user)
else:
return user.get_full_name() or user.get_username()
138 changes: 138 additions & 0 deletions commentary/abstracts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
from __future__ import unicode_literals

from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site
from django.db import models
from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible
from django.utils.html import strip_tags
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _

from . import COMMENTS_ALLOW_HTML, get_user_display
from .managers import CommentManager


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', on_delete=models.CASCADE
)
object_pk = models.CharField(_('object ID'), max_length=255)
content_object = GenericForeignKey(
ct_field='content_type', fk_field='object_pk'
)

# Metadata about the comment
site = models.ForeignKey(Site, on_delete=models.CASCADE)

class Meta:
abstract = True

def get_content_object_url(self):
"""
Get a URL suitable for redirecting to the content object.
"""
return reverse(
'comments-url-redirect',
args=(self.content_type_id, self.object_pk)
)


@python_2_unicode_compatible
class CommentAbstractModel(BaseCommentAbstractModel):
"""
A user comment about some object.
"""
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name='%(class)s_comments',
verbose_name=_('user'), blank=True,
null=True, on_delete=models.SET_NULL
)

body = models.TextField(_('comment'), db_column='comment')

submit_date = models.DateTimeField(
_('date/time submitted'), auto_now_add=True, db_index=True
)
edit_date = models.DateTimeField(
_('date/time of last edit'), auto_now=True, db_index=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.'
)
)

parent = models.ForeignKey(
'self', related_name='replies', blank=True,
null=True, on_delete=models.CASCADE
)

# TODO: add upvotes & downvotes

# Manager
objects = CommentManager()

class Meta:
abstract = True
ordering = ('submit_date',)
permissions = (
('can_moderate', 'Can moderate comments'),
)
verbose_name = _('comment')
verbose_name_plural = _('comments')

def __str__(self):
return '%s: %s...' % (self.user_display, strip_tags(self.body)[:50])

@property
def is_edited(self):
"""Check whether this comment has been edited."""
return self.submit_date != self.edit_date

@property
def user_display(self):
"""Display the full name/username of the commenter."""
return get_user_display(self.user)

@cached_property
def _date(self):
return self.submit_date.date()

def get_absolute_url(self, anchor_pattern='#c%(id)s'):
return self.get_content_object_url() + (anchor_pattern % self.__dict__)

def strip_body(self):
return strip_tags(self.body) if COMMENTS_ALLOW_HTML else self.body

def get_as_text(self):
"""
Return this comment as plain text. Useful for emails.
"""
return _(
'Posted by %(user)s at %(date)s\n\n'
'%(comment)s\n\nhttp://%(domain)s%(url)s'
) % {
'user': self.user_display,
'date': self.submit_date,
'comment': self.strip_body(),
'domain': self.site.domain,
'url': self.get_absolute_url()
}
Loading

0 comments on commit 2998675

Please sign in to comment.