Source

botanic_apartments / catalogue / forms.py

# -*- coding: utf-8 -*-
from catalogue import models
from catalogue.utils import build_bonus_field
from django import forms
from django.conf import settings
from django.db.models import BLANK_CHOICE_DASH
from django.forms.fields import EMPTY_VALUES
from django.forms.forms import DeclarativeFieldsMetaclass
from django.utils.translation import ugettext_lazy as _
from django_utils.forms import DecimalRangeField
from django_utils.forms import FancyRangeWidget
from multilingual.forms import MultilingualModelForm
from recaptcha_django import ReCaptchaField

class JqueyUiDatepicker(forms.DateInput):
    class Media:
        js = (settings.MEDIA_URL + "js/jqueryui-calendar.js",)

    def __init__(self, attrs={}):
        super(JqueyUiDatepicker, self).__init__(attrs={'class': 'vDateField', 'size': '10'})

class SearchFormMetaclass(DeclarativeFieldsMetaclass):
    def __new__(cls, name, bases, attrs):
        bonus_fields = {}
        for bonus_type in models.BonusType.objects.all():
            try:
                field = build_bonus_field(bonus_type, override=dict(required=False), add_empty_choice=True)
                field.bonus_type = bonus_type
                opt = 'b%d' % bonus_type.id
                bonus_fields[opt] = field
            except (ImportError, AttributeError):
                pass
        attrs['_bonus_fields'] = bonus_fields
        attrs.update(bonus_fields)
        new_class = super(SearchFormMetaclass, cls).__new__(cls, name, bases, attrs)
        return new_class

class SearchForm(forms.Form):
    #__metaclass__ = SearchFormMetaclass
    currency = forms.ChoiceField(label=_('currency').capitalize(), choices=(BLANK_CHOICE_DASH + list(models.CURRENCIES)), required=False)
    price = DecimalRangeField(label=_('price').capitalize(), required=False, min_value=0, decimal_places=2, widget=FancyRangeWidget(min=0, max=2000, range="'min'"), initial=(0, 2000))
    rooms = forms.ChoiceField(label=_('rooms').capitalize(), choices=(BLANK_CHOICE_DASH + list(models.ApartmentManager.ROOMS)), required=False)
    layout = forms.ChoiceField(label=_('layout').capitalize(), choices=(BLANK_CHOICE_DASH + list(models.ApartmentManager.LAYOUTS)), required=False)
    street = forms.ModelChoiceField(label=_('street').capitalize(), queryset=models.Street.objects.all(), required=False)
    level = forms.ChoiceField(label=_('level').capitalize(), choices=(BLANK_CHOICE_DASH + list(models.ApartmentManager.LEVELS)), required=False)

class StreetForm(MultilingualModelForm):
    class Meta:
        model = models.Street

class BuildingForm(forms.ModelForm):
    class Meta:
        model = models.Building

class ApartmentForm(MultilingualModelForm):
    code = forms.RegexField(regex=models.ApartmentManager.CODE_REGEX,
                            label=models.Apartment._meta.get_field('code').verbose_name,
                            max_length=models.Apartment._meta.get_field('code').max_length)
    class Meta:
        model = models.Apartment

class FindByIdForm(forms.Form):
    id = forms.IntegerField(label=_('ID'), min_value=1)

#TODO: Автоматическая перегрузка формы при изменении типа
class BonusForm(forms.ModelForm):
    def __init__(self, * args, ** kwargs):
        super(BonusForm, self).__init__(*args, ** kwargs)
        instance = kwargs.get('instance', None)
        if instance:
            bonus_type = getattr(instance, 'bonus_type', None)
            orig_value_field = self.fields.get('value', None)
            if bonus_type is not None and orig_value_field is not None:
                self.fields['value'] = build_bonus_field(bonus_type, orig_value_field, exclude=['widget'])
    class Meta:
        model = models.Bonus

class BonusTypeForm(forms.ModelForm):
    def clean_options(self):
        options = self.cleaned_data.get('options', None)
        field = getattr(self.instance, 'field', None)
        if field:
            from django_utils import import_object_from_package
            mod, field_class = import_object_from_package(field)
            if issubclass(field_class, forms.ChoiceField):
                if options in EMPTY_VALUES:
                    raise forms.ValidationError(self.fields['field'].error_messages['required'])
                parts = options.split(models.BONUS_CHOICE_DELIMATER)
                if len(parts) < 2:
                    raise forms.ValidationError(_('Number of choices must be greater then one'))
        return options

def clean_reservation_period(form):
    cleaned_data = form.cleaned_data
    start = cleaned_data.get('start', None)
    end = cleaned_data.get('end', None)
    if start is None or end is None:
        return cleaned_data
    if start > end:
        raise forms.ValidationError(form.error_fields['order'])
    apartment_id = cleaned_data.get('apartment', None)
    try:
        apartment = models.Apartment.objects.get(id=apartment_id)
    except models.Aprtment.ObjectDoesNotExist:
        raise forms.ValidationError(_('The apartment not found'))
    if not apartment.is_period_free(start, end):
        raise forms.ValidationError(form.error_fields['occupied'])
    return cleaned_data

class ReservationPeriodForm(forms.ModelForm):
    error_fields = {
    'order': _('Start later then end'),
    'occupied': _('The apartment occupied during this period, please select a different dates.'),
    }
    def clean(self):
        return clean_reservation_period(self)
PHONE_REGEX = r'\+\d{1,2} ?\(?\d{3}\)? ?\d{3}( |\-)?\d{2}( |\-)?\d{2}'
# TODO: Доделать форму
class ReservationForm(forms.Form):
    quiet = False
    error_fields = {
    'order': _('Check-in date later then departure date'),
    'occupied': _('The apartment occupied during this period, please select a different dates.'),
    'not_agree': _('You must agree with public agreement'),
    }
    apartment = forms.IntegerField(label=_('apartment'), widget=forms.HiddenInput)
    start = forms.DateField(label=_('check-in date'), widget=JqueyUiDatepicker, input_formats=['%d.%m.%Y'])
    end = forms.DateField(label=_('departure date'), widget=JqueyUiDatepicker, input_formats=['%d.%m.%Y'])
    first_name = forms.CharField(label=_('first name'), max_length=50)
    last_name = forms.CharField(label=_('last name'), max_length=50)
    phone_number = forms.RegexField(label=_('phone number'), regex=PHONE_REGEX, initial='+0 (000) 000-00-00')
    email = forms.EmailField(label=_('email'))
    is_agree = forms.BooleanField(label=_('I am agree'))
    captcha = ReCaptchaField()
    def has_changed(self):
        if not self.quiet:
            return super(ReservationForm, self).has_changed()
        else:
            return False
    def clean(self):
        return clean_reservation_period(self)
    def clean_is_agree(self):
        is_agree = self.cleaned_data.get('is_agree', False)
        if not is_agree:
            raise forms.ValidationError(form.error_fields['not_agree'])
        return is_agree
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.