style: 💭 update docstring comments across project
This commit is contained in:
parent
a4f8275383
commit
2187af7b10
22 changed files with 104 additions and 35 deletions
|
|
@ -11,6 +11,8 @@ for model_name in models.__all__:
|
||||||
|
|
||||||
@admin.register(models.User)
|
@admin.register(models.User)
|
||||||
class UserAdmin(BaseUserAdmin):
|
class UserAdmin(BaseUserAdmin):
|
||||||
|
"""Admin class override for the User model."""
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, {"fields": ("username", "email", "password")}),
|
(None, {"fields": ("username", "email", "password")}),
|
||||||
("Profile", {"fields": ("pronouns", "location", "bio")}),
|
("Profile", {"fields": ("pronouns", "location", "bio")}),
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class MokuConfig(AppConfig):
|
class MokuConfig(AppConfig):
|
||||||
|
"""Django application configuration for moku.blog."""
|
||||||
|
|
||||||
name = "moku"
|
name = "moku"
|
||||||
label = "moku"
|
label = "moku"
|
||||||
verbose_name = "moku.blog"
|
verbose_name = "moku.blog"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,3 @@
|
||||||
"""
|
|
||||||
ASGI config for moku project.
|
|
||||||
|
|
||||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.core.asgi import get_asgi_application
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
@ -14,3 +5,7 @@ from django.core.asgi import get_asgi_application
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "moku.config.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "moku.config.settings")
|
||||||
|
|
||||||
application = get_asgi_application()
|
application = get_asgi_application()
|
||||||
|
"""
|
||||||
|
ASGI application for moku.blog.
|
||||||
|
More information: https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,3 @@
|
||||||
"""
|
|
||||||
URL configuration for moku project.
|
|
||||||
|
|
||||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
|
||||||
https://docs.djangoproject.com/en/5.0/topics/http/urls/
|
|
||||||
Examples:
|
|
||||||
Function views
|
|
||||||
1. Add an import: from my_app import views
|
|
||||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
|
||||||
Class-based views
|
|
||||||
1. Add an import: from other_app.views import Home
|
|
||||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
|
||||||
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 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
|
||||||
|
|
@ -57,6 +40,10 @@ urlpatterns = [
|
||||||
name="step.delete",
|
name="step.delete",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
"""
|
||||||
|
URL patterns, defining the routes available in moku.blog.
|
||||||
|
More information: https://docs.djangoproject.com/en/5.0/topics/http/urls/
|
||||||
|
"""
|
||||||
|
|
||||||
if settings.DEBUG_TOOLBAR:
|
if settings.DEBUG_TOOLBAR:
|
||||||
urlpatterns += [path("__debug__/", include("debug_toolbar.urls"))]
|
urlpatterns += [path("__debug__/", include("debug_toolbar.urls"))]
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,3 @@
|
||||||
"""
|
|
||||||
WSGI config for moku project.
|
|
||||||
|
|
||||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
@ -14,3 +5,7 @@ from django.core.wsgi import get_wsgi_application
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "moku.config.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "moku.config.settings")
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
|
"""
|
||||||
|
WSGI application for moku.blog.
|
||||||
|
More information: https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class Verbs:
|
class Verbs:
|
||||||
|
"""Defines choices of possible verbs in posts."""
|
||||||
|
|
||||||
ATE = "ate"
|
ATE = "ate"
|
||||||
DRANK = "drank"
|
DRANK = "drank"
|
||||||
MADE = "made"
|
MADE = "made"
|
||||||
|
|
@ -247,3 +249,4 @@ EMOJI_CATEGORIES = [
|
||||||
),
|
),
|
||||||
(_("tools & things"), ("🥄", "🍴", "🍽️", "🥣", "🥡", "🥢", "🧂", "🔪", "🪓")),
|
(_("tools & things"), ("🥄", "🍴", "🍽️", "🥣", "🥡", "🥢", "🧂", "🔪", "🪓")),
|
||||||
]
|
]
|
||||||
|
"""Defines emoji that are available in the emoji picker widget."""
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,5 @@ from emoji import demojize
|
||||||
|
|
||||||
|
|
||||||
def unemoji(txt: str):
|
def unemoji(txt: str):
|
||||||
|
"""Turn emoji in the given string into plain text."""
|
||||||
return demojize(txt, delimiters=("", ""))
|
return demojize(txt, delimiters=("", ""))
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ from moku.models import Post
|
||||||
|
|
||||||
|
|
||||||
class PostForm(ModelForm):
|
class PostForm(ModelForm):
|
||||||
|
"""Form for creating and updating posts."""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Post
|
model = Post
|
||||||
fields = ("emoji", "verb", "food", "recipe", "image")
|
fields = ("emoji", "verb", "food", "recipe", "image")
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ from moku.models.recipe import Recipe, RecipeStep
|
||||||
|
|
||||||
|
|
||||||
class RecipeForm(ModelForm):
|
class RecipeForm(ModelForm):
|
||||||
|
"""Form for creating and updating recipes."""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Recipe
|
model = Recipe
|
||||||
fields = ("title",)
|
fields = ("title",)
|
||||||
|
|
@ -12,6 +14,8 @@ class RecipeForm(ModelForm):
|
||||||
|
|
||||||
|
|
||||||
class RecipeStepForm(ModelForm):
|
class RecipeStepForm(ModelForm):
|
||||||
|
"""Form for creating and updating steps of a recipe."""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RecipeStep
|
model = RecipeStep
|
||||||
fields = ("instructions",)
|
fields = ("instructions",)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ from moku.models.user import User, UserSettings
|
||||||
|
|
||||||
|
|
||||||
class UserForm(UserCreationForm):
|
class UserForm(UserCreationForm):
|
||||||
|
"""Form for creating a new user account on the site."""
|
||||||
|
|
||||||
captcha = ReCaptchaField(required=True)
|
captcha = ReCaptchaField(required=True)
|
||||||
check = forms.BooleanField(required=True)
|
check = forms.BooleanField(required=True)
|
||||||
|
|
||||||
|
|
@ -30,6 +32,8 @@ class UserForm(UserCreationForm):
|
||||||
|
|
||||||
|
|
||||||
class UserSettingsForm(forms.ModelForm):
|
class UserSettingsForm(forms.ModelForm):
|
||||||
|
"""Form for creating or updating user settings."""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserSettings
|
model = UserSettings
|
||||||
fields = ("language",)
|
fields = ("language",)
|
||||||
|
|
@ -37,6 +41,8 @@ class UserSettingsForm(forms.ModelForm):
|
||||||
|
|
||||||
|
|
||||||
class ProfileForm(forms.ModelForm):
|
class ProfileForm(forms.ModelForm):
|
||||||
|
"""Form for updating user profile information."""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ("avatar", "pronouns", "location", "bio")
|
fields = ("avatar", "pronouns", "location", "bio")
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ from PIL import Image, ImageOps
|
||||||
|
|
||||||
|
|
||||||
def _convert_image_to_webp(image_file):
|
def _convert_image_to_webp(image_file):
|
||||||
|
"""Private helper function for image conversion."""
|
||||||
image = Image.open(image_file)
|
image = Image.open(image_file)
|
||||||
ImageOps.exif_transpose(image, in_place=True)
|
ImageOps.exif_transpose(image, in_place=True)
|
||||||
image.convert("RGB")
|
image.convert("RGB")
|
||||||
|
|
@ -15,8 +16,10 @@ def _convert_image_to_webp(image_file):
|
||||||
|
|
||||||
|
|
||||||
def process_avatar_image(image_file):
|
def process_avatar_image(image_file):
|
||||||
|
"""Image conversion function for user avatars."""
|
||||||
return _convert_image_to_webp(image_file)
|
return _convert_image_to_webp(image_file)
|
||||||
|
|
||||||
|
|
||||||
def process_post_image(image_file):
|
def process_post_image(image_file):
|
||||||
|
"""Image conversion function for post images."""
|
||||||
return _convert_image_to_webp(image_file)
|
return _convert_image_to_webp(image_file)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ from django.utils import translation
|
||||||
|
|
||||||
|
|
||||||
class MokuLanguageMiddleware:
|
class MokuLanguageMiddleware:
|
||||||
|
"""Activates the chosen language of an authenticated user if set."""
|
||||||
|
|
||||||
def __init__(self, get_response):
|
def __init__(self, get_response):
|
||||||
self.get_response = get_response
|
self.get_response = get_response
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,13 @@ from moku.validators import validate_emoji
|
||||||
|
|
||||||
|
|
||||||
def post_image_filename(instance, _):
|
def post_image_filename(instance, _):
|
||||||
|
"""Returns the filename that post images should be saved to."""
|
||||||
return f"posts/{instance.created_by.username}__{instance.uuid}.webp"
|
return f"posts/{instance.created_by.username}__{instance.uuid}.webp"
|
||||||
|
|
||||||
|
|
||||||
class PostManager(models.Manager):
|
class PostManager(models.Manager):
|
||||||
|
"""Manages post objects more efficiently by pre-fetching recipes and their steps."""
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return (
|
return (
|
||||||
super()
|
super()
|
||||||
|
|
@ -28,6 +31,8 @@ class PostManager(models.Manager):
|
||||||
|
|
||||||
|
|
||||||
class Post(models.Model):
|
class Post(models.Model):
|
||||||
|
"""Represents a single post on the site."""
|
||||||
|
|
||||||
uuid = ShortUUIDField(
|
uuid = ShortUUIDField(
|
||||||
verbose_name=_("unique id"),
|
verbose_name=_("unique id"),
|
||||||
max_length=22,
|
max_length=22,
|
||||||
|
|
@ -85,6 +90,10 @@ class Post(models.Model):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def text(self):
|
def text(self):
|
||||||
|
"""
|
||||||
|
The text of the post, with the post's chosen verb hydrated with food and user
|
||||||
|
information.
|
||||||
|
"""
|
||||||
return self.get_verb_display() % {
|
return self.get_verb_display() % {
|
||||||
"user": (
|
"user": (
|
||||||
f'<a href="{self.created_by.get_absolute_url()}">'
|
f'<a href="{self.created_by.get_absolute_url()}">'
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ from shortuuid.django_fields import ShortUUIDField
|
||||||
|
|
||||||
|
|
||||||
class RecipeManager(models.Manager):
|
class RecipeManager(models.Manager):
|
||||||
|
"""Manages recipe objects more efficiently by pre-fetching steps."""
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return (
|
return (
|
||||||
super()
|
super()
|
||||||
|
|
@ -16,6 +18,8 @@ class RecipeManager(models.Manager):
|
||||||
|
|
||||||
|
|
||||||
class Recipe(models.Model):
|
class Recipe(models.Model):
|
||||||
|
"""Represents a single recipe on the site."""
|
||||||
|
|
||||||
uuid = ShortUUIDField(
|
uuid = ShortUUIDField(
|
||||||
verbose_name=_("unique id"),
|
verbose_name=_("unique id"),
|
||||||
max_length=22,
|
max_length=22,
|
||||||
|
|
@ -47,6 +51,8 @@ class Recipe(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class RecipeStep(models.Model):
|
class RecipeStep(models.Model):
|
||||||
|
"""Represents a single step belonging to a recipe."""
|
||||||
|
|
||||||
uuid = ShortUUIDField(
|
uuid = ShortUUIDField(
|
||||||
verbose_name=_("step id"),
|
verbose_name=_("step id"),
|
||||||
max_length=22,
|
max_length=22,
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,13 @@ from moku.validators import validate_username_length, validate_username_regex
|
||||||
|
|
||||||
|
|
||||||
def user_avatar_filename(instance, _):
|
def user_avatar_filename(instance, _):
|
||||||
|
"""Returns the filename that user avatar images should be saved to."""
|
||||||
return f"avatars/{instance.username}.webp"
|
return f"avatars/{instance.username}.webp"
|
||||||
|
|
||||||
|
|
||||||
class User(AbstractUser):
|
class User(AbstractUser):
|
||||||
|
"""Represents a single authenticated user on the site."""
|
||||||
|
|
||||||
username = models.CharField(
|
username = models.CharField(
|
||||||
verbose_name=_("username"),
|
verbose_name=_("username"),
|
||||||
max_length=64,
|
max_length=64,
|
||||||
|
|
@ -74,10 +77,13 @@ class User(AbstractUser):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def email_confirmed(self):
|
def email_confirmed(self):
|
||||||
|
"""Whether the user has confirmed their email address."""
|
||||||
return self.email_confirmed_at is not None
|
return self.email_confirmed_at is not None
|
||||||
|
|
||||||
|
|
||||||
class UserSettings(models.Model):
|
class UserSettings(models.Model):
|
||||||
|
"""Represents settings for a single user."""
|
||||||
|
|
||||||
user = models.OneToOneField(
|
user = models.OneToOneField(
|
||||||
"User", related_name="settings", on_delete=models.CASCADE
|
"User", related_name="settings", on_delete=models.CASCADE
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ from emoji import is_emoji
|
||||||
|
|
||||||
|
|
||||||
def validate_emoji(value):
|
def validate_emoji(value):
|
||||||
|
"""Validates that a given string is a single emoji."""
|
||||||
if not is_emoji(value):
|
if not is_emoji(value):
|
||||||
raise ValidationError(_("Must be an emoji."))
|
raise ValidationError(_("Must be an emoji."))
|
||||||
|
|
||||||
|
|
@ -16,9 +17,11 @@ validate_username_regex = RegexValidator(
|
||||||
_("Username may only contain letters, numbers, hyphens, underscores and dots."),
|
_("Username may only contain letters, numbers, hyphens, underscores and dots."),
|
||||||
"invalid",
|
"invalid",
|
||||||
)
|
)
|
||||||
|
"""Validates that a given string is a valid username."""
|
||||||
|
|
||||||
|
|
||||||
def validate_username_length(value):
|
def validate_username_length(value):
|
||||||
|
"""Validates the length of a given username string according to Django settings."""
|
||||||
if (
|
if (
|
||||||
len(value) < settings.USERNAME_MIN_LENGTH
|
len(value) < settings.USERNAME_MIN_LENGTH
|
||||||
or len(value) > settings.USERNAME_MAX_LENGTH
|
or len(value) > settings.USERNAME_MAX_LENGTH
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ from moku.views.base import View
|
||||||
|
|
||||||
|
|
||||||
class LoginView(View, BaseLoginView):
|
class LoginView(View, BaseLoginView):
|
||||||
|
"""Allows users to log in by username and password."""
|
||||||
|
|
||||||
template_name = "moku/login.jinja"
|
template_name = "moku/login.jinja"
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
|
|
@ -27,4 +29,6 @@ class LoginView(View, BaseLoginView):
|
||||||
|
|
||||||
|
|
||||||
class LogoutView(BaseLogoutView):
|
class LogoutView(BaseLogoutView):
|
||||||
|
"""Logs the user out and redirect them to the feed."""
|
||||||
|
|
||||||
next_page = "feed"
|
next_page = "feed"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ from django.views import generic
|
||||||
|
|
||||||
|
|
||||||
class View(generic.TemplateView):
|
class View(generic.TemplateView):
|
||||||
|
"""Defines a common set of data to be passed to the template context."""
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
return {
|
return {
|
||||||
**super().get_context_data(**kwargs),
|
**super().get_context_data(**kwargs),
|
||||||
|
|
@ -14,4 +16,6 @@ class View(generic.TemplateView):
|
||||||
|
|
||||||
|
|
||||||
class FormView(View, generic.FormView):
|
class FormView(View, generic.FormView):
|
||||||
|
"""Functions the same as `moku.views.base.View` but for rendering forms."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ from moku.views.base import FormView
|
||||||
|
|
||||||
|
|
||||||
class FeedView(FormView):
|
class FeedView(FormView):
|
||||||
|
"""Allows users to see recent posts and create a new post."""
|
||||||
|
|
||||||
template_name = "moku/feed.jinja"
|
template_name = "moku/feed.jinja"
|
||||||
form_class = PostForm
|
form_class = PostForm
|
||||||
|
|
||||||
|
|
@ -70,6 +72,8 @@ class FeedView(FormView):
|
||||||
|
|
||||||
|
|
||||||
class LatestPostJSONView(BaseView):
|
class LatestPostJSONView(BaseView):
|
||||||
|
"""Renders the latest post from a specific user as JSON."""
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
post = (
|
post = (
|
||||||
Post.objects.prefetch_related("recipe__steps")
|
Post.objects.prefetch_related("recipe__steps")
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ from moku.views.base import FormView, View
|
||||||
|
|
||||||
|
|
||||||
class DeleteRecipeView(LoginRequiredMixin, UserPassesTestMixin, View):
|
class DeleteRecipeView(LoginRequiredMixin, UserPassesTestMixin, View):
|
||||||
|
"""Deletes a recipe from the database if it belongs to the authenticated user."""
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
self.recipe.delete()
|
self.recipe.delete()
|
||||||
messages.success(self.request, _("recipe deleted successfully!"))
|
messages.success(self.request, _("recipe deleted successfully!"))
|
||||||
|
|
@ -24,6 +26,10 @@ class DeleteRecipeView(LoginRequiredMixin, UserPassesTestMixin, View):
|
||||||
|
|
||||||
|
|
||||||
class DeleteStepView(LoginRequiredMixin, UserPassesTestMixin, View):
|
class DeleteStepView(LoginRequiredMixin, UserPassesTestMixin, View):
|
||||||
|
"""
|
||||||
|
Deletes a recipe step from the database if it belongs to the authenticated user.
|
||||||
|
"""
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
if self.step.order != (self.step.recipe.steps.count() - 1):
|
if self.step.order != (self.step.recipe.steps.count() - 1):
|
||||||
messages.error(self.request, _("sorry! you can only delete the last step."))
|
messages.error(self.request, _("sorry! you can only delete the last step."))
|
||||||
|
|
@ -45,6 +51,8 @@ class DeleteStepView(LoginRequiredMixin, UserPassesTestMixin, View):
|
||||||
|
|
||||||
|
|
||||||
class EditStepView(LoginRequiredMixin, UserPassesTestMixin, FormView):
|
class EditStepView(LoginRequiredMixin, UserPassesTestMixin, FormView):
|
||||||
|
"""Allows users to edit steps of a recipe they created."""
|
||||||
|
|
||||||
template_name = "moku/recipe/edit_step.jinja"
|
template_name = "moku/recipe/edit_step.jinja"
|
||||||
form_class = RecipeStepForm
|
form_class = RecipeStepForm
|
||||||
|
|
||||||
|
|
@ -69,6 +77,8 @@ class EditStepView(LoginRequiredMixin, UserPassesTestMixin, FormView):
|
||||||
|
|
||||||
|
|
||||||
class IndexRecipeView(LoginRequiredMixin, View):
|
class IndexRecipeView(LoginRequiredMixin, View):
|
||||||
|
"""Shows a list of recipes created by the authenticated user."""
|
||||||
|
|
||||||
template_name = "moku/recipe/index.jinja"
|
template_name = "moku/recipe/index.jinja"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
|
@ -81,6 +91,8 @@ class IndexRecipeView(LoginRequiredMixin, View):
|
||||||
|
|
||||||
|
|
||||||
class NewRecipeView(LoginRequiredMixin, FormView):
|
class NewRecipeView(LoginRequiredMixin, FormView):
|
||||||
|
"""Allows users to create a new recipe."""
|
||||||
|
|
||||||
template_name = "moku/recipe/form.jinja"
|
template_name = "moku/recipe/form.jinja"
|
||||||
form_class = RecipeForm
|
form_class = RecipeForm
|
||||||
|
|
||||||
|
|
@ -95,6 +107,11 @@ class NewRecipeView(LoginRequiredMixin, FormView):
|
||||||
|
|
||||||
|
|
||||||
class ShowRecipeView(FormView):
|
class ShowRecipeView(FormView):
|
||||||
|
"""
|
||||||
|
Shows users details about a recipe, and allows steps to be created for it if they
|
||||||
|
are logged in as the recipe creator.
|
||||||
|
"""
|
||||||
|
|
||||||
template_name = "moku/recipe/show.jinja"
|
template_name = "moku/recipe/show.jinja"
|
||||||
form_class = RecipeStepForm
|
form_class = RecipeStepForm
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,18 @@ from moku.views.base import View
|
||||||
|
|
||||||
|
|
||||||
class ChangelogView(View):
|
class ChangelogView(View):
|
||||||
|
"""Displays the static changelog page."""
|
||||||
|
|
||||||
template_name = "moku/changelog.jinja"
|
template_name = "moku/changelog.jinja"
|
||||||
|
|
||||||
|
|
||||||
class PrivacyView(View):
|
class PrivacyView(View):
|
||||||
|
"""Displays the static privacy policy page."""
|
||||||
|
|
||||||
template_name = "moku/privacy.jinja"
|
template_name = "moku/privacy.jinja"
|
||||||
|
|
||||||
|
|
||||||
class TermsView(View):
|
class TermsView(View):
|
||||||
|
"""Displays the static terms of use page."""
|
||||||
|
|
||||||
template_name = "moku/terms.jinja"
|
template_name = "moku/terms.jinja"
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ from moku.views.base import FormView, View
|
||||||
|
|
||||||
|
|
||||||
class EditProfileView(LoginRequiredMixin, FormView):
|
class EditProfileView(LoginRequiredMixin, FormView):
|
||||||
|
"""Allows a user to edit information within their user profile."""
|
||||||
|
|
||||||
template_name = "moku/profile/edit.jinja"
|
template_name = "moku/profile/edit.jinja"
|
||||||
form_class = ProfileForm
|
form_class = ProfileForm
|
||||||
|
|
||||||
|
|
@ -26,6 +28,8 @@ class EditProfileView(LoginRequiredMixin, FormView):
|
||||||
|
|
||||||
|
|
||||||
class EditSettingsView(LoginRequiredMixin, FormView):
|
class EditSettingsView(LoginRequiredMixin, FormView):
|
||||||
|
"""Allows a user to edit information within their user settings."""
|
||||||
|
|
||||||
template_name = "moku/settings.jinja"
|
template_name = "moku/settings.jinja"
|
||||||
form_class = UserSettingsForm
|
form_class = UserSettingsForm
|
||||||
|
|
||||||
|
|
@ -50,6 +54,8 @@ class EditSettingsView(LoginRequiredMixin, FormView):
|
||||||
|
|
||||||
|
|
||||||
class ProfileView(View):
|
class ProfileView(View):
|
||||||
|
"""Shows a user's profile along with a list of their recent posts."""
|
||||||
|
|
||||||
template_name = "moku/profile/show.jinja"
|
template_name = "moku/profile/show.jinja"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
|
@ -62,6 +68,8 @@ class ProfileView(View):
|
||||||
|
|
||||||
|
|
||||||
class SignupView(FormView):
|
class SignupView(FormView):
|
||||||
|
"""Allows non-authenticated users to create an account on the site."""
|
||||||
|
|
||||||
template_name = "moku/signup.jinja"
|
template_name = "moku/signup.jinja"
|
||||||
form_class = UserForm
|
form_class = UserForm
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue