diff --git a/cookbook/forms.py b/cookbook/forms.py index 2cea2d07..7179c2c4 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -36,7 +36,10 @@ class UserPreferenceForm(forms.ModelForm): prefix = 'preference' def __init__(self, *args, **kwargs): - space = kwargs.pop('space') + if x := kwargs.get('instance', None): + space = x.space + else: + space = kwargs.pop('space') super().__init__(*args, **kwargs) self.fields['plan_share'].queryset = User.objects.filter(userpreference__space=space).all() @@ -483,7 +486,7 @@ class ShoppingPreferenceForm(forms.ModelForm): fields = ( 'shopping_share', 'shopping_auto_sync', 'mealplan_autoadd_shopping', 'mealplan_autoexclude_onhand', - 'mealplan_autoinclude_related', 'default_delay', 'filter_to_supermarket', 'shopping_recent_days' + 'mealplan_autoinclude_related', 'default_delay', 'filter_to_supermarket', 'shopping_recent_days', 'csv_delim' ) help_texts = { @@ -498,6 +501,7 @@ class ShoppingPreferenceForm(forms.ModelForm): 'default_delay': _('Default number of hours to delay a shopping list entry.'), 'filter_to_supermarket': _('Filter shopping list to only include supermarket categories.'), 'shopping_recent_days': _('Days of recent shopping list entries to display.'), + 'csv_delim': _('Delimiter to use for CSV exports.'), } labels = { 'shopping_share': _('Share Shopping List'), @@ -507,7 +511,8 @@ class ShoppingPreferenceForm(forms.ModelForm): 'mealplan_autoinclude_related': _('Include Related'), 'default_delay': _('Default Delay Hours'), 'filter_to_supermarket': _('Filter to Supermarket'), - 'shopping_recent_days': _('Recent Days') + 'shopping_recent_days': _('Recent Days'), + 'csv_delim': _('CSV Delimiter'), } widgets = { diff --git a/cookbook/migrations/0162_userpreference_csv_delim.py b/cookbook/migrations/0162_userpreference_csv_delim.py new file mode 100644 index 00000000..e296ba95 --- /dev/null +++ b/cookbook/migrations/0162_userpreference_csv_delim.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2021-11-30 22:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0161_alter_shoppinglistentry_food'), + ] + + operations = [ + migrations.AddField( + model_name='userpreference', + name='csv_delim', + field=models.CharField(default=',', max_length=2), + ), + ] diff --git a/cookbook/models.py b/cookbook/models.py index 57b5d878..77affc5d 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -333,6 +333,7 @@ class UserPreference(models.Model, PermissionModelMixin): filter_to_supermarket = models.BooleanField(default=False) default_delay = models.DecimalField(default=4, max_digits=8, decimal_places=4) shopping_recent_days = models.PositiveIntegerField(default=7) + csv_delim = models.CharField(max_length=2, default=",") created_at = models.DateTimeField(auto_now_add=True) space = models.ForeignKey(Space, on_delete=models.CASCADE, null=True) diff --git a/cookbook/serializer.py b/cookbook/serializer.py index e5a4b9cc..3401d217 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -155,7 +155,7 @@ class FoodInheritFieldSerializer(UniqueFieldsMixin): class UserPreferenceSerializer(serializers.ModelSerializer): # food_inherit_default = FoodInheritFieldSerializer(source='space.food_inherit', read_only=True) food_ignore_default = serializers.SerializerMethodField('get_ignore_default') - plan_share = UserNameSerializer(many=True, allow_null=True, required=False) + plan_share = UserNameSerializer(many=True, allow_null=True, required=False, read_only=True) def get_ignore_default(self, obj): return FoodInheritFieldSerializer(Food.inherit_fields.difference(obj.space.food_inherit.all()), many=True).data @@ -165,14 +165,19 @@ class UserPreferenceSerializer(serializers.ModelSerializer): raise NotFound() return super().create(validated_data) + def update(self, instance, validated_data): + # don't allow writing to FoodInheritField via API + return super().update(instance, validated_data) + class Meta: model = UserPreference fields = ( 'user', 'theme', 'nav_color', 'default_unit', 'default_page', 'use_kj', 'search_style', 'show_recent', 'plan_share', 'ingredient_decimals', 'comments', 'shopping_auto_sync', 'mealplan_autoadd_shopping', 'food_ignore_default', 'default_delay', - 'mealplan_autoinclude_related', 'mealplan_autoexclude_onhand', 'shopping_share', 'shopping_recent_days' + 'mealplan_autoinclude_related', 'mealplan_autoexclude_onhand', 'shopping_share', 'shopping_recent_days', 'csv_delim' ) + read_only_fields = ['user'] class UserFileSerializer(serializers.ModelSerializer): diff --git a/vue/src/apps/ShoppingListView/ShoppingListView.vue b/vue/src/apps/ShoppingListView/ShoppingListView.vue index a265dcd5..f71063e8 100644 --- a/vue/src/apps/ShoppingListView/ShoppingListView.vue +++ b/vue/src/apps/ShoppingListView/ShoppingListView.vue @@ -10,10 +10,11 @@