style: 🎨 make code ruff compliant

This commit is contained in:
m5ka 2024-03-26 12:18:47 +00:00
parent 11ed6bd2a1
commit a4f8275383
21 changed files with 819 additions and 238 deletions

View file

@ -3,7 +3,6 @@ from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from moku import models from moku import models
for model_name in models.__all__: for model_name in models.__all__:
model = getattr(models, model_name) model = getattr(models, model_name)
if model.__name__ != "User": if model.__name__ != "User":
@ -14,32 +13,11 @@ for model_name in models.__all__:
class UserAdmin(BaseUserAdmin): class UserAdmin(BaseUserAdmin):
fieldsets = ( fieldsets = (
(None, {"fields": ("username", "email", "password")}), (None, {"fields": ("username", "email", "password")}),
( ("Profile", {"fields": ("pronouns", "location", "bio")}),
"Profile", ("Status", {"fields": ("email_confirmed_at",)}),
{
"fields": (
"pronouns", "location", "bio"
),
},
),
(
"Status",
{
"fields": (
"email_confirmed_at",
)
},
),
( (
"Permissions", "Permissions",
{ {"fields": ("is_staff", "is_superuser", "groups", "user_permissions")},
"fields": (
"is_staff",
"is_superuser",
"groups",
"user_permissions",
), ),
}, ("Dates", {"fields": ("date_joined", "last_seen_at")}),
),
("Dates", {"fields": ("date_joined", "last_seen_at",)}),
) )

View file

@ -1,4 +1,3 @@
import sys
from pathlib import Path from pathlib import Path
import environ import environ
@ -71,9 +70,7 @@ TEMPLATES = [
"django.template.context_processors.tz", "django.template.context_processors.tz",
"django.contrib.messages.context_processors.messages", "django.contrib.messages.context_processors.messages",
], ],
"filters": { "filters": {"unemoji": "moku.filters.unemoji"},
"unemoji": "moku.filters.unemoji",
},
"policies": {"ext.i18n.trimmed": True}, "policies": {"ext.i18n.trimmed": True},
}, },
}, },

View file

@ -14,6 +14,7 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.conf import settings from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from django.contrib import admin from django.contrib import admin
@ -50,7 +51,11 @@ urlpatterns = [
path("recipes/<str:uuid>", ShowRecipeView.as_view(), name="recipe.show"), path("recipes/<str:uuid>", ShowRecipeView.as_view(), name="recipe.show"),
path("recipes/<str:uuid>/delete", DeleteRecipeView.as_view(), name="recipe.delete"), path("recipes/<str:uuid>/delete", DeleteRecipeView.as_view(), name="recipe.delete"),
path("recipes/<str:uuid>/<str:step>", EditStepView.as_view(), name="step.edit"), path("recipes/<str:uuid>/<str:step>", EditStepView.as_view(), name="step.edit"),
path("recipes/<str:uuid>/<str:step>/delete", DeleteStepView.as_view(), name="step.delete"), path(
"recipes/<str:uuid>/<str:step>/delete",
DeleteStepView.as_view(),
name="step.delete",
),
] ]
if settings.DEBUG_TOOLBAR: if settings.DEBUG_TOOLBAR:

View file

