Giter Site home page Giter Site logo

django-add-comments's Introduction

django-add-comments

Add comments to a Django model via mixin:

# app/models.py
from comment.models import AbstractCommentable  # import mixin


class Sentinel(AbstractCommentable):  # add to class declaration
    """Any `app`, e.g. `essay`, `article`... can be 'commentable'."""

    title = models.CharField(max_length=50)
Action Authorization Description
View comments list All users Add filter public/private later
Get comment form Authenticated users Reactive via htmx / hyperscript 1
Delete / edit comment Authorized authors Reactive via htmx / hyperscript 1

Setup

Load virtual env

.venv> poetry add django-add-comments # pip3 install django-add-comments

Will include dependencies from pyproject.toml:

python = "^3.8"
Django = "^4.0"
django-extensions = "^3.1.5"
django-crispy-forms = "^1.13.0"

Add app to project settings

# in project_folder/settings.py
INSTALLED_APPS = [
    ...,
    "crispy_forms",  # add crispy_forms at least > v1.13, if not yet added
    "comments",  # this is the new django-comments folder
]

Add basic routes to urlpatterns

# in project_folder/urls.py
from django.urls import path, include  # new

urlpatterns = [
    ...,
    path(
        "comments/", include("comments.urls")
    ),  # routes for update, delete, view, toggle comment
]

Add Comment model to database

.venv> python manage.py migrate

Configuration

What we're going to do

>>> obj = Sentinel.objects.create(title="A sample title") # instance is made, e.g. id=1, id=2, etc.
>>> obj.add_comment_url # url to add a comment to `A sample title`

A sentinel is the model being commented on.

We've created a dummy Sentinel model to represent this construct.

Let's say we've initialized one model instance called obj with slug="a-sample-title".

What we'd like is the ability to write a comment to obj through a url represented by: obj.add_comment_url

@add_comment_url thus needs to become a property of the Sentinel model.

Add imports

# sentinels/models.py
from comments.models import AbstractCommentable  # new
from django.template.response import TemplateResponse  # new
from django.urls import reverse, URLPattern  # new
from django.utils.functional import cached_property, classproperty  # new

Make sentinel model inherit from abstract base model

# sentinels/models.py
class Sentinel(AbstractCommentable):  # new
    ...

Add model properties

# sentinels/models.py
class Sentinel(AbstractCommentable):
    id = models.UUIDField
    slug = models.Slugfield

    @cached_property  # copy this to the sentinel model, note `slug` as identifier
    def add_comment_url(self) -> str:
        return self.set_add_comment_url(self.slug)

    @classmethod  # copy this to the sentinel model, note `slug` as identifier
    def add_comment_func(cls, request, slug: str) -> TemplateResponse:
        target = cls.objects.get(slug=slug)
        return cls.allow_commenting_form_on_target_instance(request, target)

    @classproperty  # copy this to the sentinel model, note `slug` as identifier
    def add_comment_path(cls) -> URLPattern:
        return cls.set_add_comment_path("<slug:slug>", cls.add_comment_func)

Gotcha: if pk is identifier, revise <slug:slug> to <pk:int> above:

  1. self.set_add_comment_url(self.pk)
  2. def add_comment_func(cls, request, pk: int):
  3. target = cls.objects.get(pk=pk)
  4. cls.set_add_comment_path("<int:pk>", cls.add_comment_func)

Add sentinel namespaced url for adding comments

Add path to the sentinel's url patterns:

# sentinels/urls.py
from .models import Sentinel
from .apps import (
    SentinelConfig,
)  # already pre-made during `python manage.py startapp sentinels`

app_name = (
    SentinelConfig.name
)  # remember the `app_name` in relation to the `add_comment_url` property
url_patterns = [
    Sentinel.add_comment_path,  # This is really just a shortcut to a created path.
    ...,
]

Add template tag for displaying comment form with list of added comments

Add template tag to sentinel's template to show form with list

<!-- sentinels/templates/sentinel_detail.html -->
<h1>Title: {{ object.title }}</h1>
{% load comments %} <!-- see templatetags/comments.py which contains `object.add_comment_url`  -->
{% list_comments sentinel_target_obj=object head_label='Add an Answer'%}
<!-- the `object` is whatever variable passed to the template, the head_label provides an ability to label the items to be inputted. The default is 'Add a Comment' -->

The form that represents this "add comment" action / url will be loaded in every comment list. See context in template tag.

Footnotes

  1. No page refresh 2

django-add-comments's People

Contributors

justmars avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.