Package: django-add-comments
django-add-commentsAddcommentsto a Django model via mixin:# app/models.pyfromcomment.modelsimportAbstractCommentable# import mixinclassSentinel(AbstractCommentable):# add to class declaration"""Any `app`, e.g. `essay`, `article`... can be 'commentable'."""title=models.CharField(max_length=50)ActionAuthorizationDescriptionView comments listAll usersAdd filter public/private laterGet comment formAuthenticated usersReactive via htmx / hyperscript [^1]Delete / edit commentAuthorized authorsReactive via htmx / hyperscript [^1]SetupLoad virtual env.venv>poetryadddjango-add-comments# pip3 install django-add-commentsWill include dependencies frompyproject.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.pyINSTALLED_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.pyfromdjango.urlsimportpath,include# newurlpatterns=[...,path('comments/',include('comments.urls'))# routes for update, delete, view, toggle comment]Add Comment model to database.venv>pythonmanage.pymigrateConfigurationWhat 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 dummySentinelmodel to represent this construct.Let's say we've initialized one model instance calledobjwithslug="a-sample-title".What we'd like is the ability to write a comment toobjthrough a url represented by:obj.add_comment_url@add_comment_urlthus needs to become a property of theSentinelmodel.Add imports# sentinels/models.pyfromcomments.modelsimportAbstractCommentable# newfromdjango.template.responseimportTemplateResponse# newfromdjango.urlsimportreverse,URLPattern# newfromdjango.utils.functionalimportcached_property,classproperty# newMake sentinel model inherit from abstract base model# sentinels/models.pyclassSentinel(AbstractCommentable):# new...Add model properties# sentinels/models.pyclassSentinel(AbstractCommentable):id=models.UUIDField...# identifier is UUIDslug=models.Slugfield...@cached_property# copy this to the sentinel model, note `slug` as identifierdefadd_comment_url(self)->str:returnself.set_add_comment_url(self.slug)@classmethod# copy this to the sentinel model, note `slug` as identifierdefadd_comment_func(cls,request,slug:str)->TemplateResponse:target=cls.objects.get(slug=slug)returncls.allow_commenting_form_on_target_instance(request,target)@classproperty# copy this to the sentinel model, note `slug` as identifierdefadd_comment_path(cls)->URLPattern:returncls.set_add_comment_path("<slug:slug>",cls.add_comment_func)Gotcha: ifpkis identifier, revise<slug:slug>to<pk:int>above:self.set_add_comment_url(self.pk)def add_comment_func(cls, request, pk: int):target = cls.objects.get(pk=pk)cls.set_add_comment_path("<int:pk>", cls.add_comment_func)Add sentinel namespaced url for adding commentsAdd path to the sentinel's url patterns:# sentinels/urls.pyfrom.modelsimportSentinelfrom.appsimportSentinelConfig# already pre-made during `python manage.py startapp sentinels`app_name=SentinelConfig.name# remember the `app_name` in relation to the `add_comment_url` propertyurl_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 commentsAdd template tag to sentinel's template to show form with list<!-- sentinels/templates/sentinel_detail.html --><h1>Title:{{object.title}}</h1>{%loadcomments%}<!-- see templatetags/comments.py which contains `object.add_comment_url`  -->{%list_commentssentinel_target_obj=objecthead_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 intemplate tag.[^1]:No page refresh