@ -22,53 +22,228 @@ EMOJI_CATEGORIES = [
( (
_("fruit & veg"), _("fruit & veg"),
( (
"🍏", "🍎", "🍐", "🍊", "🍋", "🍌", "🍉", "🍇", "🍓", "🫐", "🍈", "🍒", "🍑", "🥭", "🍍", "🍏",
"🥥", "🥝", "🍅", "🍆", "🥑", "🫛", "🥦", "🥬", "🥒", "🌶️", "🫑", "🌽", "🥕", "🫒", "🧄", "🍎",
"🧅", "🥔", "🍠", "🫚", "🍐",
"🍊",
"🍋",
"🍌",
"🍉",
"🍇",
"🍓",
"🫐",
"🍈",
"🍒",
"🍑",
"🥭",
"🍍",
"🥥",
"🥝",
"🍅",
"🍆",
"🥑",
"🫛",
"🥦",
"🥬",
"🥒",
"🌶️",
"🫑",
"🌽",
"🥕",
"🫒",
"🧄",
"🧅",
"🥔",
"🍠",
"🫚",
), ),
), ),
( (
_("savoury dishes"), _("savoury dishes"),
( (
"🥯", "🍞", "🥖", "🥨", "🧀", "🥚", "🍳", "🧈", "🥞", "🧇", "🥓", "🥩", "🍗", "🍖", "🦴", "🥯",
"🌭", "🍔", "🍟", "🍕", "🫓", "🥪", "🥙", "🧆", "🌮", "🌯", "🫔", "🥗", "🥘", "🫕", "🥫", "🍞",
"🫙", "🍝", "🍜", "🍲", "🍛", "🍣", "🍱", "🥟", "🦪", "🍤", "🍙", "🍚", "🍘", "🍥", "🌰", "🥖",
"🥜", "🫘", "🧊", "🥨",
"🧀",
"🥚",
"🍳",
"🧈",
"🥞",
"🧇",
"🥓",
"🥩",
"🍗",
"🍖",
"🦴",
"🌭",
"🍔",
"🍟",
"🍕",
"🫓",
"🥪",
"🥙",
"🧆",
"🌮",
"🌯",
"🫔",
"🥗",
"🥘",
"🫕",
"🥫",
"🫙",
"🍝",
"🍜",
"🍲",
"🍛",
"🍣",
"🍱",
"🥟",
"🦪",
"🍤",
"🍙",
"🍚",
"🍘",
"🍥",
"🌰",
"🥜",
"🫘",
"🧊",
), ),
), ),
( (
_("sweet treats"), _("sweet treats"),
( (
"🥠", "🥮", "🍢", "🍡", "🍧", "🍨", "🍦", "🥧", "🧁", "🍰", "🎂", "🍮", "🍭", "🍬", "🍫", "🥠",
"🥐", "🍿", "🍩", "🍪", "🍯", "🥮",
"🍢",
"🍡",
"🍧",
"🍨",
"🍦",
"🥧",
"🧁",
"🍰",
"🎂",
"🍮",
"🍭",
"🍬",
"🍫",
"🥐",
"🍿",
"🍩",
"🍪",
"🍯",
), ),
), ),
( (
_("drinks"), _("drinks"),
( (
"🥛", "🫗", "🍼", "🫖", "☕️", "🍵", "🧃", "🥤", "🧋", "🍶", "🍺", "🍻", "🥂", "🍷", "🥃", "🥛",
"🍸", "🍹", "🧉", "🍾", "🫗",
"🍼",
"🫖",
"☕️",
"🍵",
"🧃",
"🥤",
"🧋",
"🍶",
"🍺",
"🍻",
"🥂",
"🍷",
"🥃",
"🍸",
"🍹",
"🧉",
"🍾",
), ),
), ),
( (
_("people"), _("people"),
( (
"😀", "😃", "😄", "😁", "😆", "🥹", "😅", "😂", "🤣", "🥲", "😊", "😇", "🙂", "🙃", "😉", "😀",
"😌", "😌", "😍", "🥰", "😘", "😗", "😙", "😚", "😋", "😛", "😝", "😜", "🤪", "🤨", "🧐", "😃",
"😄",
"😁",
"😆",
"🥹",
"😅",
"😂",
"🤣",
"🥲",
"😊",
"😇",
"🙂",
"🙃",
"😉",
"😌",
"😌",
"😍",
"🥰",
"😘",
"😗",
"😙",
"😚",
"😋",
"😛",
"😝",
"😜",
"🤪",
"🤨",
"🧐",
), ),
), ),
( (
_("animals"), _("animals"),
( (
"🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼", "🐨", "🐯", "🦁", "🐮", "🐷", "🐽", "🐸", "🐶",
"🐵", "🙈", "🙉", "🙊", "🐒", "🐔", "🐧", "🐦", "🐤", "🐣", "🐥", "🪿", "🦆", "🐦‍⬛", "🦅", "🐱",
"🦉", "🦇", "🐺", "🐗", "🐴", "🦄", "🫎", "🐝", "🪱", "🐛", "🦋", "🐌", "🐞", "🐜", "🪰", "🐭",
"🐹",
"🐰",
"🦊",
"🐻",
"🐼",
"🐨",
"🐯",
"🦁",
"🐮",
"🐷",
"🐽",
"🐸",
"🐵",
"🙈",
"🙉",
"🙊",
"🐒",
"🐔",
"🐧",
"🐦",
"🐤",
"🐣",
"🐥",
"🪿",
"🦆",
"🐦‍⬛",
"🦅",
"🦉",
"🦇",
"🐺",
"🐗",
"🐴",
"🦄",
"🫎",
"🐝",
"🪱",
"🐛",
"🦋",
"🐌",
"🐞",
"🐜",
"🪰",
), ),
), ),
( (_("tools & things"), ("🥄", "🍴", "🍽️", "🥣", "🥡", "🥢", "🧂", "🔪", "🪓")),
_("tools & things"),
(
"🥄", "🍴", "🍽️", "🥣", "🥡", "🥢", "🧂", "🔪", "🪓",
)
)
] ]

View file

@ -1,4 +1,4 @@
from django.forms import Form, ModelForm from django.forms import ModelForm
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from moku.models.recipe import Recipe, RecipeStep from moku.models.recipe import Recipe, RecipeStep
@ -8,9 +8,7 @@ class RecipeForm(ModelForm):
class Meta: class Meta:
model = Recipe model = Recipe
fields = ("title",) fields = ("title",)
labels = { labels = {"title": _("recipe title")}
"title": _("recipe title"),
}
class RecipeStepForm(ModelForm): class RecipeStepForm(ModelForm):

View file

