justquick / django-activity-stream

Generate generic activity streams from the actions on your site. Users can follow any actors' activities for personalized streams.
http://django-activity-stream.rtfd.io/en/latest/
BSD 3-Clause "New" or "Revised" License
2.39k stars 484 forks source link

Documentation is not so good for newbie #162

Closed robinlery closed 2 years ago

robinlery commented 11 years ago

Hi. I just found about django-activity-stream. As a newbie, to create something like activity feeds in not a good idea. So I was very excited to use django-activity-stream. But I felt that the documentation was not up to what I can understand to. It was not so hard to grasp the idea behind. But "how-to" do x to get y, was a bit exhausting for me. I installed it, and added the app in my settings, and then I was lost! It would be really great, if the documentation was improved from a newbie's point of view. Best wishes! Thank you.

justquick commented 11 years ago

what would you add? where exactly did you get lost?

mayuroks commented 10 years ago

One or two simple examples at the end of the documentation could have served as solid starting points. Even Djangodocs have polls app as a demo example. The newbie's point of view robinlery is talking about is taking a simple example and describing it like a flow of simple events / instructions, if I am guessing it correct.

robinlery commented 10 years ago

Yes, @mayuroks, you are right. One or two examples would have helped me greatly, and also maybe to other newbie. @justquick I got lost in the topic 'Generating Action'. Could you please make a tutorial regarding generating acitivities of two models. I will be very grateful. Thank you.

leesolway commented 10 years ago

I would also like to see a few tutorials.

justquick commented 10 years ago

agreed. i think i can come up with something based on the polls tutorial

michaeljones commented 10 years ago

+1

Very excited to see this project as I'd love to integrate notifications and activity streams into my project but I am struggling with the documentation. It looks great and feels extensive but it is a bit rough on newcomers. Almost as if it assumes you completely understand activity streams and are just after a Django compatible API for it.

As an example, I have an project that manages events, organisations and venues. To start, I wanted to produce a activity-stream entry when a new Venue is created by a user and then show that information to the site moderators. Here are my current sources of confusion (not that I expect you to explain it all to me here, just to give you an idea of where a newbie might struggle):

Writing this out is helping me to understand it a little more as I read and re-read the docs but I don't feel it is very clear.

It is possible that your target audience is people who are more experienced than me, but if you'd like to open it up a little, I'd recommend adding a bit more to the docs.

I'd be happy to try to contribute suggestions if you're open to pull requests. Perhaps it would help me to further understand the system.

Anyway, I'm still super excited about the project. I just hope this helps a little. Michael

brunoamaral commented 10 years ago

I was following the documentation and got all the way to Generating Actions as well.

Please tell me if I got this right: the action.send should be used when the object is being saved to the database right?

What if we want to tie an action to the admin interface, to lets say, admin marks an object with published=True?

michaeljones commented 10 years ago

I'm still learning this myself but action.send creates a new Action entry in the database which can be queried into an activity-stream through the Action Manager methods.

If you want an Action that represent the object being saved to the database then you would call action.send when you save the object or add a post_save hook as the first example on the Generating Actions page.

If you want to tie an action to the admin interface then you might want to look into Django Admin Actions where you will be able to write your own publish action which calls action.send from the function you write.

Sorry if you know this already, but I'm just trying to help.

brunoamaral commented 10 years ago

@michaeljones you are right, tying it to an admin action does help. It won't however trigger if the user is saving an object inside it's own form view.

michaeljones commented 10 years ago

It seems that you can also override the form used by the Admin view for your Model. Perhaps you can write one that detects if 'published' is being checked and creates an action.

brunoamaral commented 10 years ago

@michaeljones correct, and you can also override the default Model.save() method. I added a pull request with that reference.

ryangallen commented 9 years ago

@brunoamaral you can call action.send() in an admin.py save_model method https://docs.djangoproject.com/en/1.7/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model

jaineshp commented 9 years ago

@justquick : Is there any example app? That would do great! Thank you.

druss16 commented 9 years ago

@justquick any examples created for this django-activity-stream? Very difficult as a newb to follow documentation. Would love to know if there is a tutorial or example available. Thank you very much!

rolandgeider commented 9 years ago

I recently added django-activity-stream to a project of mine, once you get the two or three concepts needed, it's easy. At the moment I don't have much time, but I could image helping with this.

druss16 commented 9 years ago

@rolandgeider Thanks for your response. If you don't mind me asking, what specific two or three concepts are you referring to?

In theory, after reading @justquick docs and activitystrea.ms, I think I understand the idea of an actor, verb, action object, and target, but just do not know how to connect the dots within django. Where I think my difficulty is is understanding the interaction between signals.py, managers.py, models, views, and templates, in order to render a stream and store in the database.

Without giving away anything proprietary, would you happen to have any images that illustrate the connection between these files and how you were able to ultimately render your stream? Thanks in advance!

rolandgeider commented 9 years ago

@druss16 sure, there's nothing proprietary, everything I do is open source :smile: My project is a fitness manager with users, workouts, logs, etc. I am implementing a group feature with a stream.

  1. Register all the models that will be part of the stream
  2. Find all places where some interesting event happens, in my case when a user creates a group, leaves a group, adds a workout, and so on. Here you need to understand what those actors, verbs, targets are. Deciding when and what to "log" something is actually the hard part
  3. Once you have this, the rest is basically just "filtering" by whatever you need. In my case I am only interested on seeing what happened with a group, regardless of who did what. There are other methods so you can see what a certain user did, can follow and unfollow people, etc. but that is nothing special, in all cases you get an activity stream back.
  4. Rendering depends on what you want to present, what I did (and please note that this is very much a work in progress) is this. You get objects with the same verbs, actors, etc. that you created and run with that.

