From 251c3a51f8a5d04ba56b319edc8107ca11103b15 Mon Sep 17 00:00:00 2001 From: Tze Hng Loke Date: Tue, 28 Nov 2023 21:52:41 -0500 Subject: [PATCH] Added model for preferences, tagged to to user mode, added view to fetch preferences and display them according. Added model form to allow users to customize their own preferences dynamically --- accounts/migrations/0003_user_preferences.py | 25 +++++++++++ accounts/models.py | 8 +++- core/settings.py | 1 + core/urls.py | 4 ++ preferences/forms.py | 14 ++++++ preferences/models.py | 15 +++++++ preferences/templates/preferences.html | 45 ++++++++++++++++++++ preferences/urls.py | 10 +++++ preferences/views.py | 43 +++++++++++++++++++ templates/navigation.html | 6 +++ 10 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 accounts/migrations/0003_user_preferences.py create mode 100644 preferences/forms.py create mode 100644 preferences/models.py create mode 100644 preferences/templates/preferences.html create mode 100644 preferences/urls.py create mode 100644 preferences/views.py diff --git a/accounts/migrations/0003_user_preferences.py b/accounts/migrations/0003_user_preferences.py new file mode 100644 index 0000000..505a3a2 --- /dev/null +++ b/accounts/migrations/0003_user_preferences.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.7 on 2023-11-29 02:51 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("preferences", "__first__"), + ("accounts", "0002_alter_user_table"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="preferences", + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="preferences.preferences", + ), + ), + ] diff --git a/accounts/models.py b/accounts/models.py index b756e6d..6f616bf 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -1,6 +1,7 @@ from django.contrib.auth.models import AbstractUser from django.utils.translation import gettext_lazy as _ - +from django.db import models +from preferences.models import Preferences class User(AbstractUser): class Meta: @@ -10,3 +11,8 @@ class Meta: def __str__(self): return self.username + + #store user preferences in a one to one mapping + preferences = models.OneToOneField(Preferences, on_delete=models.CASCADE, blank=True, null=True) + + diff --git a/core/settings.py b/core/settings.py index 894d1d4..62dd1e7 100644 --- a/core/settings.py +++ b/core/settings.py @@ -49,6 +49,7 @@ "homes", "residents", "work", + "preferences" ] CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5" diff --git a/core/urls.py b/core/urls.py index 7324fd3..8695127 100644 --- a/core/urls.py +++ b/core/urls.py @@ -47,5 +47,9 @@ "work/", include("work.urls"), ), + path( + "preferences/", + include("preferences.urls"), + ), path("", TemplateView.as_view(template_name="home.html"), name="home"), ] diff --git a/preferences/forms.py b/preferences/forms.py new file mode 100644 index 0000000..d3be361 --- /dev/null +++ b/preferences/forms.py @@ -0,0 +1,14 @@ +from django import forms +from django.forms import ModelForm +from preferences.models import Preferences + +class PreferencesForm (ModelForm): + class Meta: + model = Preferences + fields = ('Language', 'Mode') + widgets = { + 'Language': forms.Select(attrs={'class': 'form-control'}), + 'Mode': forms.Select(attrs={'class': 'form-control'}), + } + labels = {'Language': 'Preferred Language', + 'Mode': 'Preferred Mode'} \ No newline at end of file diff --git a/preferences/models.py b/preferences/models.py new file mode 100644 index 0000000..49d5c6f --- /dev/null +++ b/preferences/models.py @@ -0,0 +1,15 @@ +from django.db import models + +def generate_lists (L): + result = [] + for elem in L: + result.append ((elem,elem)) + return result + +languages = ['English (en)', 'Suomi (fi)'] +viewModes = ['dark', 'light'] + +# for user preferences +class Preferences (models.Model): + Language = models.CharField (max_length = 30, blank=True, choices = generate_lists (languages)) + Mode = models.CharField (max_length = 30, blank=True, choices = generate_lists (viewModes)) \ No newline at end of file diff --git a/preferences/templates/preferences.html b/preferences/templates/preferences.html new file mode 100644 index 0000000..80866a1 --- /dev/null +++ b/preferences/templates/preferences.html @@ -0,0 +1,45 @@ +{% extends 'base.html' %} + +{% load i18n %} +{% load crispy_forms_tags %} + +{% block content %} +
+
+
+

Set Preferences

+
+
+
+ + {{form|crispy}} +
+ {% csrf_token %} + +
+
+
+
+
+
+ +
+
+
+

Your Current Preferences

+
+ {% if not request.user.preferences %} +

No current preferences. Set some!

+ {% else %} + {% for name, value in fields %} + {% if name != "id" %} +

{{ name }} : {{ value }}

+ {% endif %} + {% endfor %} + {% endif %} +
+
+
+
+ +{% endblock content %} diff --git a/preferences/urls.py b/preferences/urls.py new file mode 100644 index 0000000..9056a19 --- /dev/null +++ b/preferences/urls.py @@ -0,0 +1,10 @@ +from django.urls import path +from .views import setPreferences + +urlpatterns = [ + path( + "", + setPreferences, + name="preferences-view", + ), +] diff --git a/preferences/views.py b/preferences/views.py new file mode 100644 index 0000000..3e9977c --- /dev/null +++ b/preferences/views.py @@ -0,0 +1,43 @@ +from django.shortcuts import render, redirect, reverse +from django.contrib.auth.decorators import login_required +from preferences.forms import PreferencesForm +from preferences.models import Preferences +from django.core import serializers + +# this function creates a blank preference model form on GET request +# and returns a context with the form and the fields from the preference +# object tagged to the current user +# on non GET request we update the database to save the new preferences +@login_required +def setPreferences (request): + context = {} + if request.method == 'GET': + context['form'] = PreferencesForm () + # null check for preferences field + if request.user.preferences: + fields = [(field.name, field.value_to_string(request.user.preferences)) for field in Preferences._meta.fields] + context['fields'] = fields + return render(request, '../templates/preferences.html', context) + + # for any other request type that is not GET + form = PreferencesForm(request.POST) + context['form'] = form + + if not form.is_valid(): + return render(request, '../templates/preferences.html', context) + + preferences = Preferences( + Language = form.cleaned_data['Language'], + Mode = form.cleaned_data['Mode'], + ) + + preferences.save () + + request.user.preferences = preferences + request.user.save () + + # extract the fields to be displayed from the preferences + fields = [(field.name, field.value_to_string(request.user.preferences)) for field in Preferences._meta.fields] + context['fields'] = fields + + return render(request, '../templates/preferences.html', context) \ No newline at end of file diff --git a/templates/navigation.html b/templates/navigation.html index 11befa7..20d7280 100644 --- a/templates/navigation.html +++ b/templates/navigation.html @@ -40,6 +40,12 @@ {% translate "Residents" %} + +