@ -1,7 +1,6 @@
from django import forms from django import forms
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.forms import UserCreationForm
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_recaptcha.fields import ReCaptchaField from django_recaptcha.fields import ReCaptchaField
from moku.models.user import User, UserSettings from moku.models.user import User, UserSettings
@ -14,10 +13,7 @@ class UserForm(UserCreationForm):
class Meta(UserCreationForm.Meta): class Meta(UserCreationForm.Meta):
model = User model = User
fields = ("username", "email", "password1", "password2") fields = ("username", "email", "password1", "password2")
labels = { labels = {"username": _("username"), "email": _("email address")}
"username": _("username"),
"email": _("email address"),
}
help_texts = { help_texts = {
"username": User._meta.get_field("username").help_text, "username": User._meta.get_field("username").help_text,
"email": User._meta.get_field("email").help_text, "email": User._meta.get_field("email").help_text,
@ -26,10 +22,10 @@ class UserForm(UserCreationForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["captcha"].error_messages = { self.fields["captcha"].error_messages = {
"required": _("make sure you've ticked the captcha."), "required": _("make sure you've ticked the captcha.")
} }
self.fields["check"].error_messages = { self.fields["check"].error_messages = {
"required": _("you must agree to the terms of use and privacy policy."), "required": _("you must agree to the terms of use and privacy policy.")
} }
@ -37,9 +33,7 @@ class UserSettingsForm(forms.ModelForm):
class Meta: class Meta:
model = UserSettings model = UserSettings
fields = ("language",) fields = ("language",)
labels = { labels = {"language": _("language")}
"language": _("language"),
}
class ProfileForm(forms.ModelForm): class ProfileForm(forms.ModelForm):

View file

@ -1,49 +1,162 @@
# ruff: noqa: E501
# Generated by Django 5.0.3 on 2024-03-24 17:24 # Generated by Django 5.0.3 on 2024-03-24 17:24
import re
import django.contrib.auth.models import django.contrib.auth.models
import django.core.validators import django.core.validators
import django.utils.timezone import django.utils.timezone
import moku.validators
import re
from django.db import migrations, models from django.db import migrations, models
import moku.validators
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [("auth", "0012_alter_user_first_name_max_length")]
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='User', name="User",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('password', models.CharField(max_length=128, verbose_name='password')), "id",
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), models.BigAutoField(
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), auto_created=True,
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), primary_key=True,
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), serialize=False,
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), verbose_name="ID",
('username', models.CharField(db_index=True, help_text="this is the unique identifier you'll use to log in. it may only contain letters, numbers, hyphens, dashes and dots.", max_length=64, unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[a-zA-Z0-9-_.]+\\Z'), 'Username may only contain letters, numbers, hyphens, underscores and dots.', 'invalid'), moku.validators.validate_username_length], verbose_name='username')), ),
('email', models.EmailField(help_text="this should be your email address. make sure it's valid and that you have access to it.", max_length=128, unique=True, verbose_name='email address')), ),
('email_confirmed_at', models.DateTimeField(blank=True, null=True)), ("password", models.CharField(max_length=128, verbose_name="password")),
('pronouns', models.CharField(blank=True, help_text='what pronouns should people use when referring to you?', max_length=64, verbose_name='pronouns')), (
('location', models.CharField(blank=True, help_text='where in the world are you?', max_length=64, verbose_name='location')), "last_login",
('bio', models.TextField(blank=True, help_text='write something about yourself!', verbose_name='about me')), models.DateTimeField(
('last_seen_at', models.DateTimeField(blank=True, help_text='the last time this user accessed the site.', null=True, verbose_name='last seen at')), blank=True, null=True, verbose_name="last login"
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), ),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), ),
(
"is_superuser",
models.BooleanField(
default=False,
help_text="Designates that this user has all permissions without explicitly assigning them.",
verbose_name="superuser status",
),
),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"is_active",
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
),
),
(
"date_joined",
models.DateTimeField(
default=django.utils.timezone.now, verbose_name="date joined"
),
),
(
"username",
models.CharField(
db_index=True,
help_text="this is the unique identifier you'll use to log in. it may only contain letters, numbers, hyphens, dashes and dots.",
max_length=64,
unique=True,
validators=[
django.core.validators.RegexValidator(
re.compile("^[a-zA-Z0-9-_.]+\\Z"),
"Username may only contain letters, numbers, hyphens, underscores and dots.",
"invalid",
),
moku.validators.validate_username_length,
],
verbose_name="username",
),
),
(
"email",
models.EmailField(
help_text="this should be your email address. make sure it's valid and that you have access to it.",
max_length=128,
unique=True,
verbose_name="email address",
),
),
("email_confirmed_at", models.DateTimeField(blank=True, null=True)),
(
"pronouns",
models.CharField(
blank=True,
help_text="what pronouns should people use when referring to you?",
max_length=64,
verbose_name="pronouns",
),
),
(
"location",
models.CharField(
blank=True,
help_text="where in the world are you?",
max_length=64,
verbose_name="location",
),
),
(
"bio",
models.TextField(
blank=True,
help_text="write something about yourself!",
verbose_name="about me",
),
),
(
"last_seen_at",
models.DateTimeField(
blank=True,
help_text="the last time this user accessed the site.",
null=True,
verbose_name="last seen at",
),
),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
related_name="user_set",
related_query_name="user",
to="auth.group",
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.permission",
verbose_name="user permissions",
),
),
], ],
options={ options={
'verbose_name': 'user', "verbose_name": "user",
'verbose_name_plural': 'users', "verbose_name_plural": "users",
'abstract': False, "abstract": False,
}, },
managers=[ managers=[("objects", django.contrib.auth.models.UserManager())],
('objects', django.contrib.auth.models.UserManager()), )
],
),
] ]

View file

@ -1,32 +1,104 @@
# ruff: noqa: E501
# Generated by Django 5.0.3 on 2024-03-25 10:04 # Generated by Django 5.0.3 on 2024-03-25 10:04
import django.db.models.deletion import django.db.models.deletion
import moku.models.post
import moku.validators
import shortuuid.django_fields import shortuuid.django_fields
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import moku.models.post
import moku.validators
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("moku", "0001_initial")]
dependencies = [
('moku', '0001_initial'),
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Post', name="Post",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('uuid', shortuuid.django_fields.ShortUUIDField(alphabet=None, help_text='the unique id that identifies this post.', length=22, max_length=22, prefix='', verbose_name='unique id')), "id",
('emoji', models.CharField(help_text='an emoji to accompany your post!', max_length=8, validators=[moku.validators.validate_emoji], verbose_name='emoji')), models.BigAutoField(
('verb', models.CharField(choices=[('ate', '%(user)s ate %(food)s'), ('made', '%(user)s made %(food)s'), ('cooked', '%(user)s cooked %(food)s'), ('baked', '%(user)s baked %(food)s'), ('ordered', '%(user)s ordered %(food)s')], help_text='how should we best phrase this entry?', max_length=32, verbose_name='verb')), auto_created=True,
('food', models.CharField(help_text='what did you eat?', max_length=128, verbose_name='food')), primary_key=True,
('image', models.ImageField(blank=True, help_text='here you can upload a picture of what you ate!', upload_to=moku.models.post.post_image_filename, verbose_name='image')), serialize=False,
('created_at', models.DateTimeField(auto_now_add=True, help_text='when this post was created.')), verbose_name="ID",
('updated_at', models.DateTimeField(auto_now=True, help_text='when this post was last updated.')),
('created_by', models.ForeignKey(db_column='created_by_user_id', on_delete=django.db.models.deletion.CASCADE, related_name='posts', to=settings.AUTH_USER_MODEL)),
],
), ),
),
(
"uuid",
shortuuid.django_fields.ShortUUIDField(
alphabet=None,
help_text="the unique id that identifies this post.",
length=22,
max_length=22,
prefix="",
verbose_name="unique id",
),
),
(
"emoji",
models.CharField(
help_text="an emoji to accompany your post!",
max_length=8,
validators=[moku.validators.validate_emoji],
verbose_name="emoji",
),
),
(
"verb",
models.CharField(
choices=[
("ate", "%(user)s ate %(food)s"),
("made", "%(user)s made %(food)s"),
("cooked", "%(user)s cooked %(food)s"),
("baked", "%(user)s baked %(food)s"),
("ordered", "%(user)s ordered %(food)s"),
],
help_text="how should we best phrase this entry?",
max_length=32,
verbose_name="verb",
),
),
(
"food",
models.CharField(
help_text="what did you eat?",
max_length=128,
verbose_name="food",
),
),
(
"image",
models.ImageField(
blank=True,
help_text="here you can upload a picture of what you ate!",
upload_to=moku.models.post.post_image_filename,
verbose_name="image",
),
),
(
"created_at",
models.DateTimeField(
auto_now_add=True, help_text="when this post was created."
),
),
(
"updated_at",
models.DateTimeField(
auto_now=True, help_text="when this post was last updated."
),
),
(
"created_by",
models.ForeignKey(
db_column="created_by_user_id",
on_delete=django.db.models.deletion.CASCADE,
related_name="posts",
to=settings.AUTH_USER_MODEL,
),
),
],
)
] ]