Hope that helps!

Edit: link to files in specific commit, not branch as then the line number can change

druss16 commented 9 years ago

Wow! Roland (@rolandgeider) I can't thank you enough for sending this! Really appreciate your help and generosity. These four steps successfully connected the remaining dots. Now I have a functioning activity stream! (It's not pretty by any means, but now that I understand what's going on, I will go ahead and iterate and continue customizing). I can't tell you how relieving this is. This was a 4 or 5 week hurdle that I just couldn't seem to overcome; so again, I appreciate your time and willingness to help. (I will have to pay it forward some day.)

I am very impressed by the website you built. Judging by both the code and user interface, it seems very robust and comprehensive. I am an athlete myself and workout every so often. I will have to play around with this a bit. Hopefully, some day I will achieve your skill level!

Cheers, Dan

rolandgeider commented 9 years ago

@druss16 Dan, thanks for the kind words! :) This is one of those once you understand it, it's easy type of things, when I started I was also confused about what steps should be done in what order.

I'm also glad you like my project, if you ever want to hack on it, just ping me!

druss16 commented 9 years ago

@rolandgeider Hope all is well. I actually had one more additional question regarding the activity stream if you didn't mind taking the time to provide some more insight. I was able to get my activity stream up and running, as a result of the guidance you provided, but was wondering if you had any best practices in regards to rendering an image within the activity stream.

For example, if "Betty posted a picture to the group" rather than just rendering that activity via text, what's the best way to render the actual image of the 'picture' betty posted? and her profile image?

Any thoughts or feedback that you could provide on this particular roadblock would be very much appreciated!

Thanks, Dan

rolandgeider commented 9 years ago

Hi @druss16!

Glad you could work on! I still want to sit down and polish my other message enough that I can send a PR. One day... :)

While I have not images in my activity stream (yet, but they are planed), I would imagine that since you have access to the objects in the template, you could just check if they have an "image" property (or whatever you've called it) and try to render that? Perhaps something like this? (this is really from the top of my head and not tested in any way!):

{% if event.action_object.image %}
    <img  src="{{ event.action_object.image.url }}"> <!-- is it called .url?? never sure about that -->
{% else %}
    <!-- something else -->
{% endif %}
csawtelle commented 7 years ago

Documentation is unclear in a few parts, heres is one example:


urlpatterns = patterns('',
    ...
    ('^activity/', include('actstream.urls')),
    ...
)

Adding this to the app/urls.py

from django.conf.urls import url, include
from django.contrib import admin

#To show images
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    ('^activity/', include('actstream.urls')),
]

generates an error, that is hard to debug

`Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/django/utils/autoreload.py", line 227, in wrapper
    fn(*args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/django/core/management/commands/runserver.py", line 125, in inner_run
    self.check(display_num_errors=True)
  File "/usr/local/lib/python3.5/dist-packages/django/core/management/base.py", line 359, in check
    include_deployment_checks=include_deployment_checks,
  File "/usr/local/lib/python3.5/dist-packages/django/core/management/base.py", line 346, in _run_checks
    return checks.run_checks(**kwargs)
  File "/usr/local/lib/python3.5/dist-packages/django/core/checks/registry.py", line 81, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/usr/local/lib/python3.5/dist-packages/django/core/checks/urls.py", line 16, in check_url_config
    return check_resolver(resolver)
  File "/usr/local/lib/python3.5/dist-packages/django/core/checks/urls.py", line 26, in check_resolver
    return check_method()
  File "/usr/local/lib/python3.5/dist-packages/django/urls/resolvers.py", line 254, in check
    for pattern in self.url_patterns:
  File "/usr/local/lib/python3.5/dist-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.5/dist-packages/django/urls/resolvers.py", line 405, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/usr/local/lib/python3.5/dist-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.5/dist-packages/django/urls/resolvers.py", line 398, in urlconf_module
    return import_module(self.urlconf_name)
  File "/usr/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/build/MatchAdemics/phdmatch/urls.py", line 25, in <module>
    ('^activity/', include('actstream.urls')),
  File "/usr/local/lib/python3.5/dist-packages/django/conf/urls/__init__.py", line 50, in include
    urlconf_module = import_module(urlconf_module)
  File "/usr/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/usr/local/lib/python3.5/dist-packages/actstream/urls.py", line 5, in <module>
    from django.conf.urls.defaults import url, patterns
ImportError: No module named 'django.conf.urls.defaults'
justinpitcher commented 7 years ago

Without checking, I believe you're missing an import of the urls at the top of the file.

go-run-jump commented 7 years ago

Actually this happens because patterns has been depreciated in django (the issue was solved in #320). The easiest way to proceed, is to install the development version until a new version of django-activity-stream is released.

$ pip install git+https://github.com/justquick/django-activity-stream.git#egg=actstream

Furthermore you should use url in the urlpatterns instead of the tuple:

urlpatterns = [
    url('^activity/', include('actstream.urls')),
]
elebumm commented 6 years ago

I took hours trying to figure this out and I will agree that the documentation does need work. I found @rolandgeider's walkthrough to be extremely helpful and I am extremely thankful for the time you took to walkthrough.

That being said, I love this project. It's super powerful and has saved me a lot of time despite struggling through the documentation. I am going to try working on different examples and help write the documentation with a little bit more examples.