sandwitches 1.2.0__py3-none-any.whl → 1.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sandwitches/api.py CHANGED
@@ -37,6 +37,16 @@ class Error(Schema):
37
37
  message: str
38
38
 
39
39
 
40
+ class RatingResponseSchema(Schema):
41
+ average: float
42
+ count: int
43
+
44
+
45
+ @api.get("ping")
46
+ def ping(request):
47
+ return {"status": "ok", "message": "pong"}
48
+
49
+
40
50
  @api.get("v1/me", response={200: UserSchema, 403: Error})
41
51
  def me(request):
42
52
  if not request.user.is_authenticated:
@@ -71,6 +81,15 @@ def get_recipe_of_the_day(request):
71
81
  return recipe
72
82
 
73
83
 
84
+ @api.get("v1/recipes/{recipe_id}/rating", response=RatingResponseSchema)
85
+ def get_recipe_rating(request, recipe_id: int):
86
+ recipe = get_object_or_404(Recipe, id=recipe_id)
87
+ return {
88
+ "average": recipe.average_rating(),
89
+ "count": recipe.rating_count(),
90
+ }
91
+
92
+
74
93
  @api.get("v1/tags", response=list[TagSchema])
75
94
  def get_tags(request):
76
95
  return Tag.objects.all() # ty:ignore[unresolved-attribute]
sandwitches/forms.py CHANGED
@@ -80,10 +80,13 @@ class RecipeForm(forms.ModelForm):
80
80
 
81
81
 
82
82
  class RatingForm(forms.Form):