View file

@ -1,19 +1,23 @@
# ruff: noqa: E501
# Generated by Django 5.0.3 on 2024-03-25 13:49 # Generated by Django 5.0.3 on 2024-03-25 13:49
import moku.models.user
from django.db import migrations, models from django.db import migrations, models
import moku.models.user
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("moku", "0002_post")]
dependencies = [
('moku', '0002_post'),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='user', model_name="user",
name='avatar', name="avatar",
field=models.ImageField(blank=True, help_text='a little picture to show up on your profile.', upload_to=moku.models.user.user_avatar_filename, verbose_name='avatar'), field=models.ImageField(
blank=True,
help_text="a little picture to show up on your profile.",
upload_to=moku.models.user.user_avatar_filename,
verbose_name="avatar",
), ),
)
] ]

View file

@ -1,18 +1,28 @@
# ruff: noqa: E501
# Generated by Django 5.0.3 on 2024-03-25 15:34 # Generated by Django 5.0.3 on 2024-03-25 15:34
from django.db import migrations, models from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("moku", "0003_user_avatar")]
dependencies = [
('moku', '0003_user_avatar'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='post', model_name="post",
name='verb', name="verb",
field=models.CharField(choices=[('ate', '%(user)s ate %(food)s'), ('drank', '%(user)s drank %(food)s'), ('made', '%(user)s made %(food)s'), ('cooked', '%(user)s cooked %(food)s'), ('baked', '%(user)s baked %(food)s'), ('ordered', '%(user)s ordered %(food)s')], help_text='how should we best phrase this entry?', max_length=32, verbose_name='verb'), field=models.CharField(
choices=[
("ate", "%(user)s ate %(food)s"),
("drank", "%(user)s drank %(food)s"),
("made", "%(user)s made %(food)s"),
("cooked", "%(user)s cooked %(food)s"),
("baked", "%(user)s baked %(food)s"),
("ordered", "%(user)s ordered %(food)s"),
],
help_text="how should we best phrase this entry?",
max_length=32,
verbose_name="verb",
), ),
)
] ]

View file

