# How User Notification Preferences Are Stored and Managed in Yappuccino

> Learn how Yappuccino stores and manages user notification preferences using boolean fields on the Profile model and a dedicated NotificationSettingsForm.

- Repository: [Ja'farbek Yusupov/yappuccino](https://github.com/jafarbekyusupov/yappuccino)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Yappuccino stores user notification preferences as boolean fields on the one-to-one Profile model and manages updates through a dedicated NotificationSettingsForm handled in the settings view.**

The open-source Yappuccino application (available at `jafarbekyusupov/yappuccino`) implements a straightforward, model-driven approach to managing email notification preferences. Instead of creating separate tables or complex schemas, the system stores these settings directly on the user’s Profile record, making retrieval and updates efficient and atomic. This design ensures that notification settings are always available via `request.user.profile` without requiring additional database joins.

## Database Schema: The Profile Model

At the data layer, Yappuccino defines four **boolean fields** directly on the Profile model in [`users/models.py`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/models.py) (lines 30-36). These fields control specific email notification channels:

- `email_comments` – alerts for new comments on the user’s posts
- `email_replies` – alerts for replies to the user’s comments  
- `email_reposts` – alerts when someone reposts the user’s content
- `email_newsletter` – subscription to the weekly newsletter

Because the Profile model maintains a one-to-one relationship with the User model, these preferences are immediately accessible whenever the user object is loaded. The fields default to `True` or `False` based on the model definition, and changes are persisted through standard Django ORM save operations.

## Form Handling with NotificationSettingsForm

To expose these fields in the UI, Yappuccino uses a **ModelForm** called `NotificationSettingsForm` defined in [`users/forms.py`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/forms.py) (lines 48-57). This form maps the four boolean model fields to HTML checkboxes, handling both validation and sanitization automatically.

The form accepts a `Profile` instance as its `instance` parameter, allowing it to pre-populate checkbox states based on current database values. When `form.save()` is called, Django writes the cleaned boolean values directly back to the Profile record.

## View Logic and Preference Updates

The actual update flow occurs in the `settings` view located in [`users/views.py`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/views.py) (lines 52-59). The view detects notification-specific submissions by checking for the `notification_submit` key in the POST data:

```python
elif 'notification_submit' in request.POST:
    form = NotificationSettingsForm(request.POST, instance=request.user.profile)
    if form.is_valid():
        form.save()
        # Redirect or render success message

```

This pattern isolates notification updates from other settings forms on the same page. The view binds the submitted POST data to the current user’s profile instance, validates the input against the form’s field definitions, and persists changes to the database atomically.

## Template Rendering in the Settings Page

The frontend implementation lives in [`users/templates/users/settings.html`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/templates/users/settings.html) (lines 85-124). The template renders the `NotificationSettingsForm` as a group of checkboxes, each bound to the respective model field:

```html
<form method="POST">
  {% csrf_token %}
  <input type="checkbox" name="email_comments"
         {% if user.profile.email_comments %}checked{% endif %}>
  <label>New comments on your posts</label>

  <input type="checkbox" name="email_replies"
         {% if user.profile.email_replies %}checked{% endif %}>
  <label>Replies to your comments</label>

  <input type="checkbox" name="email_reposts"
         {% if user.profile.email_reposts %}checked{% endif %}>
  <label>Someone reposts your content</label>

  <input type="checkbox" name="email_newsletter"
         {% if user.profile.email_newsletter %}checked{% endif %}>
  <label>Weekly newsletter</label>

  <button type="submit" name="notification_submit">Save Notification Settings</button>
</form>

```

The template checks each boolean field on `user.profile` to determine the initial checked state, ensuring the UI reflects the stored preferences.

## Working with Notification Preferences Programmatically

Developers can interact with these preferences outside the standard form flow using the Django ORM.

**Reading current preferences:**

```python
profile = request.user.profile
prefs = {
    "comments":   profile.email_comments,
    "replies":   profile.email_replies,
    "reposts":   profile.email_reposts,
    "newsletter": profile.email_newsletter,
}

```

**Updating preferences manually:**

```python
profile = request.user.profile
profile.email_comments = True          # enable comment notifications

profile.email_newsletter = False       # disable newsletter

profile.save()                        # persist changes

```

**Using the built-in form programmatically:**

```python
from users.forms import NotificationSettingsForm

def update_notification(request):
    if request.method == "POST":
        form = NotificationSettingsForm(
            request.POST,
            instance=request.user.profile,
        )
        if form.is_valid():
            form.save()               # writes all four booleans to DB

```

## Summary

- **Storage:** Four boolean fields (`email_comments`, `email_replies`, `email_reposts`, `email_newsletter`) on the Profile model in [`users/models.py`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/models.py) store preferences directly in the database.
- **Validation:** The `NotificationSettingsForm` in [`users/forms.py`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/forms.py) handles input sanitization and maps HTML checkboxes to model fields.
- **Processing:** The settings view in [`users/views.py`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/views.py) detects `notification_submit` POST requests, validates the form, and saves changes.
- **Presentation:** The settings template in [`users/templates/users/settings.html`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/templates/users/settings.html) renders the form with current values pre-selected.
- **Access:** Preferences are available anywhere via `request.user.profile` without additional queries.

## Frequently Asked Questions

### Where are notification preferences stored in Yappuccino?

Notification preferences are stored as boolean columns on the Profile model in [`users/models.py`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/models.py). The specific fields are `email_comments`, `email_replies`, `email_reposts`, and `email_newsletter`, which are defined at lines 30-36. Because Profile has a one-to-one relationship with User, these settings are accessible through `request.user.profile` in any view or template.

### What notification types does Yappuccino support?

According to the source code in [`users/models.py`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/models.py), Yappuccino supports four distinct email notification types: new comments on the user’s posts, replies to the user’s comments, reposts of the user’s content, and a weekly newsletter. Each type corresponds to a separate boolean field on the Profile model, allowing users to toggle channels independently.

### How does the settings view handle notification form submissions?

The settings view in [`users/views.py`](https://github.com/jafarbekyusupov/yappuccino/blob/main/users/views.py) (lines 52-59) checks for the presence of `notification_submit` in the POST data to identify notification-specific updates. It then instantiates `NotificationSettingsForm` with the submitted data and the current user’s profile instance, validates the input, and calls `form.save()` to persist the boolean values to the database.

### Can notification preferences be updated outside the web interface?

Yes. Since the preferences are standard Django model fields, they can be updated programmatically through the ORM by importing the Profile model, setting the boolean attributes (e.g., `profile.email_comments = False`), and calling `profile.save()`. Developers can also use `NotificationSettingsForm` programmatically in custom views or management commands to validate and save changes.