sandwitches 1.2.0__tar.gz → 1.3.0__tar.gz
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-1.2.0 → sandwitches-1.3.0}/PKG-INFO +1 -1
- {sandwitches-1.2.0 → sandwitches-1.3.0}/pyproject.toml +1 -1
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/api.py +19 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/forms.py +8 -5
- sandwitches-1.3.0/src/sandwitches/migrations/0007_alter_rating_score.py +23 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/models.py +4 -1
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/settings.py +1 -1
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/templates/detail.html +16 -18
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/views.py +1 -1
- {sandwitches-1.2.0 → sandwitches-1.3.0}/README.md +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/__init__.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/admin.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/asgi.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/locale/nl/LC_MESSAGES/django.mo +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/locale/nl/LC_MESSAGES/django.po +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/migrations/0001_initial.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/migrations/0002_historicalrecipe.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/migrations/0003_rating.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/migrations/0004_add_uploaded_by.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/migrations/0005_historicalrecipe_uploaded_by.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/migrations/0006_profile.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/migrations/__init__.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/storage.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/tasks.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/templates/base.html +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/templates/base_pico.html +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/templates/form.html +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/templates/index.html +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/templates/setup.html +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/templates/signup.html +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/templatetags/__init__.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/templatetags/markdown_extras.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/urls.py +0 -0
- {sandwitches-1.2.0 → sandwitches-1.3.0}/src/sandwitches/wsgi.py +0 -0
|
@@ -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]
|
|
@@ -80,10 +80,13 @@ class RecipeForm(forms.ModelForm):
|
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
class RatingForm(forms.Form):
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
score = forms.
|
|
86
|
-
|
|
87
|
-
|
|
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
|
+
]
|
|
@@ -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.
|
|
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
|
|
|
@@ -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("/
|
|
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
|
-
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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;">
|
|
@@ -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 =
|
|
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
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|