@ -1,3 +1,4 @@
# ruff: noqa: E501
# Generated by Django 5.0.3 on 2024-03-25 17:02 # Generated by Django 5.0.3 on 2024-03-25 17:02
import django.db.models.deletion import django.db.models.deletion
@ -6,18 +7,139 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("moku", "0004_alter_post_verb")]
dependencies = [
('moku', '0004_alter_post_verb'),
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='UserSettings', name="UserSettings",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('language', models.CharField(choices=[('af', 'Afrikaans'), ('ar', 'Arabic'), ('ar-dz', 'Algerian Arabic'), ('ast', 'Asturian'), ('az', 'Azerbaijani'), ('bg', 'Bulgarian'), ('be', 'Belarusian'), ('bn', 'Bengali'), ('br', 'Breton'), ('bs', 'Bosnian'), ('ca', 'Catalan'), ('ckb', 'Central Kurdish (Sorani)'), ('cs', 'Czech'), ('cy', 'Welsh'), ('da', 'Danish'), ('de', 'German'), ('dsb', 'Lower Sorbian'), ('el', 'Greek'), ('en', 'English'), ('en-au', 'Australian English'), ('en-gb', 'British English'), ('eo', 'Esperanto'), ('es', 'Spanish'), ('es-ar', 'Argentinian Spanish'), ('es-co', 'Colombian Spanish'), ('es-mx', 'Mexican Spanish'), ('es-ni', 'Nicaraguan Spanish'), ('es-ve', 'Venezuelan Spanish'), ('et', 'Estonian'), ('eu', 'Basque'), ('fa', 'Persian'), ('fi', 'Finnish'), ('fr', 'French'), ('fy', 'Frisian'), ('ga', 'Irish'), ('gd', 'Scottish Gaelic'), ('gl', 'Galician'), ('he', 'Hebrew'), ('hi', 'Hindi'), ('hr', 'Croatian'), ('hsb', 'Upper Sorbian'), ('hu', 'Hungarian'), ('hy', 'Armenian'), ('ia', 'Interlingua'), ('id', 'Indonesian'), ('ig', 'Igbo'), ('io', 'Ido'), ('is', 'Icelandic'), ('it', 'Italian'), ('ja', 'Japanese'), ('ka', 'Georgian'), ('kab', 'Kabyle'), ('kk', 'Kazakh'), ('km', 'Khmer'), ('kn', 'Kannada'), ('ko', 'Korean'), ('ky', 'Kyrgyz'), ('lb', 'Luxembourgish'), ('lt', 'Lithuanian'), ('lv', 'Latvian'), ('mk', 'Macedonian'), ('ml', 'Malayalam'), ('mn', 'Mongolian'), ('mr', 'Marathi'), ('ms', 'Malay'), ('my', 'Burmese'), ('nb', 'Norwegian Bokmål'), ('ne', 'Nepali'), ('nl', 'Dutch'), ('nn', 'Norwegian Nynorsk'), ('os', 'Ossetic'), ('pa', 'Punjabi'), ('pl', 'Polish'), ('pt', 'Portuguese'), ('pt-br', 'Brazilian Portuguese'), ('ro', 'Romanian'), ('ru', 'Russian'), ('sk', 'Slovak'), ('sl', 'Slovenian'), ('sq', 'Albanian'), ('sr', 'Serbian'), ('sr-latn', 'Serbian Latin'), ('sv', 'Swedish'), ('sw', 'Swahili'), ('ta', 'Tamil'), ('te', 'Telugu'), ('tg', 'Tajik'), ('th', 'Thai'), ('tk', 'Turkmen'), ('tr', 'Turkish'), ('tt', 'Tatar'), ('udm', 'Udmurt'), ('ug', 'Uyghur'), ('uk', 'Ukrainian'), ('ur', 'Urdu'), ('uz', 'Uzbek'), ('vi', 'Vietnamese'), ('zh-hans', 'Simplified Chinese'), ('zh-hant', 'Traditional Chinese')], default='en', help_text='what language do you want to use moku.blog in?', max_length=16, verbose_name='language')), "id",
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='settings', to=settings.AUTH_USER_MODEL)), models.BigAutoField(
], auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
), ),
),
(
"language",
models.CharField(
choices=[
("af", "Afrikaans"),
("ar", "Arabic"),
("ar-dz", "Algerian Arabic"),
("ast", "Asturian"),
("az", "Azerbaijani"),
("bg", "Bulgarian"),
("be", "Belarusian"),
("bn", "Bengali"),
("br", "Breton"),
("bs", "Bosnian"),
("ca", "Catalan"),
("ckb", "Central Kurdish (Sorani)"),
("cs", "Czech"),
("cy", "Welsh"),
("da", "Danish"),
("de", "German"),
("dsb", "Lower Sorbian"),
("el", "Greek"),
("en", "English"),
("en-au", "Australian English"),
("en-gb", "British English"),
("eo", "Esperanto"),
("es", "Spanish"),
("es-ar", "Argentinian Spanish"),
("es-co", "Colombian Spanish"),
("es-mx", "Mexican Spanish"),
("es-ni", "Nicaraguan Spanish"),
("es-ve", "Venezuelan Spanish"),
("et", "Estonian"),
("eu", "Basque"),
("fa", "Persian"),
("fi", "Finnish"),
("fr", "French"),
("fy", "Frisian"),
("ga", "Irish"),
("gd", "Scottish Gaelic"),
("gl", "Galician"),
("he", "Hebrew"),
("hi", "Hindi"),
("hr", "Croatian"),
("hsb", "Upper Sorbian"),
("hu", "Hungarian"),
("hy", "Armenian"),
("ia", "Interlingua"),
("id", "Indonesian"),
("ig", "Igbo"),
("io", "Ido"),
("is", "Icelandic"),
("it", "Italian"),
("ja", "Japanese"),
("ka", "Georgian"),
("kab", "Kabyle"),
("kk", "Kazakh"),
("km", "Khmer"),
("kn", "Kannada"),
("ko", "Korean"),
("ky", "Kyrgyz"),
("lb", "Luxembourgish"),
("lt", "Lithuanian"),
("lv", "Latvian"),
("mk", "Macedonian"),
("ml", "Malayalam"),
("mn", "Mongolian"),
("mr", "Marathi"),
("ms", "Malay"),
("my", "Burmese"),
("nb", "Norwegian Bokmål"),
("ne", "Nepali"),
("nl", "Dutch"),
("nn", "Norwegian Nynorsk"),
("os", "Ossetic"),
("pa", "Punjabi"),
("pl", "Polish"),
("pt", "Portuguese"),
("pt-br", "Brazilian Portuguese"),
("ro", "Romanian"),
("ru", "Russian"),
("sk", "Slovak"),
("sl", "Slovenian"),
("sq", "Albanian"),
("sr", "Serbian"),
("sr-latn", "Serbian Latin"),
("sv", "Swedish"),
("sw", "Swahili"),
("ta", "Tamil"),
("te", "Telugu"),
("tg", "Tajik"),
("th", "Thai"),
("tk", "Turkmen"),
("tr", "Turkish"),
("tt", "Tatar"),
("udm", "Udmurt"),
("ug", "Uyghur"),
("uk", "Ukrainian"),
("ur", "Urdu"),
("uz", "Uzbek"),
("vi", "Vietnamese"),
("zh-hans", "Simplified Chinese"),
("zh-hant", "Traditional Chinese"),
],
default="en",
help_text="what language do you want to use moku.blog in?",
max_length=16,
verbose_name="language",
),
),
(
"user",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="settings",
to=settings.AUTH_USER_MODEL,
),
),
],
)
] ]

View file

