Create a News-Curator and News Subscription App using Django
Tags: python, django, tutorial, webdev
Published: 2020-08-26 17:31:50

I have recently released a django package named [django-newsfeed](https://github.com/saadmk11/django-newsfeed).
This makes it really easy to build a news curator and newsletter subscription website.

Today I'm going to show you how to easily create a news curator website or
add a newsfeed subscription service to your existing website. 

### Requirements:

+ Django >= 2.2
+ django-newsfeed
+ celery
+ celery-beat
+ redis

### Setup Project:

Lets get started

1. Create Virtualenv and install requirements:

```shell
$ mkvirtualenv example-newsfeed     # you can use virtualenv instead of virtualenvwrapper
$ mkdir django-newsfeed
$ cd django-newsfeed/

$ pip install celery Django django-celery-beat django-newsfeed redis
```
** You need to have redis installed in your system. Here is a [guide](https://redis.io/topics/quickstart)

2. Setup django:

```shell
$ django-admin.py startproject example_newsfeed .    # dot (.) is added to create project on current directory
$ python manage.py migrate
```

3. Now add ``newsfeed`` and ``celery-beat`` to installed apps.

```python
INSTALLED_APPS = [
    ...
    'django_celery_beat',
    'newsfeed',
]
```

4. Add ``django-newsfeed`` urls to project ``urls.py``.

```python
urlpatterns = [
    ...
    path('newsfeed/', include('newsfeed.urls', namespace='newsfeed')),
    ...
]
```

5. Create superuser and Run Django Development Server

```shell
$ python manage.py createsuperuser
$ python manage.py runserver       # http://127.0.0.1:8000/
```

6. Go to Django Admin Page, login and create Posts, Issues and Newsletters.

Now You can navigate to:

* **latest_issue:** ``newsfeed/``
* **issue_list:** ``newsfeed/issues/``
* **issue_detail:** ``newsfeed/issues/<slug:issue_number>/``
* **newsletter_subscribe:** ``newsfeed/subscribe/``
* **newsletter_subscription_confirm:** ``newsfeed/subscribe/confirm/<uuid:token>/``
* **newsletter_unsubscribe:** ``newsfeed/unsubscribe/``

7. Override Templates to your liking. To learn more about it [click here](https://github.com/saadmk11/django-newsfeed/blob/master/README.rst#usage)
Here is the [code for this tutorial](https://github.com/saadmk11/test-django-newsfeed).
You can see the overridden templates here. It uses bootstrap to style the templates.

### Setup Sending Newsletters:

Now that the project is set up we can create celery task to send newsletters.

**Configure Celery**

1. Setup [celery from here](https://docs.celeryproject.org/en/stable/django/first-steps-with-django.html).

2. Add celery settings for redis to ``settings.py``

```python
# Celery Settings
CELERY_BROKER_URL = 'redis://localhost:6379'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = TIME_ZONE
```

3. Add Email settings to ``settings.py``

```python
# Email Settings
EMAIL_HOST = 'test_host'
EMAIL_HOST_USER = 'test_user'
EMAIL_HOST_PASSWORD = 'test_password'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
```

** Change this for production server [django reference](https://docs.djangoproject.com/en/2.2/ref/settings/#email-host)

1. Create a django app named ``core``

```shell
$ python manage.py startapp core
```

2. Now add ``core`` to installed apps.

```python
INSTALLED_APPS = [
    ...
    'core',
]
```

6. Create ``tasks.py`` file in the ``core`` app directory. Paste this code in the file.

```python
from celery.decorators import task

from newsfeed.models import Newsletter
from newsfeed.utils.send_newsletters import send_email_newsletter


@task(name="send_email_newsletter_task")
def send_email_newsletter_task(newsletters_ids=None, respect_schedule=True):
    newsletters = None

    if newsletters_ids:
        newsletters = Newsletter.objects.filter(
            id__in=newsletters_ids
        )
    send_email_newsletter(
        newsletters=newsletters,
        respect_schedule=respect_schedule
    )
```

** This will enable you to call the ``EmailNewsletterSender`` provided by ``django-newsletter``
in a celery task.

Now you can send newsletters from the django admin page.

7. Add this code to the ``celery.py`` file on your project directory.
(``celery.py`` file should be created following the step 3)

```python
app.conf.beat_schedule = {
    'send_email_newsletter': {
        'task': 'send_email_newsletter_task',
        # http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html
        # run this task every hour
        'schedule': crontab(minute=0, hour='*'),
    }
}
```
** This will schedule sending newsletters every hour.
Now you can send scheduled newsletters to all the subscribers autometically using this scheduled task.

8. Add this code to the ``admin.py`` file on the ``core`` app directory.

```python
from django.contrib import admin, messages

from newsfeed.admin import NewsletterAdmin
from newsfeed.models import Newsletter

from .tasks import send_email_newsletter_task

admin.site.unregister(Newsletter)


@admin.register(Newsletter)
class NewsletterAdmin(NewsletterAdmin):

    def send_newsletters(self, request, queryset):
        newsletter_ids = list(queryset.values_list('id', flat=True))

        send_email_newsletter_task.delay(
            newsletters_ids=newsletter_ids,
            respect_schedule=False
        )
        messages.add_message(
            request,
            messages.SUCCESS,
            'Sending selected newsletters(s) to the subscribers',
        )
```

** This will override the admin action for sending newsletters to use celery task.

#### Source Code for this tutorial here: https://github.com/saadmk11/test-django-newsfeed

#### Video Demo:
[![A Example News Curator and News Subscription website using django package dnajgo-newsfeed](https://i.imgur.com/vupGREz.png)](https://youtu.be/xTLwQHOrY00 "A Example News Curator and News Subscription website using django package dnajgo-newsfeed")


#### More:

You can learn more about all the configuration for ``django-newsfeed`` on github.

Checkout the package from here: [django-newsfeed](https://github.com/saadmk11/django-newsfeed)


#### Conclusion:

If you use this package please feel free to provide some feedback on [twitter](https://twitter.com/saad_mk11)
or on the comment section.
If you have any suggestion or want to contribute to this package
please create an [issue](https://github.com/saadmk11/django-newsfeed/issues)
and read the [contribution guide](https://github.com/saadmk11/django-newsfeed/blob/master/CONTRIBUTING.rst).

Feedback and Contribution is always welcome.