| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- from __future__ import annotations
- from django import forms
- from django.contrib.auth import get_user_model
- from django.core.exceptions import ValidationError
- from crispy_forms.helper import FormHelper
- from crispy_forms.layout import Layout, Field
- from .models import Organization, UserProfile
- from api.models import Profile as ApiProfile
- class OrganizationForm(forms.ModelForm):
- class Meta:
- model = Organization
- fields = ["name", "code", "timezone", "currency_code"]
- ## ProvidedService moved to recycle_core app; form now lives in recycle_core.forms
- class UserSelfForm(forms.ModelForm):
- class Meta:
- model = get_user_model()
- fields = ["first_name", "last_name", "email"]
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.helper = FormHelper()
- self.helper.form_tag = False
- self.helper.layout = Layout(
- Field("first_name"),
- Field("last_name"),
- Field("email"),
- )
- class ProfileSelfForm(forms.ModelForm):
- tags = forms.CharField(label="Tags", required=False, help_text="Comma-separated")
- class Meta:
- model = ApiProfile
- fields = ["bio", "interests", "industry"]
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.helper = FormHelper()
- self.helper.form_tag = False
- self.helper.layout = Layout(
- Field("bio"),
- Field("interests"),
- Field("industry"),
- Field("tags"),
- )
- if self.instance and getattr(self.instance, "pk", None):
- try:
- names = list(self.instance.tags.names())
- self.fields["tags"].initial = ", ".join(names)
- except Exception:
- self.fields["tags"].initial = ""
- def save(self, commit: bool = True):
- profile = super().save(commit)
- tags = [t.strip() for t in self.cleaned_data.get("tags", "").split(",") if t.strip()]
- try:
- if commit and hasattr(profile, "tags"):
- profile.tags.set(tags)
- except Exception:
- pass
- return profile
- class UserProfilePhotoForm(forms.ModelForm):
- remove_photo = forms.BooleanField(label="Remove current photo", required=False)
- class Meta:
- model = UserProfile
- fields = ["my_photo", "remove_photo"]
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- # Friendlier widget: accept images only, keep input visually hidden (we trigger via button)
- self.fields["my_photo"].widget = forms.ClearableFileInput(attrs={
- "accept": "image/*",
- "class": "hidden",
- "id": "id_my_photo",
- })
- self.helper = FormHelper()
- self.helper.form_tag = False
- self.helper.layout = Layout(
- Field("my_photo"),
- Field("remove_photo"),
- )
- def clean_my_photo(self):
- f = self.cleaned_data.get("my_photo")
- if not f:
- return f
- # Basic size/type validation (max ~5MB)
- try:
- content_type = getattr(f, "content_type", "")
- if content_type and not content_type.startswith("image/"):
- raise ValidationError("Please upload an image file.")
- except Exception:
- # If storage/file doesn't provide content_type, best-effort skip
- pass
- max_bytes = 5 * 1024 * 1024
- if getattr(f, "size", 0) and f.size > max_bytes:
- raise ValidationError("Image too large (max 5MB).")
- return f
- def save(self, commit: bool = True):
- instance: UserProfile = super().save(commit=False)
- remove = self.cleaned_data.get("remove_photo", False)
- new_file = self.cleaned_data.get("my_photo")
- if remove and not new_file:
- # Clear current photo
- try:
- if instance.my_photo:
- instance.my_photo.delete(save=False)
- except Exception:
- pass
- instance.my_photo = None
- if commit:
- instance.save()
- return instance
|