@ -1,3 +1,4 @@
# ruff: noqa: E501
# Generated by Django 5.0.3 on 2024-03-25 21:09 # Generated by Django 5.0.3 on 2024-03-25 21:09
import django.db.models.deletion import django.db.models.deletion
@ -7,36 +8,114 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [("moku", "0005_usersettings")]
dependencies = [
('moku', '0005_usersettings'),
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Recipe', name="Recipe",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('uuid', shortuuid.django_fields.ShortUUIDField(alphabet=None, help_text='the unique id that identifies this recipe.', length=22, max_length=22, prefix='', verbose_name='unique id')), "id",
('title', models.CharField(help_text='give the recipe a title, just so you know the recipe is for.', max_length=64, verbose_name='recipe title')), models.BigAutoField(
('created_at', models.DateTimeField(auto_now_add=True)), auto_created=True,
('updated_at', models.DateTimeField(auto_now=True)), primary_key=True,
('created_by', models.ForeignKey(db_column='created_by_user_id', on_delete=django.db.models.deletion.CASCADE, related_name='recipes', to=settings.AUTH_USER_MODEL)), serialize=False,
verbose_name="ID",
),
),
(
"uuid",
shortuuid.django_fields.ShortUUIDField(
alphabet=None,
help_text="the unique id that identifies this recipe.",
length=22,
max_length=22,
prefix="",
verbose_name="unique id",
),
),
(
"title",
models.CharField(
help_text="give the recipe a title, just so you know the recipe is for.",
max_length=64,
verbose_name="recipe title",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"created_by",
models.ForeignKey(
db_column="created_by_user_id",
on_delete=django.db.models.deletion.CASCADE,
related_name="recipes",
to=settings.AUTH_USER_MODEL,
),
),
], ],
), ),
migrations.AddField( migrations.AddField(
model_name='post', model_name="post",
name='recipe', name="recipe",
field=models.ForeignKey(blank=True, help_text='the recipe for what you ate, if you have one.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='moku.recipe', verbose_name='recipe'), field=models.ForeignKey(
blank=True,
help_text="the recipe for what you ate, if you have one.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to="moku.recipe",
verbose_name="recipe",
),
), ),
migrations.CreateModel( migrations.CreateModel(
name='RecipeStep', name="RecipeStep",
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('uuid', shortuuid.django_fields.ShortUUIDField(alphabet=None, help_text='the unique id that identifies this step.', length=22, max_length=22, prefix='', verbose_name='step id')), "id",
('instructions', models.CharField(help_text='the instructions for this step of the recipe. try to keep it clear and concise!', max_length=128, verbose_name='step instructions')), models.BigAutoField(
('order', models.IntegerField(db_index=True, default=0, help_text='which step in the recipe is this. this affects the order the recipe steps are shown.', verbose_name='step number')), auto_created=True,
('recipe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='steps', to='moku.recipe')), primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"uuid",
shortuuid.django_fields.ShortUUIDField(
alphabet=None,
help_text="the unique id that identifies this step.",
length=22,
max_length=22,
prefix="",
verbose_name="step id",
),
),
(
"instructions",
models.CharField(
help_text="the instructions for this step of the recipe. try to keep it clear and concise!",
max_length=128,
verbose_name="step instructions",
),
),
(
"order",
models.IntegerField(
db_index=True,
default=0,
help_text="which step in the recipe is this. this affects the order the recipe steps are shown.",
verbose_name="step number",
),
),
(
"recipe",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="steps",
to="moku.recipe",
),
),
], ],
), ),
] ]

View file

@ -2,11 +2,4 @@ from moku.models.post import Post
from moku.models.recipe import Recipe, RecipeStep from moku.models.recipe import Recipe, RecipeStep
from moku.models.user import User, UserSettings from moku.models.user import User, UserSettings
__all__ = ["Post", "Recipe", "RecipeStep", "User", "UserSettings"]
__all__ = [
"Post",
"Recipe",
"RecipeStep",
"User",
"UserSettings",
]

View file

