Проблема, при использовании API класса CurrencyUser не защищено. То есть если мы будем напрямую использовать CurrencyUser.transfer(receiver, 100)
(на самом деле вызов должен быть таким user.credits.transfer(receiver,100)
это для понятности примера), то оно не проверит имеется ли у него такая сумма или нет, существует ли переданный счет в системе, отправляет ли он на свой же счет (и т.д.). Как быть в этом случае? Важно ли сопровождать API в проектировании? Или только в формах делать валидацию и все?
И вообще хотел бы ваши замечания послушать по коду в целом.
Имеется форма:
# Форма перевода валюты
class TransferForm(forms.Form):
login_receiver = forms.CharField(label='Логин', max_length=10, validators=[validate_regex_username, validate_username_exists])
sum = forms.IntegerField(label='Сумма', min_value=1)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')
self.user = self.request.user
super(TransferForm, self).__init__(*args, **kwargs)
def clean_login_receiver(self):
login_receiver = self.cleaned_data['login_receiver']
if self.user.login == login_receiver:
raise ValidationError(_('Вы переводите на свой счет, выберите другой счет'))
return login_receiver
def clean_sum(self):
sum = self.cleaned_data['sum']
# Если пользователь не имеет необходимую сумму на счете
if not self.user.credits.has_required_sum(sum=sum):
raise ValidationError(_('Недостаточно валюты для перевода'))
return sum
Представление:
# Перевод валют на другой аккаунт
class TransferView(LoginRequiredMixin, FormView):
form_class = TransferForm
template_name = 'currency/transfer.html'
def form_valid(self, form):
# Логин получателя
login_receiver = form.cleaned_data['login_receiver']
# Сумма перевода
sum = form.cleaned_data['sum']
# Объект получателя, ищем по логину
receiver = get_object_or_404(Account, login=login_receiver)
# Переводим сумму на аккаунт получателя
if self.request.user.credits.transfer(user_receiver=receiver, sum=sum):
messages.success(self.request, 'Вы успешно перевели {sum} кредитов на {login} '.format(sum=sum, login=login_receiver))
return render(self.request, self.template_name, {
'form': form,
})
def get_form_kwargs(self):
kwargs = super(TransferView, self).get_form_kwargs()
kwargs['request'] = self.request
return kwargs
Класс для работы с валютой (не весь) является полем класса User:
class CurrencyUser:
...
# Перевод валюты
def transfer(self, user_receiver, sum):
# Причина уменьшения валюты
cause_sub = 'Перевод {sum} единиц на логин {login} '.format(sum=sum, login=user_receiver)
# Причина начисления валюты
cause_add = 'Перевод {sum} единиц от логина {login} '.format(sum=sum, login=self.user)
# тут бы неплохо блок транзакции добавить
# Операция вычитания валюты
sub = Operation(login=self.user, currency=self.currency_type, sum=-sum, cause=cause_sub)
# Операция добавления валюты
add = Operation(login=user_receiver, currency=self.currency_type, sum=sum, cause=cause_add)
# Выполнение запросов
sub.save()
add.save()
return True
Updated 29 Aug. 2015, 18:17 by Key.