һ
"MoneyTalks"
. 844 ____________ ..
____________ ..
____________ ..
____________ ..
____________ ..
_____ _____________ 20__.
. ..
_____________________ ________________________________
( ) ()
_____ _____________ 20__.
( )
.. , .. , .. , .. , ..
______________.
_____ _____________ 20__.
( )
2014 .
. 4
1 . 6
1.1 . 6
1.2 . 9
1.3 . 10
1.3.1 . 10
1.3.2 . 11
1.3.3 . 12
1.3.4 . 13
2 . 16
2.1 . 16
2.2 . 17
2.3 . 17
2.4 . 17
2.5 . 17
2.6 . 18
3 . 20
3.1 .. 20
3.2 .. 22
3.3 23
4 . 33
4.1 . 33
4.1.1 . 33
4.2 . 36
4.3 . 37
4.4 . 39
5 . 40
5.1 .. 40
5.2 .. 40
5.3 .. 41
5.3.1 . 41
5.3.2 . 42
5.3.3 . 43
5.3.4 . 43
5.3.5 . 44
5.3.6 ,
. 45
5.3.7 , , . 46
5.3.8 , ,
. 47
5.4 .. 48
. 49
. 50
.. 52
- . , , [1].
|
|
40 [2]. : , , , , , , , .
, . iPhone . , , .
, : , .
, .
:
- Python, , ;
- - Django, MVC;
- PyCharm, Django.
.
MoneyTalks .
(16-30 ) .
, :
1) ();
2) ;
3) ;
4) ;
5) .
1) .
- :
- ;
- ;
- ;
- ;
- ;
- , ;
- , , ;
- , , , ;
- ;
- / , , .
( ) ( , , ..).
2) .
. Windows Server, Linux.
|
|
.
:
- ;
- .
, 30. , , .
3)
:
- +10C +35C;
- 630 800 ;
- 80%;
- 0,75 /³;
- , , [3].
. .
4)
( ):
- Windows Server 2008 :
- 1 ;
- 512 ;
- 8 ;
- DVD ;
- Super VGA (800x600) , , Microsoft [4].
- Ubuntu Server:
- 300 ;
- 64-128 ;
- 1 ;
- 640480;
- CD DVD , USB [5].
5)
Python, PyCharm (Community Professional ) Visual Studio . Python 3.2.
Django 1.7.
, Python. MVC (Model-View-Controller).
6)
, :
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- .
7)
: 1 6 2014.
:
- . :
- UML , , .
- . .
- . 75% .
- [6].
, , ( 1 1).
1 MoneyTalks
.
2.3.1
:
.
:
.
:
.
:
1. .
|
|
:
1. , .
2. .
3. .
:
2.1. .
2.1.1. .
2.1.2. .
2.1.3. .
2.1.4. .
2.2. .
2.2.1. .
2.2.2. .
2.2.3. .
2.3. .
2.3.1. .
2.3.2. .
2.3.3. .
:
.
2.3.2
:
.
:
.
:
.
:
1. .
:
1. , .
2. .
3. .
:
2.1. .
2.1.1. .
2.1.2. .
2.1.3. .
2.2. .
2.2.1. .
2.2.2. .
:
.
2.3.3
:
.
:
.
:
.
1. .
2. .
3. , :
3.1. .
3.2. .
3.3. .
3.4. ,
3.4.1.
3.5. :
3.5.1. 3.1.
4. () , :
4.1. .
4.2. .
4.3. .
4.4. ,
4.4.1. ,
4.5. :
4.5.1. 4.1.
5. ,
5.1. .
5.2. .
5.3. .
6. .
:
.
2.3.4
:
.
:
.
:
.
:
1. .
2. .
:
1. , .
2. .
3. .
:
2.1. .
|
|
2.1.1. .
2.1.2. .
2.1.3. .
2.1.4. .
2.1.5. .
2.1.6. .
2.1.7. .
2.1.8. .
2.2. .
2.2.1. .
2.3. .
2.3.1. .
2.4. .
2.4.1. .
2.5. .
2.5.1. .
2.6. .
2.6.1. .
2.6.2. .
2.6.3. .
2.7. .
2.7.1. .
2.7.2. .
:
[7, c. 101-103].
.
, , . .
, .
, , [7].
:
- ;
- ;
- ;
- ;
- .
, . , , . , .
, . , , , , : , , ӻ.
, .
, : , . .
, , . . , .
3.4
, . , , , .
, , . . , .
2 .
2
.
-. .
. .
. 0 . , , .
, . , .
|
|
. .
, .
, .
, , .
, , , .
.
, . .
, . . , , [7].
, . , , . 3 , .
3
. ( 2), , , Django User.
3 , , clean() __str__() , balance() :
1) __str__() str(), . , , .
:
def __str__(self):
return self.name
2) balance() , .
:
def balance(self):
value = Decimal(0.00)
for transaction in self.transactions_from.all():
value -= transaction.amount
for transaction in self.transactions_to.all():
value += transaction.amount
return value
3) clean() , ValidationError clean() , NON_FIELD_ERRORS, , .
:
def clean(self):
cleaned_data = super().clean()
if self.user.places.filter(name=self.name).exists():
raise ValidationError(_(' '))
return cleaned_data
UML. , . . , . , . .
, . , [8].
4 . , .
UI . . Templates , Static (, ). .
, .
Models . , , , .
4
SQL database , , .
, . , (use case).
, , , , , , . . 5 full_clean BaseForm.
5 full_clean BaseForm
full_clean() BaseForm.
, , .
full_clean() ErrorDict, , . , , . clean_fields(), clean_form() post_clean(). , clean() field . clean_form() clean() , self. _post_clean() .
full_clean, BaseForm :
def full_clean(self):
"""
Cleans all of self.data and populates self._errors and
self.cleaned_data.
"""
self._errors = ErrorDict()
if not self.is_bound: # Stop further processing.
return
self.cleaned_data = {}
# If the form is permitted to be empty, and none of the form data has
# changed from the initial data, short circuit any validation.
if self.empty_permitted and not self.has_changed():
return
self._clean_fields()
self._clean_form()
self._post_clean()
def _clean_fields(self):
for name, field in self.fields.items():
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.initial.get(name, field.initial)
value = field.clean(value, initial)
else:
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError as e:
self.add_error(name, e)
def _clean_form(self):
try:
cleaned_data = self.clean()
except ValidationError as e:
self.add_error(None, e)
else:
if cleaned_data is not None:
self.cleaned_data = cleaned_data
def _post_clean(self):
"""
An internal hook for performing additional cleaning after form cleaning
is complete. Used for model validation in model forms.
"""
pass
full_clean() Model 6.
6 full_clean Model
full_clean() Model.
, , .
full_clean() clean_fields() exclude=exclude, clean(). validate_unique, exclude=exclude, get_unique_checks exclude=exclude, perform_unique_checks unique_checks, _perform_date_checks date_checks. , ValidationError errors.
:
def full_clean(self, exclude=None, validate_unique=True):
"""
Calls clean_fields, clean, and validate_unique, on the model,
and raises a ``ValidationError`` for any errors that occurred.
"""
errors = {}
if exclude is None:
exclude = []
else:
exclude = list(exclude)
try:
self.clean_fields(exclude=exclude)
except ValidationError as e:
errors = e.update_error_dict(errors)
# Form.clean() is run even if other validation fails, so do the
# same with Model.clean() for consistency.
try:
self.clean()
except ValidationError as e:
errors = e.update_error_dict(errors)
def validate_unique(self, exclude=None):
"""
Checks unique constraints on the model and raises ``ValidationError``
if any failed.
"""
unique_checks, date_checks = self._get_unique_checks(exclude=exclude)
errors = self._perform_unique_checks(unique_checks)
date_errors = self._perform_date_checks(date_checks)
for k, v in date_errors.items():
errors.setdefault(k, []).extend(envy)
if errors:
raise ValidationError(errors)
# Run unique checks, but only for fields that passed validation.
if validate_unique:
for name in errors.keys():
if name!= NON_FIELD_ERRORS and name not in exclude:
exclude.append(name)
try:
self.validate_unique(exclude=exclude)
except ValidationError as e:
errors = e.update_error_dict(errors)
if errors:
raise ValidationError(errors)
7 BaseModelForm.
, :
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=ErrorList, label_suffix=None, empty_permitted=False, instance=None):
opts = self._meta
self.instance = instance
object_data = model_to_dict(instance, opts.fields, opts.exclude)
object_data.update(initial)
super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data, error_class, label_suffix, empty_permitted)
for field_name in self.fields:
formfield = self.fields[field_name]
limit_choices_to = formfield.limit_choices_to
formfield.queryset = formfield.queryset.complex_filter(limit_choices_to)
BaseModelForm model_to_dict() instance, opts.fields opts.exclude, , update() initial, BaseForm. self.fields, complex_filter() limit_choices_to QuerySet.
7 BaseModelForm
balance() Account 8, 3.1.
8 balance Account
balance() Account.
balance() . , transaction in self.transactions_to.all transaction in self.transactions_from.all, +amount, , , -amount.
9 clean Category.Model.
9 clean() Category.Model
clean() Category.Model.
clean() ( filter()). , , , , ValidationError. , .
, , .
, .
, , , , , .
, , TestCase. TestCase ( , , ). (asserts) [9]. - test_.
, .
Place
Place . , .
.
class PlaceTest(TestCase):
def test_null_place(self):
with self.assertRaises(IntegrityError):
p = Place()
p.save()
def test_place_without_user(self):
with self.assertRaises(IntegrityError):
p = Place.objects.create(
name='test',
)
Category
Category , , name . , ( , ).
.
class CategoryTest(TestCase):
def test_trycategoryname(self):
user = get_user_model().objects.create(
username='test',
)
cat = Category(name='TestCategory', parent=None, user=user)
self.assertEqual(cat.__str__(), 'TestCategory')
def test_cleancategory(self):
user = get_user_model().objects.create(
username='test',
)
Category.objects.create(name='test', user=user)
cat2 = Category(name='test', user=user)
self.assertRaisesMessage(ValidationError, 'Name must be unique', cat2.clean)
def test_trycategorynamethesameparent(self):
user = get_user_model().objects.create(
username='test',
)
parent = Category.objects.create(name='parent', user=user, parent=None)
Category.objects.create(name='child', user=user, parent=parent)
child = Category(name='child', user=user, parent=parent)
self.assertRaisesMessage(ValidationError, 'Name must be unique', child.clean)
Transaction
Transaction , , account_from account_to, .
.
class TransactionTest(TestCase):
def test_double_amount(self):
user = get_user_model().objects.create(
username='test',
)
# Transaction.objects.create(account_from='test', account_to='test', user=user)
acc = Account(name='qwe', user=user)
acc.save()
trans2 = Transaction(account_from=acc, account_to=acc, user=user)
self.assertRaisesMessage(ValidationError, ' ', trans2.clean)
Account
Account balance, .
.
class AccountTest(TestCase):
def test_balance(self):
amount = Decimal(1.23)
user = get_user_model().objects.create(
username='test',
)
account = Account.objects.create(
name='test',
user=user,
)
Transaction.objects.create(
account_to=account,
amount=amount,
)
self.assertAlmostEqual(account.balance(), amount, 2)
, , .
PyCharm. 10.
10
, . , , PyCharm. , Run with Coverage ( 11).
11
12.
12
59% 92% . api, .
. (. Continuous Integration) , . , , . . [10].
Travis CI. Travis CI - , GitHub . GitHub, [11].
, , .
GitHub , webhook [12]. GitHub Sign in with GitHub, 13.
13 Travis CI
. 14.
14
.travis.yml, , , , . .
language: python
python:
- "3.2"
- "3.3"
# command to install dependencies
install: "pip install -r requirements.txt"
script:
- "flake8."
- "python manage.py test"
, script. flake8., , .
.
, Travis CI , Failed, Passed, .
5.4
- 15. Linux - Apache. , Firefox Windows.
, -, Python Django.
- , Django Apache mod_wsgi PostgreSQL [13].
15
MoneyTalks - . , , .
:
- ;
- , , , ;
- , , ;
- .
MoneyTalks , , .