GithubHelp home page GithubHelp logo

django-wiki / django-nyt Goto Github PK

View Code? Open in Web Editor NEW
141.0 141.0 46.0 710 KB

Notification system for Django with batteries included: Email digests, user settings, JSON API

License: Apache License 2.0

Python 84.17% Makefile 1.17% CSS 4.45% HTML 10.21%

django-nyt's Introduction

django-wiki

Docs Build status Coverage Status PyPi Downloads IRC

Django support

The below table explains which Django versions are supported.

Release Django Upgrade from
0.11.x 3.2, 4.0, 4.1, 4.2, 5.0 0.10
0.10.x 2.2, 3.0, 3.1, 3.2, 4.0, 4.1, 4.2 0.7
0.9.x 2.2, 3.0, 3.1, 3.2, 4.0 0.7
0.8.x 2.2, 3.0, 3.1, 3.2, 4.0 0.7
0.7.x 2.2, 3.0, 3.1, 3.2 0.5 or 0.6
0.6.x 2.1, 2.2, 3.0 0.5
0.5.x 2.1, 2.2 0.4
0.4.x 1.11, 2.0, 2.1 0.3
0.3.x 1.8, 1.9, 1.10, 1.11 0.2
0.2.x 1.8, 1.9, 1.10 0.1
0.1.x 1.5, 1.6, 1.7 0.0.24
0.0.24 1.4, 1.5, 1.6 1.7 (unstable) 0.0.?

For upgrade instructions, please refer to the Release Notes

Translations (Transifex)

Django-wiki is fully translated into 13 languages, apart from the default (English) and some additional languages underway.

But please help out in adding more languages! It's very easy and you don't even need to be a programmer.

Some languages...

  • ...just need a little push, as they are almost fully complete
  • ...got initiated and need a new instigator to carry on the ambitions
  • ...do not exist yet - but you can request them and become the coordinator

Visit the django-wiki project on Transifex

Demo

A demo running the latest main branch is available here:

https://demo.django-wiki.org

Sign up for an account to see the notification system, or you can log in with the existing account:

  • user: admin
  • password:admin

Community

Please use our IRC or mailing list (google group) for getting in touch on development and support. Please do not email developers asking for personal support.

Always a work in progr...

On a number of factors, this project has proven itself useful and stable.

  • There won't be changes that are expected to cause loss of data without a proper upgrade path.
  • The model API has been very stable and is only subject to smaller changes.
  • The plugin API seems pretty stable.
  • You can maintain the latest version of django-wiki through PyPi (package name: wiki), using SemVer versioning schema.

What should I customize? What can break?

You will need to learn a bit of Django to customize django-wiki.

The simplest is to override templates and create your own template tags. Do not make your own hard copy of this repository in order to fiddle with internal parts of the wiki, this strategy will lead you to lose out on future updates with highly improved features, plugins and security fixes.

You can also override the whole Bootstrap theming. At present, you're best off maintaining your own Bootstrap SCSS and hard-copying, then overriding django-wiki's rules.

All Python views are class-based. However for most cases overriding views and URLs shouldn't be the best place to start since most customization can be achieved through plugins, templates and SCSS.

Contributing

Contributions are welcome! ❤️

Please read our Developer Guide

Manifesto

Django needs a mature wiki system appealing to all kinds of needs, both big and small:

  • Be pluggable and light-weight. Don't integrate optional features in the core.
  • Be open. Make an extension API that allows the ecology of the wiki to grow in a structured way. Wikipedia consists of over 1100 extension projects written for MediaWiki. We should learn from this.
  • Be smart. This is the map of tables in MediaWiki - we'll understand the choices of other wiki projects and make our own. After-all, this is a Django project.
  • Be simple. The source code should almost explain itself.
  • Be structured. Markdown is a simple syntax for readability. Features should be implemented either through easy coding patterns in the content field, but rather stored in a structured way (in the database) and managed through a friendly interface. This gives control back to the website developer, and makes knowledge more usable. Just ask: Why has Wikipedia never changed? Answer: Because it's knowledge is stored in a complicated way, thus it becomes very static.

Docs

See the docs/ folder, or read them at:

https://django-wiki.readthedocs.io/en/latest/

If you wish to add something, please ask in the google group or raise an issue if you're in doubt about whether something might change.

Background

Django-wiki is a rewrite of django-simplewiki, a project from 2009 that aimed to be a base system for a wiki. It proposed that the user should customize the wiki by overwriting templates, but soon learned that the only customization that really took place was that people forked the entire project. We don't want that for django-wiki, we want it to be modular and extendable.

As of now, Django has existed for too long without a proper wiki application. The dream of django-wiki is to become a contestant alongside Mediawiki, so that Django developers can stick to the Django platform even when facing tough challenges such as implementing a wiki.

Q&A

  • Why is the module named just wiki ? Because when we tried pip install wiki, it returned "No distributions at all found for wiki", so we had to make up for that! ...oh, and django-wiki was occupied.
  • What markup language will you use? Markdown. The markup renderer is not a pluggable part but has been internalized into core parts. Discussion should go here: #76
  • Why not use django-reversion? It's a great project, but if the wiki has to grow ambitious, someone will have to optimize its behavior, and using a third-party application for something as crucial as the revision system is a no-go in this regard.
  • Any support for multiple wikis? Yes, in an sense you can just imagine that you always have multiple wikis, because you always have hierarchies and full control of their permissions. See this discussion: #63

Docker tl;dr

There is a docker container available here: https://github.com/riotkit-org/docker-django-wiki

Acknowledgements

Original source of inspiration back in 2009 was django-cms, and since then Wagtail has also done a tremendous amount of work to promote Django models as a fundamental structure and enabler for application design.

django-nyt's People

Contributors

ad-m avatar atombrella avatar benjaoming avatar destos avatar duvholt avatar hiasen avatar holoduke avatar jluttine avatar kimond avatar oscarmcm avatar rsalmaso avatar spookylukey avatar timeyyy avatar tonioo avatar valberg avatar werty9021 avatar ztomaz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-nyt's Issues

Use Celery for email notifications and digests

Currently, all kinds of notifications, instant or not, can only be sent by email through a management command.

By adding Celery support, we can have emails sent out when new notifications have been created and send out daily digests etc. through Celery as well...

Database integrity error

I am trying to use a django app that has django-nyt as one of its dependencies. When trying to do the first migration, I get a django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint') in the django_nyt.0001_initial migration. Anyone ever seen this?

Test project on Django 3.0: No module named 'channels'

This has silently failed. Not sure how to handle it. Perhaps the current tests don't even use channels.

#88

py36-django30 run-test: commands[0] | sh -c '! python test-project/manage.py makemigrations --dry-run --exit --noinput'
Traceback (most recent call last):
  File "test-project/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/travis/build/django-wiki/django-nyt/.tox/py36-django30/lib/python3.6/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "/home/travis/build/django-wiki/django-nyt/.tox/py36-django30/lib/python3.6/site-packages/django/core/management/__init__.py", line 377, in execute
    django.setup()
  File "/home/travis/build/django-wiki/django-nyt/.tox/py36-django30/lib/python3.6/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/home/travis/build/django-wiki/django-nyt/.tox/py36-django30/lib/python3.6/site-packages/django/apps/registry.py", line 91, in populate
    app_config = AppConfig.create(entry)
  File "/home/travis/build/django-wiki/django-nyt/.tox/py36-django30/lib/python3.6/site-packages/django/apps/config.py", line 90, in create
    module = import_module(entry)
  File "/home/travis/build/django-wiki/django-nyt/.tox/py36-django30/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'channels'

MiddleWare

Hello. I inserted this code:
CHANNEL_LAYERS = { "default": { "BACKEND": "asgiref.inmemory.ChannelLayer", "ROUTING": "django_nyt.routing.channel_routing", }, }

But after that "request" variable in my middleware has changed. I can't get request.META['PATH_INFO']. What is wrong?

Error on disconnecting Websockets

Latest pre release 1.0b5
Using sockets, when i navigate away from a page.

2017-06-24 10:10:15,607 - ERROR - worker - Error processing message with consumer django_nyt.consumers.ws
_disconnect:
Traceback (most recent call last):
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/channels/worker.py", line 119, i
n run
    consumer(message, **kwargs)
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/channels/sessions.py", line 78,
in inner
    return func(*args, **kwargs)
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/channels/auth.py", line 42, in i
nner
    return func(message, *args, **kwargs)
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django_nyt/consumers.py", line 3
8, in ws_disconnect
    for subscription in models.Subscription.objects.filter(settings__user=message.user):
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django/db/models/manager.py", li
ne 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django/db/models/query.py", line
 784, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django/db/models/query.py", line
 802, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django/db/models/sql/query.py",
line 1261, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django/db/models/sql/query.py",
line 1287, in _add_q
    allow_joins=allow_joins, split_subq=split_subq,
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django/db/models/sql/query.py",
line 1217, in build_filter
    condition = lookup_class(lhs, value)
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django/db/models/lookups.py", li
ne 24, in __init__
    self.rhs = self.get_prep_lookup()
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django/db/models/fields/related_
lookups.py", line 112, in get_prep_lookup
    self.rhs = target_field.get_prep_value(self.rhs)
  File "/home/tim/.virtualenvs/poolbook3.6.1/lib/python3.6/site-packages/django/db/models/fields/__init__