83
- """Simple form for rating recipes (1-5)."""
84
-
85
- score = forms.ChoiceField(
86
- choices=[(str(i), str(i)) for i in range(1, 6)],
87
- widget=forms.RadioSelect,
83
+ """Form for rating recipes (0-10)."""
84
+
85
+ score = forms.FloatField(
86
+ min_value=0.0,
87
+ max_value=10.0,
88
+ widget=forms.NumberInput(
89
+ attrs={"step": "0.1", "min": "0", "max": "10", "class": "slider"}
90
+ ),
88
91
  label="Your rating",
89
92
  )
@@ -0,0 +1,23 @@
1
+ # Generated by Django 6.0 on 2025-12-29 17:58
2
+
3
+ import django.core.validators
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+ dependencies = [
9
+ ("sandwitches", "0006_profile"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="rating",
15
+ name="score",
16
+ field=models.FloatField(
17
+ validators=[
18
+ django.core.validators.MinValueValidator(0.0),
19
+ django.core.validators.MaxValueValidator(10.0),
20
+ ]
21
+ ),
22
+ ),
23
+ ]
sandwitches/models.py CHANGED
@@ -6,6 +6,7 @@ from django.contrib.auth import get_user_model
6
6
  from django.db.models import Avg
7
7
  from .tasks import email_users
8
8
  from django.conf import settings
9
+ from django.core.validators import MinValueValidator, MaxValueValidator
9
10
  import logging
10
11
  from django.urls import reverse
11
12
 
@@ -179,7 +180,9 @@ class Recipe(models.Model):
179
180
  class Rating(models.Model):
180
181
  recipe = models.ForeignKey(Recipe, related_name="ratings", on_delete=models.CASCADE)
181
182
  user = models.ForeignKey(User, related_name="ratings", on_delete=models.CASCADE)
182
- score = models.PositiveSmallIntegerField(choices=[(i, i) for i in range(1, 6)])
183
+ score = models.FloatField(
184
+ validators=[MinValueValidator(0.0), MaxValueValidator(10.0)]
185
+ )
183
186
  created_at = models.DateTimeField(auto_now_add=True)
184
187
  updated_at = models.DateTimeField(auto_now=True)
185
188
 
sandwitches/settings.py CHANGED
@@ -149,7 +149,7 @@ AUTH_PASSWORD_VALIDATORS = [
149
149
 
150
150
  # Media files (for uploaded images)
151
151
  MEDIA_URL = "/media/"
152
- MEDIA_ROOT = Path("/config/media")
152
+ MEDIA_ROOT = Path(os.environ.get("MEDIA_ROOT", default=BASE_DIR / "media")) # ty:ignore[no-matching-overload]
153
153
 
154
154
  # Static (for CSS etc)
155
155
  STATIC_URL = "/static/"
@@ -83,24 +83,22 @@
83
83
  {% endif %}
84
84
 
85
85
  <div class="row">
86
- {% for i in "12345"|make_list %}
87
- <div class="col-sm-2">
88
- <label class="form-check">
89
- <input
90
- type="radio"
91
- name="{{ rating_form.score.name }}"
92
- id="rating-{{ i }}"
93
- value="{{ i }}"
94
- {% if user_rating and user_rating.score|stringformat:"s" == i %}
95
- checked
96
- {% elif rating_form.score.value == i %}
97
- checked
98
- {% endif %}
99
- />
100
- <span>{{ i }}</span>
101
- </label>
102
- </div>
103
- {% endfor %}
86
+ <div class="col-sm-12">
87
+ <label for="{{ rating_form.score.id_for_label }}">
88
+ Score (0-10): <span id="score-output">{{ rating_form.score.value|default:"5.0" }}</span>
89
+ </label>
90
+ <input
91
+ type="range"
92
+ name="{{ rating_form.score.name }}"
93
+ id="{{ rating_form.score.id_for_label }}"
94
+ min="0"
95
+ max="10"
96
+ step="0.1"
97
+ value="{{ rating_form.score.value|default:'5.0' }}"
98
+ oninput="document.getElementById('score-output').innerText = parseFloat(this.value).toFixed(1)"
99
+ style="width: 100%;"
100
+ >
101
+ </div>
104
102
  </div>
105
103
  </fieldset>
106
104
  <p style="margin-top:0.5rem;">
sandwitches/views.py CHANGED
@@ -66,7 +66,7 @@ def recipe_rate(request, pk):
66
66
 
67
67
  form = RatingForm(request.POST)
68
68
  if form.is_valid():
69
- score = int(form.cleaned_data["score"])
69
+ score = float(form.cleaned_data["score"])
70
70
  Rating.objects.update_or_create( # ty:ignore[unresolved-attribute]
71
71
  recipe=recipe, user=request.user, defaults={"score": score}
72
72
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sandwitches
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: Add your description here
5
5
  Author: Martyn van Dijke
6
6
  Author-email: Martyn van Dijke <martijnvdijke600@gmail.com>
@@ -1,8 +1,8 @@
1
1
  sandwitches/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  sandwitches/admin.py,sha256=IIVQOr_CIXsdFXDPQoZ_c83DuqbHVnw4Ht9tAtmvLM0,870
3
- sandwitches/api.py,sha256=r4HrlEv9IQMuvlr-WravamzTbUWcn85zS1e-iReHEuU,1968
3
+ sandwitches/api.py,sha256=YDadi-3f2Oz4ia5gXo_rgXVZkZ6LAOiOWraz9bpZzho,2404
4
4
  sandwitches/asgi.py,sha256=cygnXdXSSVspM7ZXuj47Ef6oz7HSTw4D7BPzgE2PU5w,399
5
- sandwitches/forms.py,sha256=NeGUi3xPzQpgw2cVWpo2ZKpYUXsCuJ3SzgGUkvxdV2A,2610
5
+ sandwitches/forms.py,sha256=RFOF9WFXB2kgZp-dXFJjmja_N9VFrBJaB1SB5Rr7zOo,2682
6
6
  sandwitches/locale/nl/LC_MESSAGES/django.mo,sha256=GgZ4aNmU-v0FStt7mafi_UCR4hC0PC06W0mIUPPWtUE,2906
7
7
  sandwitches/locale/nl/LC_MESSAGES/django.po,sha256=uk2W5ai6tyhKlA-rcucv5NpZfBrHNBev6Rp5wKWirqc,2843
8
8
  sandwitches/migrations/0001_initial.py,sha256=01IfkFbUyYMpTHV5GaBxJEKjzRIdUdPR5sY3AUTODww,2546
@@ -11,14 +11,15 @@ sandwitches/migrations/0003_rating.py,sha256=iKk9M9lcBS5LwsJkMYsmYfHKqKs2QRTILgI
11
11
  sandwitches/migrations/0004_add_uploaded_by.py,sha256=gZawakGU-H0Abnn2Bw_Mswy9ngipzUC-BHRXRByKVZo,720
12
12
  sandwitches/migrations/0005_historicalrecipe_uploaded_by.py,sha256=xmYDXgBxjrQkbEtorQlDzW0K1Z70UNxRrUk75WjYdEI,766
13
13
  sandwitches/migrations/0006_profile.py,sha256=gzmxZWXmjldimYRdovuNouc2Y2idihg8UvEaU0ad_Ds,1558
14
+ sandwitches/migrations/0007_alter_rating_score.py,sha256=hHdJqjTwq2afcBi7TRSBofAjedDxu5YybbXLhUoMGUg,588
14
15
  sandwitches/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- sandwitches/models.py,sha256=7Upm6abkEZjmk5rIzViW7M_4a3ai03-9tLWLkCty2hs,6390
16
- sandwitches/settings.py,sha256=5Qg0Wd-X1Kj1Fm7Teh0SRO8jOmVSUkpnUXfZRe1TjwI,5604
16
+ sandwitches/models.py,sha256=CxTwpzIej9hCnBb7kEF5bQAbw-lOvN_8w4SGplCDbFI,6484
17
+ sandwitches/settings.py,sha256=vkIxkZpbaobuLeqYydckYSBJBrCAs-4royx7vym2bQA,5680
17
18
  sandwitches/storage.py,sha256=HIiOEDa_LhpsbhCUBNO-SlCZDUJOoANUbyDIbspEcoE,2325
18
19
  sandwitches/tasks.py,sha256=aGLpTE42mCZbh2Pyt7fXIjbELm9lD727ir_2bto-wWw,3241
19
20
  sandwitches/templates/base.html,sha256=C9tUPfMKRvvdMqdDpE8ww21DH25bNktcVIwdrDEhajw,570
20
21
  sandwitches/templates/base_pico.html,sha256=yeWlWlrCfI9yVLStSyODvcNtSmxXvWm4SZORZN-31R4,8273
21
- sandwitches/templates/detail.html,sha256=p7FikXyse1bYxRCFCYH3GSwgNXHS7D9O6j4fUmmDkWQ,4592
22
+ sandwitches/templates/detail.html,sha256=6-JL7btpgVuoVhezjPlunw_ysZXbfIxy0GIVBiqZ5wE,4625
22
23
  sandwitches/templates/form.html,sha256=S4yUq9p2v7vWifhA5xj_Z4ObpMoaqUq2w08TDw3vk0o,449
23
24
  sandwitches/templates/index.html,sha256=tgZFplcedG1r4s8pBc_qvJDXECPqrESPOSw56FnnCkw,2606
24
25
  sandwitches/templates/setup.html,sha256=btid1XtR0MO_qSWriWX7LeWUtNFA7rDB4zt5Md9UNhU,1787
@@ -26,8 +27,8 @@ sandwitches/templates/signup.html,sha256=3qOdDMUHMshe2FoaQzR07lIm3Wbrzorb_h9Fp8O
26
27
  sandwitches/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
28
  sandwitches/templatetags/markdown_extras.py,sha256=0ibmRzxE3r85x4k7kK71R-9UT0CgeegYF7MHzj3juTI,344
28
29
  sandwitches/urls.py,sha256=maKaIDfb_kNmMwrpS495TymuFnJJ6fbLoi5QRLjrFds,1582
29
- sandwitches/views.py,sha256=Av9dfTAygGkFkHO47NK6RDjprMTVRpDa4c63X_h9ur8,5192
30
+ sandwitches/views.py,sha256=7ukWJHBflhAM02j_ZGuoqlBEgN2QnIIq4VhtnvRU1rM,5194
30
31
  sandwitches/wsgi.py,sha256=Eyncpnahq_4s3Lr9ruB-R3Lu9j9zBXqgPbUj7qhIbwU,399
31
- sandwitches-1.2.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
32
- sandwitches-1.2.0.dist-info/METADATA,sha256=psetHwoaKHYa-_anYOLXOaBdi1UumZwg5lR8uStEg_I,731
33
- sandwitches-1.2.0.dist-info/RECORD,,
32
+ sandwitches-1.3.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
33
+ sandwitches-1.3.0.dist-info/METADATA,sha256=d8rJUM76Ts32l7skMKmNezjt7gdH56TzrZGDPfgygEM,731
34
+ sandwitches-1.3.0.dist-info/RECORD,,