fixes #1584 This is a temporary fix. As Mouse has suggested, ultimately it would be good to re-import data from one or more of the linked data sources if there is anything missing.
348 lines
8.6 KiB
Python
348 lines
8.6 KiB
Python
""" using django model forms """
|
|
import datetime
|
|
from collections import defaultdict
|
|
|
|
from django import forms
|
|
from django.forms import ModelForm, PasswordInput, widgets, ChoiceField
|
|
from django.forms.widgets import Textarea
|
|
from django.utils import timezone
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from bookwyrm import models
|
|
|
|
|
|
class CustomForm(ModelForm):
|
|
"""add css classes to the forms"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
css_classes = defaultdict(lambda: "")
|
|
css_classes["text"] = "input"
|
|
css_classes["password"] = "input"
|
|
css_classes["email"] = "input"
|
|
css_classes["number"] = "input"
|
|
css_classes["checkbox"] = "checkbox"
|
|
css_classes["textarea"] = "textarea"
|
|
# pylint: disable=super-with-arguments
|
|
super(CustomForm, self).__init__(*args, **kwargs)
|
|
for visible in self.visible_fields():
|
|
if hasattr(visible.field.widget, "input_type"):
|
|
input_type = visible.field.widget.input_type
|
|
if isinstance(visible.field.widget, Textarea):
|
|
input_type = "textarea"
|
|
visible.field.widget.attrs["rows"] = 5
|
|
visible.field.widget.attrs["class"] = css_classes[input_type]
|
|
|
|
|
|
# pylint: disable=missing-class-docstring
|
|
class LoginForm(CustomForm):
|
|
class Meta:
|
|
model = models.User
|
|
fields = ["localname", "password"]
|
|
help_texts = {f: None for f in fields}
|
|
widgets = {
|
|
"password": PasswordInput(),
|
|
}
|
|
|
|
|
|
class RegisterForm(CustomForm):
|
|
class Meta:
|
|
model = models.User
|
|
fields = ["localname", "email", "password"]
|
|
help_texts = {f: None for f in fields}
|
|
widgets = {"password": PasswordInput()}
|
|
|
|
|
|
class RatingForm(CustomForm):
|
|
class Meta:
|
|
model = models.ReviewRating
|
|
fields = ["user", "book", "rating", "privacy"]
|
|
|
|
|
|
class ReviewForm(CustomForm):
|
|
class Meta:
|
|
model = models.Review
|
|
fields = [
|
|
"user",
|
|
"book",
|
|
"name",
|
|
"content",
|
|
"rating",
|
|
"content_warning",
|
|
"sensitive",
|
|
"privacy",
|
|
]
|
|
|
|
|
|
class CommentForm(CustomForm):
|
|
class Meta:
|
|
model = models.Comment
|
|
fields = [
|
|
"user",
|
|
"book",
|
|
"content",
|
|
"content_warning",
|
|
"sensitive",
|
|
"privacy",
|
|
"progress",
|
|
"progress_mode",
|
|
"reading_status",
|
|
]
|
|
|
|
|
|
class QuotationForm(CustomForm):
|
|
class Meta:
|
|
model = models.Quotation
|
|
fields = [
|
|
"user",
|
|
"book",
|
|
"quote",
|
|
"content",
|
|
"content_warning",
|
|
"sensitive",
|
|
"privacy",
|
|
"position",
|
|
"position_mode",
|
|
]
|
|
|
|
|
|
class ReplyForm(CustomForm):
|
|
class Meta:
|
|
model = models.Status
|
|
fields = [
|
|
"user",
|
|
"content",
|
|
"content_warning",
|
|
"sensitive",
|
|
"reply_parent",
|
|
"privacy",
|
|
]
|
|
|
|
|
|
class StatusForm(CustomForm):
|
|
class Meta:
|
|
model = models.Status
|
|
fields = ["user", "content", "content_warning", "sensitive", "privacy"]
|
|
|
|
|
|
class DirectForm(CustomForm):
|
|
class Meta:
|
|
model = models.Status
|
|
fields = ["user", "content", "content_warning", "sensitive", "privacy"]
|
|
|
|
|
|
class EditUserForm(CustomForm):
|
|
class Meta:
|
|
model = models.User
|
|
fields = [
|
|
"avatar",
|
|
"name",
|
|
"email",
|
|
"summary",
|
|
"show_goal",
|
|
"show_suggested_users",
|
|
"manually_approves_followers",
|
|
"default_post_privacy",
|
|
"discoverable",
|
|
"preferred_timezone",
|
|
"preferred_language",
|
|
]
|
|
help_texts = {f: None for f in fields}
|
|
|
|
|
|
class LimitedEditUserForm(CustomForm):
|
|
class Meta:
|
|
model = models.User
|
|
fields = [
|
|
"avatar",
|
|
"name",
|
|
"summary",
|
|
"manually_approves_followers",
|
|
"discoverable",
|
|
]
|
|
help_texts = {f: None for f in fields}
|
|
|
|
|
|
class DeleteUserForm(CustomForm):
|
|
class Meta:
|
|
model = models.User
|
|
fields = ["password"]
|
|
|
|
|
|
class UserGroupForm(CustomForm):
|
|
class Meta:
|
|
model = models.User
|
|
fields = ["groups"]
|
|
|
|
|
|
class CoverForm(CustomForm):
|
|
class Meta:
|
|
model = models.Book
|
|
fields = ["cover"]
|
|
help_texts = {f: None for f in fields}
|
|
|
|
|
|
class EditionForm(CustomForm):
|
|
class Meta:
|
|
model = models.Edition
|
|
exclude = [
|
|
"remote_id",
|
|
"origin_id",
|
|
"created_date",
|
|
"updated_date",
|
|
"edition_rank",
|
|
"authors",
|
|
"parent_work",
|
|
"shelves",
|
|
"connector",
|
|
"search_vector",
|
|
]
|
|
|
|
|
|
class AuthorForm(CustomForm):
|
|
class Meta:
|
|
model = models.Author
|
|
fields = [
|
|
"last_edited_by",
|
|
"name",
|
|
"aliases",
|
|
"bio",
|
|
"wikipedia_link",
|
|
"born",
|
|
"died",
|
|
"openlibrary_key",
|
|
"librarything_key",
|
|
"goodreads_key",
|
|
]
|
|
|
|
|
|
class ImportForm(forms.Form):
|
|
csv_file = forms.FileField()
|
|
|
|
|
|
class ExpiryWidget(widgets.Select):
|
|
def value_from_datadict(self, data, files, name):
|
|
"""human-readable exiration time buckets"""
|
|
selected_string = super().value_from_datadict(data, files, name)
|
|
|
|
if selected_string == "day":
|
|
interval = datetime.timedelta(days=1)
|
|
elif selected_string == "week":
|
|
interval = datetime.timedelta(days=7)
|
|
elif selected_string == "month":
|
|
interval = datetime.timedelta(days=31) # Close enough?
|
|
elif selected_string == "forever":
|
|
return None
|
|
else:
|
|
return selected_string # This will raise
|
|
|
|
return timezone.now() + interval
|
|
|
|
|
|
class InviteRequestForm(CustomForm):
|
|
def clean(self):
|
|
"""make sure the email isn't in use by a registered user"""
|
|
cleaned_data = super().clean()
|
|
email = cleaned_data.get("email")
|
|
if email and models.User.objects.filter(email=email).exists():
|
|
self.add_error("email", _("A user with this email already exists."))
|
|
|
|
class Meta:
|
|
model = models.InviteRequest
|
|
fields = ["email"]
|
|
|
|
|
|
class CreateInviteForm(CustomForm):
|
|
class Meta:
|
|
model = models.SiteInvite
|
|
exclude = ["code", "user", "times_used", "invitees"]
|
|
widgets = {
|
|
"expiry": ExpiryWidget(
|
|
choices=[
|
|
("day", _("One Day")),
|
|
("week", _("One Week")),
|
|
("month", _("One Month")),
|
|
("forever", _("Does Not Expire")),
|
|
]
|
|
),
|
|
"use_limit": widgets.Select(
|
|
choices=[(i, _(f"{i} uses")) for i in [1, 5, 10, 25, 50, 100]]
|
|
+ [(None, _("Unlimited"))]
|
|
),
|
|
}
|
|
|
|
|
|
class ShelfForm(CustomForm):
|
|
class Meta:
|
|
model = models.Shelf
|
|
fields = ["user", "name", "privacy", "description"]
|
|
|
|
|
|
class GoalForm(CustomForm):
|
|
class Meta:
|
|
model = models.AnnualGoal
|
|
fields = ["user", "year", "goal", "privacy"]
|
|
|
|
|
|
class SiteForm(CustomForm):
|
|
class Meta:
|
|
model = models.SiteSettings
|
|
exclude = []
|
|
|
|
|
|
class AnnouncementForm(CustomForm):
|
|
class Meta:
|
|
model = models.Announcement
|
|
exclude = ["remote_id"]
|
|
|
|
|
|
class ListForm(CustomForm):
|
|
class Meta:
|
|
model = models.List
|
|
fields = ["user", "name", "description", "curation", "privacy", "group"]
|
|
|
|
|
|
class GroupForm(CustomForm):
|
|
class Meta:
|
|
model = models.Group
|
|
fields = ["user", "privacy", "name", "description"]
|
|
|
|
|
|
class ReportForm(CustomForm):
|
|
class Meta:
|
|
model = models.Report
|
|
fields = ["user", "reporter", "statuses", "note"]
|
|
|
|
|
|
class EmailBlocklistForm(CustomForm):
|
|
class Meta:
|
|
model = models.EmailBlocklist
|
|
fields = ["domain"]
|
|
|
|
|
|
class IPBlocklistForm(CustomForm):
|
|
class Meta:
|
|
model = models.IPBlocklist
|
|
fields = ["address"]
|
|
|
|
|
|
class ServerForm(CustomForm):
|
|
class Meta:
|
|
model = models.FederatedServer
|
|
exclude = ["remote_id"]
|
|
|
|
|
|
class SortListForm(forms.Form):
|
|
sort_by = ChoiceField(
|
|
choices=(
|
|
("order", _("List Order")),
|
|
("title", _("Book Title")),
|
|
("rating", _("Rating")),
|
|
),
|
|
label=_("Sort By"),
|
|
)
|
|
direction = ChoiceField(
|
|
choices=(
|
|
("ascending", _("Ascending")),
|
|
("descending", _("Descending")),
|
|
),
|
|
)
|