@ -14,11 +14,17 @@ def post_image_filename(instance, _):
class PostManager(models.Manager): class PostManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super().get_queryset().select_related("created_by") \ return (
super()
.get_queryset()
.select_related("created_by")
.prefetch_related( .prefetch_related(
models.Prefetch("recipe__steps", queryset=RecipeStep.objects.order_by("order")) models.Prefetch(
) \ "recipe__steps", queryset=RecipeStep.objects.order_by("order")
)
)
.order_by("-created_at") .order_by("-created_at")
)
class Post(models.Model): class Post(models.Model):
@ -41,9 +47,7 @@ class Post(models.Model):
help_text=_("how should we best phrase this entry?"), help_text=_("how should we best phrase this entry?"),
) )
food = models.CharField( food = models.CharField(
verbose_name=_("food"), verbose_name=_("food"), max_length=128, help_text=_("what did you eat?")
max_length=128,
help_text=_("what did you eat?"),
) )
image = models.ImageField( image = models.ImageField(
verbose_name=_("image"), verbose_name=_("image"),
@ -68,12 +72,10 @@ class Post(models.Model):
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
created_at = models.DateTimeField( created_at = models.DateTimeField(
auto_now_add=True, auto_now_add=True, help_text=_("when this post was created.")
help_text=_("when this post was created."),
) )
updated_at = models.DateTimeField( updated_at = models.DateTimeField(
auto_now=True, auto_now=True, help_text=_("when this post was last updated.")
help_text=_("when this post was last updated."),
) )
objects = PostManager() objects = PostManager()
@ -84,6 +86,9 @@ class Post(models.Model):
@property @property
def text(self): def text(self):
return self.get_verb_display() % { return self.get_verb_display() % {
"user": f"<a href=\"{self.created_by.get_absolute_url()}\">@{self.created_by.username}</a>", "user": (
f'<a href="{self.created_by.get_absolute_url()}">'
f"@{self.created_by.username}</a>"
),
"food": escape(self.food), "food": escape(self.food),
} }

View file

@ -1,15 +1,18 @@
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from shortuuid.django_fields import ShortUUIDField from shortuuid.django_fields import ShortUUIDField
class RecipeManager(models.Manager): class RecipeManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super().get_queryset() \ return (
super()
.get_queryset()
.prefetch_related( .prefetch_related(
models.Prefetch("steps", queryset=RecipeStep.objects.order_by("order")) models.Prefetch("steps", queryset=RecipeStep.objects.order_by("order"))
) )
)
class Recipe(models.Model): class Recipe(models.Model):
@ -31,12 +34,8 @@ class Recipe(models.Model):
db_column="created_by_user_id", db_column="created_by_user_id",
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
created_at = models.DateTimeField( created_at = models.DateTimeField(auto_now_add=True)
auto_now_add=True, updated_at = models.DateTimeField(auto_now=True)
)
updated_at = models.DateTimeField(
auto_now=True,
)
objects = RecipeManager() objects = RecipeManager()
@ -57,19 +56,22 @@ class RecipeStep(models.Model):
instructions = models.CharField( instructions = models.CharField(
verbose_name=_("step instructions"), verbose_name=_("step instructions"),
max_length=128, max_length=128,
help_text=_("the instructions for this step of the recipe. try to keep it clear and concise!"), help_text=_(
"the instructions for this step of the recipe. try to keep it clear and "
"concise!"
),
) )
order = models.IntegerField( order = models.IntegerField(
verbose_name=_("step number"), verbose_name=_("step number"),
default=0, default=0,
db_index=True, db_index=True,
help_text=_("which step in the recipe is this. this affects the order the recipe steps are shown."), help_text=_(
"which step in the recipe is this. this affects the order the recipe steps "
"are shown."
),
) )
recipe = models.ForeignKey( recipe = models.ForeignKey(
"Recipe", "Recipe", related_name="steps", db_index=True, on_delete=models.CASCADE
related_name="steps",
db_index=True,
on_delete=models.CASCADE,
) )
def __str__(self): def __str__(self):

View file

@ -1,10 +1,10 @@
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from moku.validators import validate_username_regex, validate_username_length from moku.validators import validate_username_length, validate_username_regex
def user_avatar_filename(instance, _): def user_avatar_filename(instance, _):
@ -21,7 +21,7 @@ class User(AbstractUser):
help_text=_( help_text=_(
"this is the unique identifier you'll use to log in. it may only contain " "this is the unique identifier you'll use to log in. it may only contain "
"letters, numbers, hyphens, dashes and dots." "letters, numbers, hyphens, dashes and dots."
) ),
) )
email = models.EmailField( email = models.EmailField(
verbose_name=_("email address"), verbose_name=_("email address"),
@ -30,12 +30,9 @@ class User(AbstractUser):
help_text=_( help_text=_(
"this should be your email address. make sure it's valid and that you have " "this should be your email address. make sure it's valid and that you have "
"access to it." "access to it."
),
) )
) email_confirmed_at = models.DateTimeField(blank=True, null=True)
email_confirmed_at = models.DateTimeField(
blank=True,
null=True,
)
pronouns = models.CharField( pronouns = models.CharField(
verbose_name=_("pronouns"), verbose_name=_("pronouns"),
max_length=64, max_length=64,
@ -82,9 +79,7 @@ class User(AbstractUser):
class UserSettings(models.Model): class UserSettings(models.Model):
user = models.OneToOneField( user = models.OneToOneField(
"User", "User", related_name="settings", on_delete=models.CASCADE
related_name="settings",
on_delete=models.CASCADE,
) )
language = models.CharField( language = models.CharField(
verbose_name=_("language"), verbose_name=_("language"),

View file

@ -1,8 +1,9 @@
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.views import LoginView as BaseLoginView, LogoutView as BaseLogoutView from django.contrib.auth.views import LoginView as BaseLoginView
from django.contrib.auth.views import LogoutView as BaseLogoutView
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.translation import gettext as _
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from moku.views.base import View from moku.views.base import View
@ -17,7 +18,11 @@ class LoginView(View, BaseLoginView):
def get_success_url(self): def get_success_url(self):
if self.request.user.is_authenticated: if self.request.user.is_authenticated:
messages.success(self.request, _("welcome back, %(username)s!") % {"username": self.request.user.username}) messages.success(
self.request,
_("welcome back, %(username)s!")
% {"username": self.request.user.username},
)
return self.request.GET.get("next", reverse_lazy("feed")) return self.request.GET.get("next", reverse_lazy("feed"))

View file

@ -7,7 +7,9 @@ class View(generic.TemplateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
return { return {
**super().get_context_data(**kwargs), **super().get_context_data(**kwargs),
"header_emoji": random.choice(["🍔", "🍕", "🍟", "🥪", "🥘", "🍰", "🍻", "🧁", "🍞", "🥯", "🥐"]) "header_emoji": random.choice(
["🍔", "🍕", "🍟", "🥪", "🥘", "🍰", "🍻", "🧁", "🍞", "🥯", "🥐"]
),
} }

View file

@ -23,8 +23,13 @@ class FeedView(FormView):
def form_valid(self, form): def form_valid(self, form):
if not self.request.user.is_authenticated: if not self.request.user.is_authenticated:
raise PermissionDenied raise PermissionDenied
if form.instance.recipe and form.instance.recipe.created_by.id != self.request.user.id: if (
messages.error(self.request, _("you can't add someone else's recipe to your post!")) form.instance.recipe
and form.instance.recipe.created_by.id != self.request.user.id
):
messages.error(
self.request, _("you can't add someone else's recipe to your post!")
)
return redirect("feed") return redirect("feed")
form.instance.created_by = self.request.user form.instance.created_by = self.request.user
if "image" in form.changed_data and form.instance.image is not None: if "image" in form.changed_data and form.instance.image is not None:
@ -36,7 +41,7 @@ class FeedView(FormView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
**super().get_context_data(**kwargs), **super().get_context_data(**kwargs),
"posts": Post.objects.all()[:128] "posts": Post.objects.all()[:128],
} }
if self.request.user.is_authenticated: if self.request.user.is_authenticated:
return self.get_authenticated_context_data(context) return self.get_authenticated_context_data(context)
@ -47,39 +52,54 @@ class FeedView(FormView):
**context, **context,
"emoji": EMOJI_CATEGORIES, "emoji": EMOJI_CATEGORIES,
"verbs": ( "verbs": (
(verb[0], verb[1] % {"user": f"@{self.request.user.username}", "food": "..."}) (
for verb in Verbs.CHOICES verb[0],
verb[1] % {"user": f"@{self.request.user.username}", "food": "..."},
) )
for verb in Verbs.CHOICES
),
} }
def get_form(self, form_class=None): def get_form(self, form_class=None):
form = super().get_form(form_class) form = super().get_form(form_class)
if self.request.user.is_authenticated: if self.request.user.is_authenticated:
form.fields["recipe"].queryset = Recipe.objects.filter(created_by=self.request.user) form.fields["recipe"].queryset = Recipe.objects.filter(
created_by=self.request.user
)
return form return form
class LatestPostJSONView(BaseView): class LatestPostJSONView(BaseView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
post = Post.objects.prefetch_related("recipe__steps") \ post = (
.filter(created_by__username=kwargs.get("username")) \ Post.objects.prefetch_related("recipe__steps")
.order_by("-created_at").first() .filter(created_by__username=kwargs.get("username"))
.order_by("-created_at")
.first()
)
if not post: if not post:
return HttpResponse(json.dumps({"post": None}), content_type="application/json") return HttpResponse(
json.dumps({"post": None}), content_type="application/json"
)
post_data = { post_data = {
"date": str(post.created_at), "date": str(post.created_at),
"text": post.get_verb_display() % {"user": f"@{post.created_by.username}", "food": post.food}, "text": post.get_verb_display()
% {"user": f"@{post.created_by.username}", "food": post.food},
"food": post.food, "food": post.food,
"verb": { "verb": {
"id": post.verb, "id": post.verb,
"pattern": post.get_verb_display() % {"user": "$1", "food": "$2"}, "pattern": post.get_verb_display() % {"user": "$1", "food": "$2"},
}, },
"image": f"{settings.SITE_ROOT_URL}{post.image.url}" if post.image else None, "image": f"{settings.SITE_ROOT_URL}{post.image.url}"
if post.image
else None,
"user": { "user": {
"username": post.created_by.username, "username": post.created_by.username,
"url": f"{settings.SITE_ROOT_URL}{post.created_by.get_absolute_url()}", "url": f"{settings.SITE_ROOT_URL}{post.created_by.get_absolute_url()}",
}, },
} }
if post.recipe: if post.recipe:
post_data["recipe"] = [step.instructions for step in post.recipe.steps.all()] post_data["recipe"] = [
step.instructions for step in post.recipe.steps.all()
]
return HttpResponse(json.dumps(post_data), content_type="application/json") return HttpResponse(json.dumps(post_data), content_type="application/json")

View file

@ -17,10 +17,7 @@ class DeleteRecipeView(LoginRequiredMixin, UserPassesTestMixin, View):
@cached_property @cached_property
def recipe(self): def recipe(self):
return get_object_or_404( return get_object_or_404(Recipe, uuid=self.kwargs.get("uuid"))
Recipe,
uuid=self.kwargs.get("uuid"),
)
def test_func(self): def test_func(self):
return self.request.user.id == self.recipe.created_by.id return self.request.user.id == self.recipe.created_by.id
@ -77,7 +74,9 @@ class IndexRecipeView(LoginRequiredMixin, View):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
return { return {
**super().get_context_data(**kwargs), **super().get_context_data(**kwargs),
"recipes": Recipe.objects.filter(created_by=self.request.user).order_by("-created_by"), "recipes": Recipe.objects.filter(created_by=self.request.user).order_by(
"-created_by"
),
} }
@ -88,7 +87,10 @@ class NewRecipeView(LoginRequiredMixin, FormView):
def form_valid(self, form): def form_valid(self, form):
form.instance.created_by = self.request.user form.instance.created_by = self.request.user
form.save() form.save()
messages.success(self.request, _("recipe made successfully! now you can start adding the steps.")) messages.success(
self.request,
_("recipe made successfully! now you can start adding the steps."),
)
return redirect(form.instance.get_absolute_url()) return redirect(form.instance.get_absolute_url())
@ -101,12 +103,17 @@ class ShowRecipeView(FormView):
return Recipe.objects.get(uuid=self.kwargs.get("uuid")) return Recipe.objects.get(uuid=self.kwargs.get("uuid"))
def form_valid(self, form): def form_valid(self, form):
if not self.request.user.is_authenticated or self.request.user.id != self.recipe.created_by.id: if (
not self.request.user.is_authenticated
or self.request.user.id != self.recipe.created_by.id
):
messages.error(self.request, _("that's not yours!")) messages.error(self.request, _("that's not yours!"))
return redirect(form.instance.get_absolute_url()) return redirect(form.instance.get_absolute_url())
order = self.recipe.steps.count() order = self.recipe.steps.count()
if order >= 16: if order >= 16:
messages.error(self.request, _("sorry! you can't add any more steps to this recipe.")) messages.error(
self.request, _("sorry! you can't add any more steps to this recipe.")
)
return redirect(self.recipe.get_absolute_url()) return redirect(self.recipe.get_absolute_url())
form.instance.recipe = self.recipe form.instance.recipe = self.recipe
form.instance.order = order form.instance.order = order
@ -115,7 +122,4 @@ class ShowRecipeView(FormView):
return redirect(self.recipe.get_absolute_url()) return redirect(self.recipe.get_absolute_url())
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
return { return {**super().get_context_data(**kwargs), "recipe": self.recipe}
**super().get_context_data(**kwargs),
"recipe": self.recipe,
}

View file

@ -4,8 +4,8 @@ from django.db import IntegrityError
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from moku.images import process_avatar_image
from moku.forms.user import ProfileForm, UserForm, UserSettingsForm from moku.forms.user import ProfileForm, UserForm, UserSettingsForm
from moku.images import process_avatar_image
from moku.models.user import User from moku.models.user import User
from moku.views.base import FormView, View from moku.views.base import FormView, View
@ -34,14 +34,18 @@ class EditSettingsView(LoginRequiredMixin, FormView):
try: try:
form.save() form.save()
except IntegrityError: except IntegrityError:
messages.error(self.request, _("uh oh. i think something went a little bit oopsie.")) messages.error(
self.request, _("uh oh. i think something went a little bit oopsie.")
)
return self.form_invalid(form) return self.form_invalid(form)
messages.success(self.request, _("settings updated!")) messages.success(self.request, _("settings updated!"))
return redirect("settings") return redirect("settings")
def get_form(self): def get_form(self):
if hasattr(self.request.user, "settings"): if hasattr(self.request.user, "settings"):
return self.form_class(instance=self.request.user.settings, **self.get_form_kwargs()) return self.form_class(
instance=self.request.user.settings, **self.get_form_kwargs()
)
return super().get_form() return super().get_form()
@ -66,9 +70,13 @@ class SignupView(FormView):
try: try:
form.save() form.save()
except IntegrityError: except IntegrityError:
messages.error(self.request, _("sorry! someone else got to that username first.")) messages.error(
self.request, _("sorry! someone else got to that username first.")
)
return self.form_invalid(form) return self.form_invalid(form)
messages.success(self.request, _("that's it! just log in, and you're ready to go.")) messages.success(
self.request, _("that's it! just log in, and you're ready to go.")
)
return redirect("login") return redirect("login")
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):