How can I Pythonize/Djangoize/DRY my Django code?
views.py
class AccountDetail(DetailView):
model = BankAccount
template_name = 'bank/account_detail.html'
def get(self, *args, **kwargs):
self.object = self.get_object()
if self.object.is_owner(self.request.user.citizen):
return render(self.request, self.template_name, self.get_context_data())
raise Http404
class SendTransfer(SingleObjectMixin, FormView):
model = BankAccount
form_class = SendTransferForm
template_name = 'bank/send_transfer.html'
def dispatch(self, request, *args, **kwargs):
self.object = self.get_object()
return super(SendTransfer, self).dispatch(request, *args, **kwargs)
def get_object(self, queryset=None):
obj = super(SendTransfer, self).get_object(queryset)
if not obj.is_owner(self.request.user.citizen):
raise Http404
return obj
def form_valid(self, form):
data = form.cleaned_data
MoneyTransfer.objects.create(sender=self.object,
receiver=data['receiver'], # ModelChoiceField in the form
total=data['total'], # FloatField in the form, etc.
when=timezone.localtime(timezone.now()),
comment=data['comment'])
return redirect('AccountDetail', self.object.pk)
def form_invalid(self, form):
return render(self.request, self.template_name, self.get_context_data())
def get_form_kwargs(self):
kwargs = super(SendTransfer, self).get_form_kwargs()
kwargs['sender'] = BankAccount.objects.get(id=self.kwargs['pk'])
kwargs['user'] = self.request.user
return kwargs
class OutcomeTransfers(DetailView):
model = BankAccount
template_name = 'bank/report.html'
def get_object(self, queryset=None):
obj = super(OutcomeTransfers, self).get_object(queryset)
if not obj.is_owner(self.request.user.citizen):
raise Http404
return obj
def _get_queryset(self):
return self.model.objects.get(id=self.kwargs['pk']).outcome_transfers.all()
def get_context_data(self, **kwargs):
data = super(OutcomeTransfers, self).get_context_data()
queryset = self._get_queryset()
if 'sort' in self.request.GET:
queryset = queryset.order_by(self.request.GET['sort'])
data['table'] = MoneyTransferTable(queryset)
return data
class IncomeTransfers(DetailView):
model = BankAccount
template_name = 'bank/report.html'
def get_object(self, queryset=None):
obj = super(IncomeTransfers, self).get_object(queryset)
if not obj.is_owner(self.request.user.citizen):
raise Http404
return obj
def _get_queryset(self):
return self.model.objects.get(id=self.kwargs['pk']).income_transfers.all()
def get_context_data(self, **kwargs):
data = super(IncomeTransfers, self).get_context_data()
queryset = self._get_queryset()
if 'sort' in self.request.GET:
queryset = queryset.order_by(self.request.GET['sort'])
data['table'] = MoneyTransferTable(queryset)
return data
models.py
class RuleQuerySet(models.QuerySet):
def on_date(self, _date):
return self.get(start_date__lte=_date, end_date__gte=_date)
class TransferQuerySet(models.QuerySet):
def on_date(self, _date):
return self.filter(when__lt=_date + timedelta(days=1), when__gte=_date)
class Rule(models.Model):
start_date = models.DateField()
end_date = models.DateField()
deposit_percent = models.DecimalField(max_digits=10, decimal_places=3)
credit_percent = models.DecimalField(max_digits=10, decimal_places=3)
objects = RuleQuerySet.as_manager()
class BankAccount(models.Model):
organization = models.OneToOneField(Organization, related_name='bank_account', blank=True, null=True)
citizen = models.OneToOneField(Citizen, related_name='bank_account', blank=True, null=True)
DEBET = 1
CREDIT = 2
method = models.PositiveSmallIntegerField(choices=(
(DEBET, 'Дебет'),
(CREDIT, 'Кредит'),
))
when_opened = models.DateField()
@property
def owner(self):
if self.is_legal():
return self.organization
return self.citizen
def __unicode__(self):
prefix = "L" if self.is_legal() else "N"
prefix += "D" if self.method == self.DEBET else "C"
public_id = str(self.id).zfill(4)
return "%s (#%s)" % (self.owner, prefix + public_id)
def is_legal(self):
if self.organization and self.citizen:
raise ValueError("Account is legal and natural at the same time. Make it ")
return self.organization is not None
def is_owner(self, citizen):
return (self.citizen and self.citizen.id == citizen.id) or \
(self.organization and self.organization.owners.all().filter(id=citizen.id).count())
@property
def balance(self):
today = timezone.localtime(timezone.now()).date()
if self.method == self.CREDIT:
percent = Rule.objects.on_date(self.when_opened).credit_percent * decimal.Decimal(str(0.01))
else:
percent = Rule.objects.on_date(self.when_opened).deposit_percent * decimal.Decimal(str(0.01))
result = 0
current_date = self.when_opened
while current_date <= today:
dd = self.sum_total_transfers_on_date(current_date)
result += dd
if current_date < today:
result *= 1 + percent
current_date += timedelta(days=1)
return result
def sum_total_transfers_on_date(self, _date):
result = 0
result -= sum(x.total for x in self.cashing_set.on_date(_date))
result -= sum(x.total for x in self.outcome_transfers.on_date(_date))
result += sum(x.total for x in self.deposit_set.all().on_date(_date))
result += sum(x.total for x in self.income_transfers.on_date(_date))
return result
class MoneyTransfer(models.Model):
sender = models.ForeignKey(BankAccount, related_name='outcome_transfers', verbose_name="Отправитель")
receiver = models.ForeignKey(BankAccount, related_name='income_transfers', verbose_name="Получатель")
when = models.DateTimeField(verbose_name="Время")
total = models.DecimalField(max_digits=10, decimal_places=3, verbose_name="Сумма")
comment = models.CharField(max_length=255, verbose_name="Комментарий")
objects = TransferQuerySet.as_manager()
class Deposit(models.Model):
account = models.ForeignKey(BankAccount)
total = models.DecimalField(max_digits=10, decimal_places=3)
banker = models.ForeignKey(Citizen)
when = models.DateTimeField()
objects = TransferQuerySet.as_manager()
class Cashing(models.Model):
account = models.ForeignKey(BankAccount)
total = models.DecimalField(max_digits=10, decimal_places=3)
banker = models.ForeignKey(Citizen)
when = models.DateTimeField()
objects = TransferQuerySet.as_manager()
self.object.is_owner(self.request.user.citizen)
means? \$\endgroup\$ – 200_success Jan 13 '16 at 15:04