django-comments-xtd icon indicating copy to clipboard operation
django-comments-xtd copied to clipboard

Question: How can I get user comments?

Open ogurec-ogurec opened this issue 5 years ago • 14 comments

I had a small question, how can I get / display the comments of a specific user (User) and show them in the template?

ogurec-ogurec avatar Jun 16 '20 06:06 ogurec-ogurec

Such a feature is not provided. You can implement it yourself though. Only be aware that comments are not always associated with registered users. If you send a comment as a visitor, providing a name and an email address, that comment in the DB won't have a User object associated, but just the name and the email of the visitor.

Apart from that, you can create your own template tag that receives the user instance you want to filter for. I would do it with an inclusion tag.

Let's say you want to display the list of comments a user has posted on the User Profile page. So your project has a template called profile.html in which you can access the user via the request object: request.user. Then create a inclusion tag that receives the user as a parameter. Something like this:

@register.inclusion_tag("mysite/comments_from_user.html")
def comments_from_user(user):
    comments = XtdComment.objects.filter(user=user)
    return {'comments': 'comments'}

And create the template mysite/comments_from_user.html in which you render the context variable comments that you receive from the inclusion tag.

danirus avatar Jun 17 '20 06:06 danirus

Thank you for the detailed answer. That's what I did: Folder templatestags/get_comments_user.py

from django import template
from django_comments_xtd import get_model as get_comment_model

register = template.Library()
XtdComment = get_comment_model()

@register.inclusion_tag("users/profile/comments_from_user.html")
def comments_from_user(user):
    comments = XtdComment.objects.filter(user=user)
    return {'comments': 'comments'}

Template users/profile/comments_from_user.html

{% extends "base.html" %}
{% load comments %}
{% load i18n %}
{% load comments_xtd %}

{% block content %}

{% load get_comments_user %}
{% comments_from_user %}

{% for comment in comments %}
         {{comment}}
{% endfor %}

{% endblock content %}

Template users/profile/profile.html

{% load get_comments_user %}
{% comments_from_user %}

I get an error at startup:

TemplateSyntaxError at /profile
'comments_from_user' did not receive value(s) for the argument(s): 'user'

views.py

@login_required
def profile(request):
    user = request.user
    return render(request,'users/profile/profile.html', {'user': user})

What could be the mistake here?

ogurec-ogurec avatar Jun 17 '20 11:06 ogurec-ogurec

In users/profile/profile.html you have to pass the user:

{% load get_comments_user %}
{% comments_from_user user %}

danirus avatar Jun 17 '20 11:06 danirus

Thank you very much. Everything is working! A small point on the display of the list is the quotation of comments with a limited number of characters:

Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...

How can this be fixed? And how can I access the comment fields?

I used template users/profile/comments_from_user.html:

{% for comment in comments %}
    {{comment}}
{% endfor %}

ogurec-ogurec avatar Jun 17 '20 12:06 ogurec-ogurec

Thank you very much. Everything is working! A small point on the display of the list is the quotation of comments with a limited number of characters:

Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...
Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...

How can this be fixed?

Sorry, I don't understand. What do you mean?

And how can I access the comment fields?

A comment has many fields. The comment model is made of several classes. You could open the django console, import the model and list the attributes:

$ python manage.py shell
>>> from django_comments_xtd.models import XtdComment
>>> dir(XtdComment)

The comment itself is in the comment field.

danirus avatar Jun 18 '20 05:06 danirus

Sorry, I don't understand. What do you mean?

Comments are displayed with limited characters, as if it were a quote. 50 characters from the comment.Here is an example (limited comment example):

Jhon: Lorem ipsum dolor sit amet, consectetur adipiscing...

I would like to display the entire comment. But I don’t know how

ogurec-ogurec avatar Jun 18 '20 21:06 ogurec-ogurec

@danirus I did it, now I have a question, how to get a link to a post where a user comment is left?

{% for comment in comments %}
  <li>
      {{comment.user_name}} //name user
      {{comment.comment}} //content comment user
       **link to the post where the comment is left** ?
  </li>
{% endfor %}
</ul>

I will be grateful for the help

ogurec-ogurec avatar Jun 22 '20 10:06 ogurec-ogurec

Each comment has the content_object attribute, representing the object instance to which the comment was posted. You could use the get_absolute_url method of the content_object to retrieve the URL of that instance, like this:

{{ comment.content_object.get_absolute_url }}

danirus avatar Jun 26 '20 07:06 danirus

thanks for the answer. Added by

{% for comment in comments %}
  <li>
      {{comment.user_name}} //name user
      {{comment.comment}} //content comment user
       {{ comment.content_object }}
  </li>
{% endfor %}
</ul>

got an error:

AttributeError at /profile
'NoneType' object has no attribute '_base_manager'

ogurec-ogurec avatar Jun 26 '20 16:06 ogurec-ogurec

I would suggest you to run the comp example (see instructions on how to set it up here in the docs). Set it up, load the DB and run the site. Then the comments page. That page uses the comment.html template, which displays the link to the instance to which the comment was posted. It's in line 11, here.

The reason why it doesn't work for you seems to be that the content_object attribute is None. Check the list of comments yourself in the Django console. See if you can list all the comments for the particular user in the console:

$ python manage.py shell_plus
In [1]: user = User.objects.get(email="[email protected]")
In [2]: comments = XtdComment.objects.filter(user=user)
In [3]: for cm in comments:
   ...:     print(cm.content_object)
Unusual farewell
On education

It should not display a None. All the comments have to have a valid content_object. This little bit of code I add here works for the comp example, but it should work for your project too (just use the email address of your user).

danirus avatar Jun 27 '20 09:06 danirus

Thanks a lot, it works! Interestingly, but if I try to get it for ordinary users (which is registered), then everything works fine. BUT if I try to get this for the admin user, I get an error:

Console:

>>> from django.contrib.auth.models import User
>>> from django_comments_xtd import get_model as get_comment_model
>>> XtdComment = get_comment_model()

>>> user = User.objects.get(email="[email protected]")
>>> comments = XtdComment.objects.filter(user=user)

>>> for cm in comments:
...      print (cm.content_object)

Showing articles in the console:

Articles 1 Articles 2 Articles 2 Articles 4

But then at the end I get an error:

Traceback (most recent call last):
  File "<console>", line 2, in <module>
  File "..\lib\site-packages\django\contrib\contenttypes\fields.py", line 243, in __get__rel_obj =ct.get_object_for_this_type(pk=pk_val)
  File "..\lib\site-packages\django\contrib\contenttypes\models.py", line 175, in get_object_for_this_type return self.model_class()._base_manager.using(self._state.db).get(**kwargs)
AttributeError: 'NoneType' object has no attribute '_base_manager'

I repeat, for ordinary users (not an administrator), everything works

ogurec-ogurec avatar Jun 27 '20 11:06 ogurec-ogurec

how can I get the number (number) of user comments and the number of likes / anti-likes for comments in this user template?

ogurec-ogurec avatar Jul 06 '20 12:07 ogurec-ogurec

Think on this applied to the models you actually mentioned. Hint: likes/disliked are instances of the CommentFlag model, and comments of XtdComment.

danirus avatar Jul 06 '20 19:07 danirus

thanks, but I still don’t understand how I can show the number of likes in this template.

ogurec-ogurec avatar Jul 09 '20 14:07 ogurec-ogurec