diff --git a/moku/admin.py b/moku/admin.py index df991d0..6df6978 100644 --- a/moku/admin.py +++ b/moku/admin.py @@ -3,7 +3,6 @@ from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from moku import models - for model_name in models.__all__: model = getattr(models, model_name) if model.__name__ != "User": @@ -14,32 +13,11 @@ for model_name in models.__all__: class UserAdmin(BaseUserAdmin): fieldsets = ( (None, {"fields": ("username", "email", "password")}), - ( - "Profile", - { - "fields": ( - "pronouns", "location", "bio" - ), - }, - ), - ( - "Status", - { - "fields": ( - "email_confirmed_at", - ) - }, - ), + ("Profile", {"fields": ("pronouns", "location", "bio")}), + ("Status", {"fields": ("email_confirmed_at",)}), ( "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")}), ) diff --git a/moku/config/settings.py b/moku/config/settings.py index b4aeab3..07dfaed 100644 --- a/moku/config/settings.py +++ b/moku/config/settings.py @@ -1,4 +1,3 @@ -import sys from pathlib import Path import environ @@ -71,9 +70,7 @@ TEMPLATES = [ "django.template.context_processors.tz", "django.contrib.messages.context_processors.messages", ], - "filters": { - "unemoji": "moku.filters.unemoji", - }, + "filters": {"unemoji": "moku.filters.unemoji"}, "policies": {"ext.i18n.trimmed": True}, }, }, diff --git a/moku/config/urls.py b/moku/config/urls.py index 277d3d9..c14b236 100644 --- a/moku/config/urls.py +++ b/moku/config/urls.py @@ -14,6 +14,7 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ + from django.conf import settings from django.conf.urls.static import static from django.contrib import admin @@ -50,7 +51,11 @@ urlpatterns = [ path("recipes/", ShowRecipeView.as_view(), name="recipe.show"), path("recipes//delete", DeleteRecipeView.as_view(), name="recipe.delete"), path("recipes//", EditStepView.as_view(), name="step.edit"), - path("recipes///delete", DeleteStepView.as_view(), name="step.delete"), + path( + "recipes///delete", + DeleteStepView.as_view(), + name="step.delete", + ), ] if settings.DEBUG_TOOLBAR: diff --git a/moku/constants.py b/moku/constants.py index 5ad305c..02414ab 100644 --- a/moku/constants.py +++ b/moku/constants.py @@ -22,53 +22,228 @@ EMOJI_CATEGORIES = [ ( _("fruit & veg"), ( - "๐Ÿ", "๐ŸŽ", "๐Ÿ", "๐ŸŠ", "๐Ÿ‹", "๐ŸŒ", "๐Ÿ‰", "๐Ÿ‡", "๐Ÿ“", "๐Ÿซ", "๐Ÿˆ", "๐Ÿ’", "๐Ÿ‘", "๐Ÿฅญ", "๐Ÿ", - "๐Ÿฅฅ", "๐Ÿฅ", "๐Ÿ…", "๐Ÿ†", "๐Ÿฅ‘", "๐Ÿซ›", "๐Ÿฅฆ", "๐Ÿฅฌ", "๐Ÿฅ’", "๐ŸŒถ๏ธ", "๐Ÿซ‘", "๐ŸŒฝ", "๐Ÿฅ•", "๐Ÿซ’", "๐Ÿง„", - "๐Ÿง…", "๐Ÿฅ”", "๐Ÿ ", "๐Ÿซš", + "๐Ÿ", + "๐ŸŽ", + "๐Ÿ", + "๐ŸŠ", + "๐Ÿ‹", + "๐ŸŒ", + "๐Ÿ‰", + "๐Ÿ‡", + "๐Ÿ“", + "๐Ÿซ", + "๐Ÿˆ", + "๐Ÿ’", + "๐Ÿ‘", + "๐Ÿฅญ", + "๐Ÿ", + "๐Ÿฅฅ", + "๐Ÿฅ", + "๐Ÿ…", + "๐Ÿ†", + "๐Ÿฅ‘", + "๐Ÿซ›", + "๐Ÿฅฆ", + "๐Ÿฅฌ", + "๐Ÿฅ’", + "๐ŸŒถ๏ธ", + "๐Ÿซ‘", + "๐ŸŒฝ", + "๐Ÿฅ•", + "๐Ÿซ’", + "๐Ÿง„", + "๐Ÿง…", + "๐Ÿฅ”", + "๐Ÿ ", + "๐Ÿซš", ), ), ( _("savoury dishes"), ( - "๐Ÿฅฏ", "๐Ÿž", "๐Ÿฅ–", "๐Ÿฅจ", "๐Ÿง€", "๐Ÿฅš", "๐Ÿณ", "๐Ÿงˆ", "๐Ÿฅž", "๐Ÿง‡", "๐Ÿฅ“", "๐Ÿฅฉ", "๐Ÿ—", "๐Ÿ–", "๐Ÿฆด", - "๐ŸŒญ", "๐Ÿ”", "๐ŸŸ", "๐Ÿ•", "๐Ÿซ“", "๐Ÿฅช", "๐Ÿฅ™", "๐Ÿง†", "๐ŸŒฎ", "๐ŸŒฏ", "๐Ÿซ”", "๐Ÿฅ—", "๐Ÿฅ˜", "๐Ÿซ•", "๐Ÿฅซ", - "๐Ÿซ™", "๐Ÿ", "๐Ÿœ", "๐Ÿฒ", "๐Ÿ›", "๐Ÿฃ", "๐Ÿฑ", "๐ŸฅŸ", "๐Ÿฆช", "๐Ÿค", "๐Ÿ™", "๐Ÿš", "๐Ÿ˜", "๐Ÿฅ", "๐ŸŒฐ", - "๐Ÿฅœ", "๐Ÿซ˜", "๐ŸงŠ", + "๐Ÿฅฏ", + "๐Ÿž", + "๐Ÿฅ–", + "๐Ÿฅจ", + "๐Ÿง€", + "๐Ÿฅš", + "๐Ÿณ", + "๐Ÿงˆ", + "๐Ÿฅž", + "๐Ÿง‡", + "๐Ÿฅ“", + "๐Ÿฅฉ", + "๐Ÿ—", + "๐Ÿ–", + "๐Ÿฆด", + "๐ŸŒญ", + "๐Ÿ”", + "๐ŸŸ", + "๐Ÿ•", + "๐Ÿซ“", + "๐Ÿฅช", + "๐Ÿฅ™", + "๐Ÿง†", + "๐ŸŒฎ", + "๐ŸŒฏ", + "๐Ÿซ”", + "๐Ÿฅ—", + "๐Ÿฅ˜", + "๐Ÿซ•", + "๐Ÿฅซ", + "๐Ÿซ™", + "๐Ÿ", + "๐Ÿœ", + "๐Ÿฒ", + "๐Ÿ›", + "๐Ÿฃ", + "๐Ÿฑ", + "๐ŸฅŸ", + "๐Ÿฆช", + "๐Ÿค", + "๐Ÿ™", + "๐Ÿš", + "๐Ÿ˜", + "๐Ÿฅ", + "๐ŸŒฐ", + "๐Ÿฅœ", + "๐Ÿซ˜", + "๐ŸงŠ", ), ), ( _("sweet treats"), ( - "๐Ÿฅ ", "๐Ÿฅฎ", "๐Ÿข", "๐Ÿก", "๐Ÿง", "๐Ÿจ", "๐Ÿฆ", "๐Ÿฅง", "๐Ÿง", "๐Ÿฐ", "๐ŸŽ‚", "๐Ÿฎ", "๐Ÿญ", "๐Ÿฌ", "๐Ÿซ", - "๐Ÿฅ", "๐Ÿฟ", "๐Ÿฉ", "๐Ÿช", "๐Ÿฏ", + "๐Ÿฅ ", + "๐Ÿฅฎ", + "๐Ÿข", + "๐Ÿก", + "๐Ÿง", + "๐Ÿจ", + "๐Ÿฆ", + "๐Ÿฅง", + "๐Ÿง", + "๐Ÿฐ", + "๐ŸŽ‚", + "๐Ÿฎ", + "๐Ÿญ", + "๐Ÿฌ", + "๐Ÿซ", + "๐Ÿฅ", + "๐Ÿฟ", + "๐Ÿฉ", + "๐Ÿช", + "๐Ÿฏ", ), ), ( _("drinks"), ( - "๐Ÿฅ›", "๐Ÿซ—", "๐Ÿผ", "๐Ÿซ–", "โ˜•๏ธ", "๐Ÿต", "๐Ÿงƒ", "๐Ÿฅค", "๐Ÿง‹", "๐Ÿถ", "๐Ÿบ", "๐Ÿป", "๐Ÿฅ‚", "๐Ÿท", "๐Ÿฅƒ", - "๐Ÿธ", "๐Ÿน", "๐Ÿง‰", "๐Ÿพ", + "๐Ÿฅ›", + "๐Ÿซ—", + "๐Ÿผ", + "๐Ÿซ–", + "โ˜•๏ธ", + "๐Ÿต", + "๐Ÿงƒ", + "๐Ÿฅค", + "๐Ÿง‹", + "๐Ÿถ", + "๐Ÿบ", + "๐Ÿป", + "๐Ÿฅ‚", + "๐Ÿท", + "๐Ÿฅƒ", + "๐Ÿธ", + "๐Ÿน", + "๐Ÿง‰", + "๐Ÿพ", ), ), ( _("people"), ( - "๐Ÿ˜€", "๐Ÿ˜ƒ", "๐Ÿ˜„", "๐Ÿ˜", "๐Ÿ˜†", "๐Ÿฅน", "๐Ÿ˜…", "๐Ÿ˜‚", "๐Ÿคฃ", "๐Ÿฅฒ", "๐Ÿ˜Š", "๐Ÿ˜‡", "๐Ÿ™‚", "๐Ÿ™ƒ", "๐Ÿ˜‰", - "๐Ÿ˜Œ", "๐Ÿ˜Œ", "๐Ÿ˜", "๐Ÿฅฐ", "๐Ÿ˜˜", "๐Ÿ˜—", "๐Ÿ˜™", "๐Ÿ˜š", "๐Ÿ˜‹", "๐Ÿ˜›", "๐Ÿ˜", "๐Ÿ˜œ", "๐Ÿคช", "๐Ÿคจ", "๐Ÿง", + "๐Ÿ˜€", + "๐Ÿ˜ƒ", + "๐Ÿ˜„", + "๐Ÿ˜", + "๐Ÿ˜†", + "๐Ÿฅน", + "๐Ÿ˜…", + "๐Ÿ˜‚", + "๐Ÿคฃ", + "๐Ÿฅฒ", + "๐Ÿ˜Š", + "๐Ÿ˜‡", + "๐Ÿ™‚", + "๐Ÿ™ƒ", + "๐Ÿ˜‰", + "๐Ÿ˜Œ", + "๐Ÿ˜Œ", + "๐Ÿ˜", + "๐Ÿฅฐ", + "๐Ÿ˜˜", + "๐Ÿ˜—", + "๐Ÿ˜™", + "๐Ÿ˜š", + "๐Ÿ˜‹", + "๐Ÿ˜›", + "๐Ÿ˜", + "๐Ÿ˜œ", + "๐Ÿคช", + "๐Ÿคจ", + "๐Ÿง", ), ), ( _("animals"), ( - "๐Ÿถ", "๐Ÿฑ", "๐Ÿญ", "๐Ÿน", "๐Ÿฐ", "๐ŸฆŠ", "๐Ÿป", "๐Ÿผ", "๐Ÿจ", "๐Ÿฏ", "๐Ÿฆ", "๐Ÿฎ", "๐Ÿท", "๐Ÿฝ", "๐Ÿธ", - "๐Ÿต", "๐Ÿ™ˆ", "๐Ÿ™‰", "๐Ÿ™Š", "๐Ÿ’", "๐Ÿ”", "๐Ÿง", "๐Ÿฆ", "๐Ÿค", "๐Ÿฃ", "๐Ÿฅ", "๐Ÿชฟ", "๐Ÿฆ†", "๐Ÿฆโ€โฌ›", "๐Ÿฆ…", - "๐Ÿฆ‰", "๐Ÿฆ‡", "๐Ÿบ", "๐Ÿ—", "๐Ÿด", "๐Ÿฆ„", "๐ŸซŽ", "๐Ÿ", "๐Ÿชฑ", "๐Ÿ›", "๐Ÿฆ‹", "๐ŸŒ", "๐Ÿž", "๐Ÿœ", "๐Ÿชฐ", + "๐Ÿถ", + "๐Ÿฑ", + "๐Ÿญ", + "๐Ÿน", + "๐Ÿฐ", + "๐ŸฆŠ", + "๐Ÿป", + "๐Ÿผ", + "๐Ÿจ", + "๐Ÿฏ", + "๐Ÿฆ", + "๐Ÿฎ", + "๐Ÿท", + "๐Ÿฝ", + "๐Ÿธ", + "๐Ÿต", + "๐Ÿ™ˆ", + "๐Ÿ™‰", + "๐Ÿ™Š", + "๐Ÿ’", + "๐Ÿ”", + "๐Ÿง", + "๐Ÿฆ", + "๐Ÿค", + "๐Ÿฃ", + "๐Ÿฅ", + "๐Ÿชฟ", + "๐Ÿฆ†", + "๐Ÿฆโ€โฌ›", + "๐Ÿฆ…", + "๐Ÿฆ‰", + "๐Ÿฆ‡", + "๐Ÿบ", + "๐Ÿ—", + "๐Ÿด", + "๐Ÿฆ„", + "๐ŸซŽ", + "๐Ÿ", + "๐Ÿชฑ", + "๐Ÿ›", + "๐Ÿฆ‹", + "๐ŸŒ", + "๐Ÿž", + "๐Ÿœ", + "๐Ÿชฐ", ), ), - ( - _("tools & things"), - ( - "๐Ÿฅ„", "๐Ÿด", "๐Ÿฝ๏ธ", "๐Ÿฅฃ", "๐Ÿฅก", "๐Ÿฅข", "๐Ÿง‚", "๐Ÿ”ช", "๐Ÿช“", - ) - ) + (_("tools & things"), ("๐Ÿฅ„", "๐Ÿด", "๐Ÿฝ๏ธ", "๐Ÿฅฃ", "๐Ÿฅก", "๐Ÿฅข", "๐Ÿง‚", "๐Ÿ”ช", "๐Ÿช“")), ] diff --git a/moku/forms/recipe.py b/moku/forms/recipe.py index c90e56d..f327ab9 100644 --- a/moku/forms/recipe.py +++ b/moku/forms/recipe.py @@ -1,4 +1,4 @@ -from django.forms import Form, ModelForm +from django.forms import ModelForm from django.utils.translation import gettext_lazy as _ from moku.models.recipe import Recipe, RecipeStep @@ -8,9 +8,7 @@ class RecipeForm(ModelForm): class Meta: model = Recipe fields = ("title",) - labels = { - "title": _("recipe title"), - } + labels = {"title": _("recipe title")} class RecipeStepForm(ModelForm): diff --git a/moku/forms/user.py b/moku/forms/user.py index 4a3f0f8..3aeb758 100644 --- a/moku/forms/user.py +++ b/moku/forms/user.py @@ -1,7 +1,6 @@ from django import forms from django.contrib.auth.forms import UserCreationForm from django.utils.translation import gettext_lazy as _ - from django_recaptcha.fields import ReCaptchaField from moku.models.user import User, UserSettings @@ -14,10 +13,7 @@ class UserForm(UserCreationForm): class Meta(UserCreationForm.Meta): model = User fields = ("username", "email", "password1", "password2") - labels = { - "username": _("username"), - "email": _("email address"), - } + labels = {"username": _("username"), "email": _("email address")} help_texts = { "username": User._meta.get_field("username").help_text, "email": User._meta.get_field("email").help_text, @@ -26,10 +22,10 @@ class UserForm(UserCreationForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) 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 = { - "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: model = UserSettings fields = ("language",) - labels = { - "language": _("language"), - } + labels = {"language": _("language")} class ProfileForm(forms.ModelForm): diff --git a/moku/migrations/0001_initial.py b/moku/migrations/0001_initial.py index f8bb8de..df0e511 100644 --- a/moku/migrations/0001_initial.py +++ b/moku/migrations/0001_initial.py @@ -1,49 +1,162 @@ +# ruff: noqa: E501 # Generated by Django 5.0.3 on 2024-03-24 17:24 +import re + import django.contrib.auth.models import django.core.validators import django.utils.timezone -import moku.validators -import re from django.db import migrations, models +import moku.validators + class Migration(migrations.Migration): - initial = True - dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), - ] + dependencies = [("auth", "0012_alter_user_first_name_max_length")] operations = [ migrations.CreateModel( - name='User', + name="User", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('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')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("password", models.CharField(max_length=128, verbose_name="password")), + ( + "last_login", + models.DateTimeField( + blank=True, null=True, verbose_name="last login" + ), + ), + ( + "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={ - 'verbose_name': 'user', - 'verbose_name_plural': 'users', - 'abstract': False, + "verbose_name": "user", + "verbose_name_plural": "users", + "abstract": False, }, - managers=[ - ('objects', django.contrib.auth.models.UserManager()), - ], - ), + managers=[("objects", django.contrib.auth.models.UserManager())], + ) ] diff --git a/moku/migrations/0002_post.py b/moku/migrations/0002_post.py index c938cea..25fc6ed 100644 --- a/moku/migrations/0002_post.py +++ b/moku/migrations/0002_post.py @@ -1,32 +1,104 @@ +# ruff: noqa: E501 # Generated by Django 5.0.3 on 2024-03-25 10:04 import django.db.models.deletion -import moku.models.post -import moku.validators import shortuuid.django_fields from django.conf import settings from django.db import migrations, models +import moku.models.post +import moku.validators + class Migration(migrations.Migration): - - dependencies = [ - ('moku', '0001_initial'), - ] + dependencies = [("moku", "0001_initial")] operations = [ migrations.CreateModel( - name='Post', + name="Post", 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')), - ('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)), + ( + "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", + ), + ), + ( + "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, + ), + ), ], - ), + ) ] diff --git a/moku/migrations/0003_user_avatar.py b/moku/migrations/0003_user_avatar.py index fd75b9c..f05088d 100644 --- a/moku/migrations/0003_user_avatar.py +++ b/moku/migrations/0003_user_avatar.py @@ -1,19 +1,23 @@ +# ruff: noqa: E501 # Generated by Django 5.0.3 on 2024-03-25 13:49 -import moku.models.user from django.db import migrations, models +import moku.models.user + class Migration(migrations.Migration): - - dependencies = [ - ('moku', '0002_post'), - ] + dependencies = [("moku", "0002_post")] operations = [ migrations.AddField( - model_name='user', - 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'), - ), + model_name="user", + 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", + ), + ) ] diff --git a/moku/migrations/0004_alter_post_verb.py b/moku/migrations/0004_alter_post_verb.py index a8b64ec..bef0495 100644 --- a/moku/migrations/0004_alter_post_verb.py +++ b/moku/migrations/0004_alter_post_verb.py @@ -1,18 +1,28 @@ +# ruff: noqa: E501 # Generated by Django 5.0.3 on 2024-03-25 15:34 from django.db import migrations, models class Migration(migrations.Migration): - - dependencies = [ - ('moku', '0003_user_avatar'), - ] + dependencies = [("moku", "0003_user_avatar")] operations = [ migrations.AlterField( - model_name='post', - 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'), - ), + model_name="post", + 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", + ), + ) ] diff --git a/moku/migrations/0005_usersettings.py b/moku/migrations/0005_usersettings.py index 65bc607..462a45d 100644 --- a/moku/migrations/0005_usersettings.py +++ b/moku/migrations/0005_usersettings.py @@ -1,3 +1,4 @@ +# ruff: noqa: E501 # Generated by Django 5.0.3 on 2024-03-25 17:02 import django.db.models.deletion @@ -6,18 +7,139 @@ from django.db import migrations, models class Migration(migrations.Migration): - - dependencies = [ - ('moku', '0004_alter_post_verb'), - ] + dependencies = [("moku", "0004_alter_post_verb")] operations = [ migrations.CreateModel( - name='UserSettings', + name="UserSettings", 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')), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='settings', to=settings.AUTH_USER_MODEL)), + ( + "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", + ), + ), + ( + "user", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name="settings", + to=settings.AUTH_USER_MODEL, + ), + ), ], - ), + ) ] diff --git a/moku/migrations/0006_recipe_post_recipe_recipestep.py b/moku/migrations/0006_recipe_post_recipe_recipestep.py index 8a8a406..7f023da 100644 --- a/moku/migrations/0006_recipe_post_recipe_recipestep.py +++ b/moku/migrations/0006_recipe_post_recipe_recipestep.py @@ -1,3 +1,4 @@ +# ruff: noqa: E501 # Generated by Django 5.0.3 on 2024-03-25 21:09 import django.db.models.deletion @@ -7,36 +8,114 @@ from django.db import migrations, models class Migration(migrations.Migration): - - dependencies = [ - ('moku', '0005_usersettings'), - ] + dependencies = [("moku", "0005_usersettings")] operations = [ migrations.CreateModel( - name='Recipe', + name="Recipe", 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')), - ('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)), + ( + "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", + ), + ), + ( + "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( - model_name='post', - 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'), + model_name="post", + 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( - name='RecipeStep', + name="RecipeStep", 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')), - ('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')), + ( + "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", + ), + ), + ( + "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", + ), + ), ], ), ] diff --git a/moku/models/__init__.py b/moku/models/__init__.py index f94d6c2..e27b18e 100644 --- a/moku/models/__init__.py +++ b/moku/models/__init__.py @@ -2,11 +2,4 @@ from moku.models.post import Post from moku.models.recipe import Recipe, RecipeStep from moku.models.user import User, UserSettings - -__all__ = [ - "Post", - "Recipe", - "RecipeStep", - "User", - "UserSettings", -] +__all__ = ["Post", "Recipe", "RecipeStep", "User", "UserSettings"] diff --git a/moku/models/post.py b/moku/models/post.py index 88771e9..0f78ea0 100644 --- a/moku/models/post.py +++ b/moku/models/post.py @@ -14,11 +14,17 @@ def post_image_filename(instance, _): class PostManager(models.Manager): def get_queryset(self): - return super().get_queryset().select_related("created_by") \ + return ( + super() + .get_queryset() + .select_related("created_by") .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") + ) class Post(models.Model): @@ -41,9 +47,7 @@ class Post(models.Model): help_text=_("how should we best phrase this entry?"), ) food = models.CharField( - verbose_name=_("food"), - max_length=128, - help_text=_("what did you eat?"), + verbose_name=_("food"), max_length=128, help_text=_("what did you eat?") ) image = models.ImageField( verbose_name=_("image"), @@ -68,12 +72,10 @@ class Post(models.Model): on_delete=models.CASCADE, ) created_at = models.DateTimeField( - auto_now_add=True, - help_text=_("when this post was created."), + 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."), + auto_now=True, help_text=_("when this post was last updated.") ) objects = PostManager() @@ -84,6 +86,9 @@ class Post(models.Model): @property def text(self): return self.get_verb_display() % { - "user": f"@{self.created_by.username}", + "user": ( + f'' + f"@{self.created_by.username}" + ), "food": escape(self.food), } diff --git a/moku/models/recipe.py b/moku/models/recipe.py index 00ef78f..77c133b 100644 --- a/moku/models/recipe.py +++ b/moku/models/recipe.py @@ -1,15 +1,18 @@ from django.db import models -from django.utils.translation import gettext_lazy as _ from django.urls import reverse +from django.utils.translation import gettext_lazy as _ from shortuuid.django_fields import ShortUUIDField class RecipeManager(models.Manager): def get_queryset(self): - return super().get_queryset() \ + return ( + super() + .get_queryset() .prefetch_related( models.Prefetch("steps", queryset=RecipeStep.objects.order_by("order")) ) + ) class Recipe(models.Model): @@ -31,12 +34,8 @@ class Recipe(models.Model): db_column="created_by_user_id", on_delete=models.CASCADE, ) - created_at = models.DateTimeField( - auto_now_add=True, - ) - updated_at = models.DateTimeField( - auto_now=True, - ) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) objects = RecipeManager() @@ -57,19 +56,22 @@ class RecipeStep(models.Model): instructions = models.CharField( verbose_name=_("step instructions"), 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( verbose_name=_("step number"), default=0, 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", - related_name="steps", - db_index=True, - on_delete=models.CASCADE, + "Recipe", related_name="steps", db_index=True, on_delete=models.CASCADE ) def __str__(self): diff --git a/moku/models/user.py b/moku/models/user.py index dcef0ae..29a4450 100644 --- a/moku/models/user.py +++ b/moku/models/user.py @@ -1,10 +1,10 @@ from django.conf import settings from django.contrib.auth.models import AbstractUser from django.db import models -from django.utils.translation import gettext_lazy as _ 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, _): @@ -21,7 +21,7 @@ class User(AbstractUser): help_text=_( "this is the unique identifier you'll use to log in. it may only contain " "letters, numbers, hyphens, dashes and dots." - ) + ), ) email = models.EmailField( verbose_name=_("email address"), @@ -30,12 +30,9 @@ class User(AbstractUser): help_text=_( "this should be your email address. make sure it's valid and that you have " "access to it." - ) - ) - email_confirmed_at = models.DateTimeField( - blank=True, - null=True, + ), ) + email_confirmed_at = models.DateTimeField(blank=True, null=True) pronouns = models.CharField( verbose_name=_("pronouns"), max_length=64, @@ -82,9 +79,7 @@ class User(AbstractUser): class UserSettings(models.Model): user = models.OneToOneField( - "User", - related_name="settings", - on_delete=models.CASCADE, + "User", related_name="settings", on_delete=models.CASCADE ) language = models.CharField( verbose_name=_("language"), diff --git a/moku/views/auth.py b/moku/views/auth.py index 5ca4202..b6c04e3 100644 --- a/moku/views/auth.py +++ b/moku/views/auth.py @@ -1,8 +1,9 @@ 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.utils.translation import gettext as _ from django.urls import reverse_lazy +from django.utils.translation import gettext as _ from moku.views.base import View @@ -17,7 +18,11 @@ class LoginView(View, BaseLoginView): def get_success_url(self): 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")) diff --git a/moku/views/base.py b/moku/views/base.py index c9c352b..6a3c3c5 100644 --- a/moku/views/base.py +++ b/moku/views/base.py @@ -7,7 +7,9 @@ class View(generic.TemplateView): def get_context_data(self, **kwargs): return { **super().get_context_data(**kwargs), - "header_emoji": random.choice(["๐Ÿ”", "๐Ÿ•", "๐ŸŸ", "๐Ÿฅช", "๐Ÿฅ˜", "๐Ÿฐ", "๐Ÿป", "๐Ÿง", "๐Ÿž", "๐Ÿฅฏ", "๐Ÿฅ"]) + "header_emoji": random.choice( + ["๐Ÿ”", "๐Ÿ•", "๐ŸŸ", "๐Ÿฅช", "๐Ÿฅ˜", "๐Ÿฐ", "๐Ÿป", "๐Ÿง", "๐Ÿž", "๐Ÿฅฏ", "๐Ÿฅ"] + ), } diff --git a/moku/views/post.py b/moku/views/post.py index e0e0d86..022fb8e 100644 --- a/moku/views/post.py +++ b/moku/views/post.py @@ -23,8 +23,13 @@ class FeedView(FormView): def form_valid(self, form): if not self.request.user.is_authenticated: raise PermissionDenied - if 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!")) + if ( + 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") form.instance.created_by = self.request.user 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): context = { **super().get_context_data(**kwargs), - "posts": Post.objects.all()[:128] + "posts": Post.objects.all()[:128], } if self.request.user.is_authenticated: return self.get_authenticated_context_data(context) @@ -47,39 +52,54 @@ class FeedView(FormView): **context, "emoji": EMOJI_CATEGORIES, "verbs": ( - (verb[0], verb[1] % {"user": f"@{self.request.user.username}", "food": "..."}) + ( + verb[0], + verb[1] % {"user": f"@{self.request.user.username}", "food": "..."}, + ) for verb in Verbs.CHOICES - ) + ), } def get_form(self, form_class=None): form = super().get_form(form_class) 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 class LatestPostJSONView(BaseView): def get(self, request, *args, **kwargs): - post = Post.objects.prefetch_related("recipe__steps") \ - .filter(created_by__username=kwargs.get("username")) \ - .order_by("-created_at").first() + post = ( + Post.objects.prefetch_related("recipe__steps") + .filter(created_by__username=kwargs.get("username")) + .order_by("-created_at") + .first() + ) 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 = { "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, "verb": { "id": post.verb, "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": { "username": post.created_by.username, "url": f"{settings.SITE_ROOT_URL}{post.created_by.get_absolute_url()}", }, } 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") diff --git a/moku/views/recipe.py b/moku/views/recipe.py index 97fa80b..b056491 100644 --- a/moku/views/recipe.py +++ b/moku/views/recipe.py @@ -17,10 +17,7 @@ class DeleteRecipeView(LoginRequiredMixin, UserPassesTestMixin, View): @cached_property def recipe(self): - return get_object_or_404( - Recipe, - uuid=self.kwargs.get("uuid"), - ) + return get_object_or_404(Recipe, uuid=self.kwargs.get("uuid")) def test_func(self): return self.request.user.id == self.recipe.created_by.id @@ -77,7 +74,9 @@ class IndexRecipeView(LoginRequiredMixin, View): def get_context_data(self, **kwargs): return { **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): form.instance.created_by = self.request.user 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()) @@ -101,12 +103,17 @@ class ShowRecipeView(FormView): return Recipe.objects.get(uuid=self.kwargs.get("uuid")) 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!")) return redirect(form.instance.get_absolute_url()) order = self.recipe.steps.count() 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()) form.instance.recipe = self.recipe form.instance.order = order @@ -115,7 +122,4 @@ class ShowRecipeView(FormView): return redirect(self.recipe.get_absolute_url()) def get_context_data(self, **kwargs): - return { - **super().get_context_data(**kwargs), - "recipe": self.recipe, - } + return {**super().get_context_data(**kwargs), "recipe": self.recipe} diff --git a/moku/views/user.py b/moku/views/user.py index e43e847..6e215ce 100644 --- a/moku/views/user.py +++ b/moku/views/user.py @@ -4,8 +4,8 @@ from django.db import IntegrityError from django.shortcuts import redirect from django.utils.translation import gettext as _ -from moku.images import process_avatar_image from moku.forms.user import ProfileForm, UserForm, UserSettingsForm +from moku.images import process_avatar_image from moku.models.user import User from moku.views.base import FormView, View @@ -34,14 +34,18 @@ class EditSettingsView(LoginRequiredMixin, FormView): try: form.save() 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) messages.success(self.request, _("settings updated!")) return redirect("settings") def get_form(self): 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() @@ -66,9 +70,13 @@ class SignupView(FormView): try: form.save() 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) - 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") def get(self, request, *args, **kwargs):