.py", line 966, in get_prep_value
    return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'AnonymousUser'```

Quesiton on content_type and target_object

I'm unsure on how to leverage the content_type and target_object of the notify method
as well as the content_type and object_id of the subscribe method.

What is there purpose and use case?

AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'

Deprecated in 3.2 and removed in 3.9.

Internal Server Error: /wiki/
Traceback (most recent call last):
  File "$VENV/lib/python3.9/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "$VENV/lib/python3.9/site-packages/django/core/handlers/base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "$VENV/lib/python3.9/site-packages/django/core/handlers/base.py", line 143, in _get_response
    response = response.render()
  File "$VENV/lib/python3.9/site-packages/django/template/response.py", line 105, in render
    self.content = self.rendered_content
  File "$VENV/lib/python3.9/site-packages/django/template/response.py", line 83, in rendered_content
    return template.render(context, self._request)
  File "$VENV/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "$VENV/lib/python3.9/site-packages/classytags/core.py", line 151, in render
    return self.render_tag(context, **kwargs)
  File "$VENV/lib/python3.9/site-packages/sekizai/templatetags/sekizai_tags.py", line 87, in render_tag
    rendered_contents = nodelist.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 936, in render
    bit = node.render_annotated(context)
  File "$VENV/lib/python3.9/site-packages/django/template/base.py", line 903, in render_annotated
    return self.render(context)
  File "$VENV/lib/python3.9/site-packages/django/template/library.py", line 214, in render
    _dict = self.func(*resolved_args, **resolved_kwargs)
  File "$VENV/lib/python3.9/site-packages/wiki/templatetags/wiki_tags.py", line 53, in wiki_render
    content = article.get_cached_content(user=context.get("user"))
  File "$VENV/lib/python3.9/site-packages/wiki/models/article.py", line 250, in get_cached_content
    cached_content = self.render(user=user)
  File "$VENV/lib/python3.9/site-packages/wiki/models/article.py", line 211, in render
    article_markdown(
  File "$VENV/lib/python3.9/site-packages/wiki/core/markdown/__init__.py", line 49, in article_markdown
    return md.convert(text)
  File "$VENV/lib/python3.9/site-packages/wiki/core/markdown/__init__.py", line 31, in convert
    html = super().convert(text, *args, **kwargs)
  File "$VENV/lib/python3.9/site-packages/markdown/core.py", line 267, in convert
    newRoot = treeprocessor.run(root)
  File "$VENV/lib/python3.9/site-packages/wiki/core/markdown/mdx/responsivetable.py", line 15, in run
    for table_wrapper in list(root.getiterator("table")):
AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getiterator'

A bug in filtering subscriptions in `Notification.create_notifications`

On line 242 in models.py:
https://github.com/benjaoming/django-nyt/blob/master/django_nyt/models.py#L242

When creating notifications of a specific NotificationType, subscriptions to that NotificationType with an empty object_id will not receive any notifications.

The reasons seems to be that the above-mentioned line is filtering these subscriptions out. Subscription.object_id is a CharField, and thus will have a value of "" (not None) when empty.

Changing the above line to Q(object_id="") resolves the issue.

Duplicate Django-Wiki project management

We need to add support for Django 4.2 and I'm wondering if we should replicate the same configuration that we're already using on Django-Wiki here.

This means (from top of my head):

  • Drop old setup.py and Makefile configuration.
  • Use pyproject.toml
  • Use hatch for environment management

Notification Improvements?

Hey there,

I've been running an older fork of django-nyt with a few tweaks. I have to update my fork to the latest build anyway so I thought I'd check in and see if there's any interest in the specific changes made:

Improved notifymail with a number of changes:

  • Filter notifications only to active users (somewhat mentioned in #136) except handled by notifymail.py
  • notifymail checks Setting.interval to be > -1 before sending notifications. -1 treated as disabling notifications (e-mails) for a user
  • notifymail checks the new field Settings.last_sent and compares it to the user's interval setting before sending mail. This makes cron jobs work properly with set intervals.
  • Support for HTML e-mail notification templates, notifymail tries for the HTML file and falls back to the text file.

Added to the Settings object:

  • Setting had a new field added last_sent to store a datetime when notifications were last sent to the user

Added a new setting and option to existing:

  • Added NYT_SEND_ONLY_LATEST setting to enable e-mail notifications for most recent notification or all unset notifications for the subscription.
  • Notification interval setting of -1 to represent disable e-mail notifications,

Improved the content returned by get_notifications:

  • Adding a target_obj method to Subscription to return the target object, if any.
  • Added type_lbl field to returned Json data in addition to the NotficationType.key that was already included.
  • Added target field to returned Json data, as the string representation of the target object (if any).

@benjaoming would there be any interest in some or all of these things as a PR?

notify, subscribe and unsubscribe: all parameters must be serializable

Instead of boggling the user's mind with weather or not these parameters should be supplied as objects or FK integers etc, let's

  1. force that they are integers or strings (!)
  2. allow both model instances or integers or strings

Because of compatibility with Celery and such async runtimes, we should try to make these functions as dumb as possible. This will also help in cases where the arguments are received from a querystring, and we can skip resolving them before using them.

New release

Is a new minor release manageable, thus allowing the use of USERNAME_FIELD rather than username?

Cheers

Channels 2

It looks like you're still using Channels 1.

Internal Server Error: /wiki/create-root/
Traceback (most recent call last):
  File "$PROJ_VENV/lib/python3.9/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "$PROJ_VENV/lib/python3.9/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "$PROJ_VENV/lib/python3.9/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "$PROJ_VENV/lib/python3.9/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "$PROJ_VENV/lib/python3.9/site-packages/wiki/views/article.py", line 994, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "$PROJ_VENV/lib/python3.9/site-packages/django/views/generic/base.py", line 97, in dispatch
    return handler(request, *args, **kwargs)
  File "$PROJ_VENV0/lib/python3.9/site-packages/django/views/generic/edit.py", line 142, in post
    return self.form_valid(form)
  File "$PROJ_VENV/lib/python3.9/site-packages/wiki/views/article.py", line 997, in form_valid
    models.URLPath.create_root(
  File "$PROJ_VENV/lib/python3.9/site-packages/wiki/models/urlpath.py", line 247, in create_root
    article.add_revision(revision, save=True)
  File "$PROJ_VENV/lib/python3.9/site-packages/wiki/models/article.py", line 171, in add_revision
    new_revision.save()
  File "$PROJ_VENV/lib/python3.9/site-packages/django/db/models/base.py", line 748, in save
    self.save_base(using=using, force_insert=force_insert,
  File "$PROJ_VENV/lib/python3.9/site-packages/django/db/models/base.py", line 796, in save_base
    post_save.send(
  File "$PROJ_VENV/lib/python3.9/site-packages/django/dispatch/dispatcher.py", line 173, in send
    return [
  File "$PROJ_VENV/lib/python3.9/site-packages/django/dispatch/dispatcher.py", line 174, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "$PROJ_VENV/lib/python3.9/site-packages/wiki/decorators.py", line 190, in wrapper
    return signal_handler(*args, **kwargs)
  File "$PROJ_VENV/lib/python3.9/site-packages/wiki/plugins/notifications/models.py", line 61, in post_article_revision_save
    notify(
  File "$PROJ_VENV/lib/python3.9/site-packages/django_nyt/utils.py", line 55, in notify
    from django_nyt import subscribers
  File "$PROJ_VENV/lib/python3.9/site-packages/django_nyt/subscribers.py", line 3, in <module>
    from channels import Group
ImportError: cannot import name 'Group' from 'channels' ($PROJ_VENV/lib/python3.9/site-packages/channels/__init__.py)

async support + async test-project

This is a pretty hefty issue to report.

Firstly, async support should of course be part of a notifications application 💯

There's probably a lot of work to do to get there. I would suggest starting with a copy of test-project, let's call it test-project-async and start from there.

Email hook

I have copied the notifymail command so i can customize emails per event type. Would a PR for this be welcomed? What is the best way to add a customizable function call in django? I thought about parsing a setting string. Is there a nicer way?

NYT_EMAIL_HOOK = module.path.function

Improve RTD build process

Originally posted by @benjaoming in #119 (comment)

It does pass the build, but I believe this is not what we want in the end, this comes from the build log:

Processing /home/docs/checkouts/readthedocs.org/user_builds/django-nyt/checkouts/latest
  Installing build dependencies: started
  Installing build dependencies: finished with status 'done'
  Getting requirements to build wheel: started
  Getting requirements to build wheel: finished with status 'done'
  Preparing metadata (pyproject.toml): started
  Preparing metadata (pyproject.toml): finished with status 'done'
WARNING: django-nyt 1.3 does not provide the extra 'docs'
Collecting django<4.3,>=2.2 (from django-nyt==1.3)
  Downloading Django-4.2.1-py3-none-any.whl (8.0 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.0/8.0 MB 186.8 MB/s eta 0:00:00
Collecting asgiref<4,>=3.6.0 (from django<4.3,>=2.2->django-nyt==1.3)
  Downloading asgiref-3.6.0-py3-none-any.whl (23 kB)
Collecting sqlparse>=0.3.1 (from django<4.3,>=2.2->django-nyt==1.3)
  Downloading sqlparse-0.4.4-py3-none-any.whl (41 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 41.2/41.2 kB 189.4 MB/s eta 0:00:00
Building wheels for collected packages: django-nyt
  Building wheel for django-nyt (pyproject.toml): started
  Building wheel for django-nyt (pyproject.toml): finished with status 'done'
  Created wheel for django-nyt: filename=django_nyt-1.3-py3-none-any.whl size=37182 sha256=aba75df76ec565f0d6a839f5765b41c06b3d4471f5bd5c95718397e11a33050b
  Stored in directory: /tmp/pip-ephem-wheel-cache-sy3lphk2/wheels/d6/35/b9/a2fd0913eb69cebf9dde1d242c2cb14ddfcc8153b48459626d
Successfully built django-nyt
Installing collected packages: sqlparse, asgiref, django, django-nyt
Successfully installed asgiref-3.6.0 django-4.2.1 django-nyt-1.3 sqlparse-0.4.4

As we don't have a docs mode in our pyproject.toml configuration (pip install django-nyt[docs], sorry here)

So then, what I believe is the right process, it to add more install steps with the dependencies listed here

Something like this I believe will do the trick:

version: 2
build:
  os: ubuntu-20.04
  tools:
    python: "3.9"
sphinx:
   configuration: docs/conf.py
python:
   install:
    - method: pip
      path: .
    - method: pip
      path: sphinx
    - method: pip
      path: channels
    - method: pip
      path: sphinx_rtd_theme

cache not being cleared when testing

When testing with django's TestCase, after a test django is successfuly deleting all database entries. However this function is not being called.

@receiver([post_save, post_delete], sender=NotificationType)
def clear_notification_type_cache(*args, **kwargs):
    global _notification_type_cache
    print('CLEARNING NOTIFICATION TYPE CACHE', len(_notification_type_cache))
    _notification_type_cache = {}

Calling this function manually works great to fix my tests, i'm not sure if there is a bug lurking around though...

South requirement should be > 1.0

Older versions of South do not work, because they will attempt to import from the 'migrations' folder instead of 'south_migrations'

Invalid group name

The last in ws_disconnect causes the following exception:

TypeError: Group name must be a valid unicode string containing only alphanumerics, hyphens, or periods.

because settings.NOTIFICATION_CHANNEL is a format string.

I think this line isn't needed and was left there by mistake in 251bfc0

@channel_session_user
def ws_disconnect(message):
    """
    Connected to websocket.disconnect
    """
    logger.debug("Removing connection for user {} (disconnect)".format(message.user))
    for subscription in models.Subscription.objects.filter(settings__user=message.user):
        Group(
            settings.NOTIFICATION_CHANNEL.format(
                notification_key=subscription.notification_type.key
            )
        ).discard(message.reply_channel)
    Group(settings.NOTIFICATION_CHANNEL).discard(message.reply_channel)

Add a filter_include option for the notify function?

It's not possible to frame all logic within filter_exclude and therefore, we should probably introduce a companion.

These filters are quite important for systems that need extra guarantees. There are cases where the set of notified users can fluctuate and inaccuracies can produce small leaks of information to the wrong users. This could be for instance if the consent is stored in another database table that needs to be queried.

Another way to use these filters is to have a dynamic set of subscribers. I.e. you can express "anyone who is currently a superuser" through filter_include={"settings__user__is_superuser": True}

def notify(
message: str,
key: str,
target_object: Any = None,
url: str = None,
filter_exclude: dict = None,
recipient_users: list = None,
) -> List[models.Notification]:
"""
Notify subscribing users of a new event. Key can be any kind of string,
just make sure to reuse it where applicable.
Here is the most basic example: Everyone subscribing to the `"new_comments"` key
are sent a notification with the message "New comment posted"::
notify("New comment posted", "new_comments")
Here is an example that will create a Notification object for everyone who
has a subscription for the key `"comment/response"` and the model instance `comment_instance`.
The idea would be that the poster of `comment_instance` will receive notifications when someone responds to that comment.
.. code-block:: python
notify(
"there was a response to your comment",
"comment/response",
target_object=comment_instance,
url=reverse('comments:view', args=(comment_instance.id,))
)
:param message: A string containing the message that should be sent to all subscribed users.
:param key: A key object which is matched to ``NotificationType.key``.
Users with a Subscription for that NotificationType will have a Notification object created.
:param url: A URL pointing to your notification.
If the URL is pointing to your Django project's unique website,
then add an ``/absolute/url``. However, if the URL should take the user to a different website,
use a full HTTP scheme, i.e. ``https://example.org/url/``.
:param recipient_users: A possible iterable of users that should be notified
instead of notifying all subscribers of the event.
Notice that users still have to be actually subscribed
to the event key!
:param target_object: Any Django model instance that this notification
relates to. Uses Django content types.
Subscriptions with a matching content_type and object_id will be notified.
:param filter_exclude: Keyword arguments passed to filter out Subscriptions.
Will be handed to ``Subscription.objects.exclude(**filter_exclude)``.
"""

Python 3 compatibility

Stuff like #1 and this error needs to be fixed:

Traceback (most recent call last):
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/core/management/base.py", line 222, in run_from_argv
self.execute(*args, **options.__dict__)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/core/management/commands/test.py", line 72, in execute
super(Command, self).execute(*args, **options)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/core/management/base.py", line 255, in execute
output = self.handle(*args, **options)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/south/management/commands/test.py", line 8, in handle
super(Command, self).handle(*args, **kwargs)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/core/management/commands/test.py", line 89, in handle
failures = test_runner.run_tests(test_labels)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/test/simple.py", line 369, in run_tests
suite = self.build_suite(test_labels, extra_tests)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/test/simple.py", line 256, in build_suite
app = get_app(label)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/db/models/loading.py", line 148, in get_app
self._populate()
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/db/models/loading.py", line 72, in _populate
self.load_app(app_name, True)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/db/models/loading.py", line 96, in load_app
models = import_module('.models', app_name)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages/django_nyt/models.py", line 63
verbose_name=_(u"user"),
^
SyntaxError: invalid syntax

Keeping settings.AUTH_USER_MODEL into account

Hey,
I'm having troubles running the south migrations because I'm not using the standard User model.

This is what I get:

CommandError: One or more models did not validate:
django_nyt.notification: 'user' defines a relation with the model 'auth.User', which has been swapped out. Update the relation to point at settings.AUTH_USER_MODEL.

It looks to me this is related or similar to this issue:
django-wiki/django-wiki#145
And this was the fix:
django-wiki/django-wiki@e506c09

Could you have a look please?

Kind regards,

Jan

Support for Django 4.1

Hi, is there a reason on why the Django version is locked to <4.1? I just checked the tests and as well the tests app and seems that everything works fine.

❯ python -V
Python 3.10.8

❯ pip freeze
asgiref==3.5.2
Django==4.1.3
-e git+ssh://[email protected]/oscarmcm/django-nyt.git@28a5afbc10b2a31c6be8a303524905f19077fdf2#egg=django_nyt
sqlparse==0.4.3

❯ ./runtests.py
Found 4 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
Starting django_nyt e-mail dispatcher
Sending to: [email protected]
Sending to: [email protected]
Starting django_nyt e-mail dispatcher
Starting django_nyt e-mail dispatcher
Daemon mode enabled, forking
PID: 98595
Starting send loop at 2022-11-10 14:25:47.268106
....
----------------------------------------------------------------------
Ran 4 tests in 1.226s

OK
Destroying test database for alias 'default'...

I'm happy to provide a patch if there's any in order to add support for Django 4.1, those are the changes I added:

diff --git a/runtests.py b/runtests.py
index e265075..47d70d6 100755
--- a/runtests.py
+++ b/runtests.py
@@ -57,6 +57,7 @@ settings.configure(
         'django.contrib.auth.middleware.AuthenticationMiddleware',
         'django.contrib.messages.middleware.MessageMiddleware',
     ],
+    DEFAULT_AUTO_FIELD='django.db.models.AutoField',
 )
 
 
diff --git a/setup.py b/setup.py
index 0a410be..593c709 100644
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,7 @@ setup(
     keywords=["django", "notification" "alerts"],
     packages=find_packages(),
     zip_safe=False,
-    install_requires=["django>=2.2,<4.1"],
+    install_requires=["django>=2.2,<4.2"],
     classifiers=[
         'Development Status :: 5 - Production/Stable',
         'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
diff --git a/test-project/testproject/settings/__init__.py b/test-project/testproject/settings/__init__.py
index d33f83e..9d45293 100644
--- a/test-project/testproject/settings/__init__.py
+++ b/test-project/testproject/settings/__init__.py
@@ -37,8 +37,7 @@ MEDIA_URL = '/media/'
 
 STATIC_ROOT = os_path.join(PROJECT_PATH, 'static')
 STATIC_URL = '/static/'
-STATICFILES_DIRS = (
-)
+STATICFILES_DIRS = ()
 STATICFILES_FINDERS = (
     'django.contrib.staticfiles.finders.FileSystemFinder',
     'django.contrib.staticfiles.finders.AppDirectoriesFinder',
@@ -154,3 +153,4 @@ if _enable_channels:
 
 
 NYT_ENABLE_ADMIN = True
+DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

Depends on channels package

I got this message:

/venv/project_name/lib/python3.4/site-packages/celery/loaders/base.py", line 252, in autodiscover_tasks
    related_name) if mod)
  File "/opt/venv/project_name/lib/python3.4/site-packages/celery/loaders/base.py", line 273, in autodiscover_tasks
    return [find_related_module(pkg, related_name) for pkg in packages]
  File "/opt/venv/project_name/lib/python3.4/site-packages/celery/loaders/base.py", line 273, in <listcomp>
    return [find_related_module(pkg, related_name) for pkg in packages]
  File "/opt/venv/project_name/lib/python3.4/site-packages/celery/loaders/base.py", line 299, in find_related_module
    return importlib.import_module('{0}.{1}'.format(package, related_name))
  File "/opt/venv/project_name/lib/python3.4/importlib/__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
  File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
  File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1129, in _exec
  File "<frozen importlib._bootstrap>", line 1471, in exec_module
  File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
  File "/opt/venv/project_name/lib/python3.4/site-packages/django_nyt/tasks.py", line 7, in <module>
    from channels import Group
ImportError: No module named 'channels'

After install channels everything seems to work.

Notifymail command craches

I had this error when trying to run the command notifymail on my local windows 7 machine under python 3.5 and pdb
`
Entering send-loop, CTRL+C to exit
Traceback (most recent call last):
File "d:\Python35\Lib\pdb.py", line 1661, in main
pdb.runscript(mainpyfile)
File "d:\Python35\Lib\pdb.py", line 1542, in runscript
self.run(statement)
File "d:\Python35\Lib\bdb.py", line 431, in run
exec(cmd, globals, locals)
File "", line 1, in
File "d:\l2e\vip\manage.py", line 2, in
import os
File "D:\l2e\env\lib\site-packages\django\core\management_init
.py", line 363, in execute_from_command_line
utility.execute()
File "D:\l2e\env\lib\site-packages\django\core\management_init
.py", line 355, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "D:\l2e\env\lib\site-packages\django\core\management\base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "D:\l2e\env\lib\site-packages\django\core\management\base.py", line 330, in execute
output = self.handle(*args, **options)
File "D:\l2e\env\lib\site-packages\django_nyt\management\commands\notifymail.py", line 136, in handle
self.send_loop(connection, int(options['sleep_time']))
KeyError: 'sleep_time'
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program

