Лучше изменить схему БД? - PullRequest
0 голосов
/ 16 января 2011

Я создаю веб-приложение с Django.Я использую postgresql для БД.Код приложения становится действительно запутанным (мои начальные навыки важны) и медленным, даже когда я запускаю приложение локально.

Это отрывок из моего файла models.py:

REPEATS_CHOICES = (
    (NEVER, 'Never'),
    (DAILY, 'Daily'),
    (WEEKLY, 'Weekly'),
    (MONTHLY, 'Monthly'),
    ...some more...
)

class Transaction(models.Model):
    name = models.CharField(max_length=30)
    type = models.IntegerField(max_length=1, choices=TYPE_CHOICES) # 0 = 'Income' , 1 = 'Expense'
    amount = models.DecimalField(max_digits=12, decimal_places=2)
    date = models.DateField(default=date.today)
    frequency = models.IntegerField(max_length=2, choices=REPEATS_CHOICES)
    ends = models.DateField(blank=True, null=True)
    active = models.BooleanField(default=True)
    category = models.ForeignKey(Category, related_name='transactions', blank=True, null=True)
    account = models.ForeignKey(Account, related_name='transactions')

Проблема с датой, частотой и окончаниями.С помощью этой информации я могу знать все даты, в которые происходят транзакции, и использовать ее для заполнения таблицы денежных потоков.Для этого нужно создать много структур (словарей, списков и кортежей) и многократно повторять их.Может быть, есть очень простой способ решить эту проблему с помощью действующей схемы, но я не мог понять, как это сделать.

Я думаю, что приложение будет проще для программирования, если при создании транзакции я смогсохранить все даты в БД.Я не знаю, возможно ли это или это хорошая идея.

Я читаю книгу о движке приложений Google и многозначных свойствах хранилища данных.Что вы думаете об этом для решения моей проблемы?

Редактировать: я не знал о PickleField.Сейчас я читаю об этом, может быть, я мог бы использовать его для хранения всех объектов datetime транзакции.

Edit2: это отрывок из моего представления cashflow2 (извините за ужасный код):

def cashflow2(request, account_name="Initial"):

if account_name == "Initial":
    uri = "/cashflow/new_account"
    return HttpResponseRedirect(uri)     
month_info = {}
cat_info = {}
m_y_list = [] # [(month,year),]
trans = []
min, max = [] , []

account = Account.objects.get(name=account_name, user=request.user)
categories = account.categories.all() 
for year in range(2006,2017):
    for month in range(1,13):
        month_info[(month, year)] = [0, 0, 0]
        for cat in categories:
            cat_info[(cat, month, year)] = 0

previous_months = 1 # previous months from actual
next_months = 5
dates_list = month_year_list(previous_month, next_months) # Returns [(month,year)] from the requested range
m_y_list = [(date.month, date.year) for date in month_year_list(1,5)]
min, max = dates_list[0], dates_list[-1]
INCOME = 0
EXPENSE = 1
ONHAND = 2
transacs_in_dates = []
txs = account.transactions.order_by('date')

for tx in txs:
    monthyear = ()
    monthyear = (tx.date.month, tx.date.year)
    if tx.frequency == 0:
        if tx.type == 0:
            month_info[monthyear][INCOME] += tx.amount
            if tx.category:
                cat_info[(tx.category, monthyear[0], monthyear[1])] += tx.amount
        else:
            month_info[monthyear][EXPENSE] += tx.amount
            if tx.category:
                cat_info[(tx.category, monthyear[0], monthyear[1])] += tx.amount
        if monthyear in lista_m_a:
            if tx not in transacs_in_dates:
                transacs_in_dates.append(tx)
    elif tx.frequency == 4: # frequency = 'Monthly'
        months_dif = relativedelta.relativedelta(tx.ends, tx.date).months
        if tx.ends.day < tx.date.day:
            months_dif += 1
        years_dif = relativedelta.relativedelta(tx.ends, tx.date).years
        dif = months_dif + (years_dif*12)
        dates_range = dif + 1
        for i in range(dates_range):
            dt = tx.date+relativedelta.relativedelta(months=+i)
            if (dt.month, dt.year) in m_y_list:
                if tx not in transacs_in_dates:
                    transacs_in_dates.append(tx)
            if tx.type == 0:
                month_info[(fch.month,fch.year)][INCOME] += tx.amount
                if tx.category:
                    cat_info[(tx.category, fch.month, fch.year)] += tx.amount
            else:
                month_info[(fch.month,fch.year)][EXPENSE] += tx.amount
                if tx.category:
                    cat_info[(tx.category, fch.month, fch.year)] += tx.amount

import operator
thelist = []
thelist = sorted((my + tuple(v) for my, v in month_info.iteritems()),
             key = operator.itemgetter(1, 0))
thelistlist = []
for atuple in thelist:
    thelistlist.append(list(atuple))
for i in range(len(thelistlist)):
    if i != 0:
        thelistlist[i][4] = thelistlist[i-1][2] - thelistlist[i-1][3] + thelistlist[i-1][4]
list = []
for el in thelistlist:
    if (el[0],el[1]) in lista_m_a:
        list.append(el)

transactions = account.transactions.all()

cats_in_dates_income = []
cats_in_dates_expense = []
for t in transacs_in_dates:
    if t.category and t.type == 0:
        if t.category not in cats_in_dates_income:
            cats_in_dates_income.append(t.category)
    elif t.category and t.type == 1:
        if t.category not in cats_in_dates_expense:
            cats_in_dates_expense.append(t.category)

cat_infos = []
for k, v in cat_info.items():
    cat_infos.append((k[0], k[1], k[2], v))

1 Ответ

1 голос
/ 17 января 2011

Зависит от того, насколько актуален App Engine здесь. Постскриптум Если вы хотите хранить как маринованные объекты, так и объекты JSON в хранилище данных Google, ознакомьтесь с этими двумя фрагментами кода:

http://kovshenin.com/archives/app-engine-json-objects-google-datastore/ http://kovshenin.com/archives/app-engine-python-objects-in-the-google-datastore/

Также обратите внимание, что Google Datastore является нереляционной базой данных, поэтому у вас могут возникнуть другие проблемы с рефакторингом кода для перехода на него.

Ура и удачи!

...