d:\l2e\env\lib\site-packages\django_nyt\management\commands\notifymail.py(136)handle()
-> self.send_loop(connection, int(options['sleep_time']))
(Pdb) self
<django_nyt.management.commands.notifymail.Command object at 0x00000000045E21D0>
(Pdb) connection
<django.core.mail.backends.smtp.EmailBackend object at 0x00000000062BF0F0>
(Pdb) options
{'no_color': False, 'traceback': False, 'pythonpath': None, 'verbosity': 1, 'no_sys_exit': False, 'cron': False, 'settings': None, 'daemon': False}
(Pdb)

`
Could you see please?

Web-push notifications support.

It would be nice to add support of web-push notifications. Many users prefer push notifications to email notifications.
Users should have an option to receive via push or email or both.

What do you think?

AttributeError: type object 'SessionAuthentication' has no attribute 'get_user'

I'm getting this error when websocket is disconnected:

 ERROR - worker - Error processing message with consumer django_nyt.consumers.ws_disconnect:
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\channels\worker.py", line 119, in run
    consumer(message, **kwargs)
  File "C:\Python27\lib\site-packages\channels\sessions.py", line 78, in inner
    return func(*args, **kwargs)
  File "C:\Python27\lib\site-packages\channels\auth.py", line 48, in inner
    message.user = auth.get_user(fake_request)
 AttributeError: type object 'SessionAuthentication' has no attribute 'get_user'

Any Help please

Group.send not working in realtime in django-nyt

I changed the channels backend to redis server and when trying to poll a group.send from python it doesn't work in real time only works on page refresh and on socket.send from javascript any help please to let notifications show in realtime for users

Testable settings pattern

As I've just discovered this, I wanna make sure to note it somewhere:

The pattern that we have for settings in django-nyt (and django-wiki) isn't perfect because it doesn't support the @override_settings decorator used in testing.

There are some suggestions in this Stack Overflow post: https://stackoverflow.com/questions/8428556/django-default-settings-convention-for-pluggable-app

I haven't quite understood which is the perfect pattern yet. One of the reasons to have a local settings module would be to easily gather an overview and at the same time document settings. Let's see if we can keep this.

TypeError: int() argument must be a string or a number, not 'AnonymousUser'

Hi @benjaoming I'm working on the test project from the link you gave to me I'm getting this error in this line "C:\Python27\lib\site-packages\django_nyt\consumers.py", line 23, in ws_connect
for subscription in models.Subscription.objects.filter(settings__user=message.user):
Does this effect the Group.send and doesn't make connection to websocket work properly ? can you help me in this please

_notification_type_cache on NotificationType seems to cause errors with tests

In the tests for my application it seems that NotificationType is cleared after running each TestCase. This leads _notification_type_cache to no longer be valid. My current workaround is to manually create any needed NotificationType objects at the start of each test. Given the nature of how _notification_type_cache should work, I'm not sure if there's anything to do about this beyond mentioning it in documentation. Thoughts?

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.