質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.79%

modelで定義したメソッドを呼び出したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,545

shohei0718

score 17

開発環境

Python 3.7.1
Django version 2.1.5

困っていること

models.pyに集計ロジックの関数を記述し、views.pyでその関数を呼び出すことで、データの集計作業をしたいと考えています。
しかし、models.pyで集計ロジックを定義したインスタンスメソッド(def total_price(self))をviews.pyで呼び出すとエラーが出てしまい、困っています。
何か良い方法があれば、ご教授頂けますと幸いです。

出ているエラー内容

TypeError at /invoice_index
unsupported operand type(s) for +: 'function' and 'int'

Lovcal Vars
...
english_invoice     <function BillingPriceCalculator.total_price at 0x1076cdd90>

コード

class Lesson(models.Model):
  name = models.CharField('ジャンル', max_length=255)
  flat_price = models.PositiveIntegerField('基本料金', null=False, default=0)

  def __str__(self):
    return self.name

  def calculate_measured_price(lesson_hour):
    lesson_measured_price = LessonMeasuredPrice.objects.select(record, record.lesson_hour <= lesson_hour ).sort_by(lesson_hours).last
    lesson_measured_price.price

class LessonMeasuredPrice(models.Model):
  lesson_id = models.ForeignKey(Lesson, on_delete=models.PROTECT)
  price = models.PositiveIntegerField('金額', null=False, default=0)
  threshold_hours = models.PositiveIntegerField('受講時間(h)', null=False, default=0)


class CustomerLesson(models.Model):
  customer = models.ForeignKey(Customer, verbose_name='顧客名', on_delete=models.PROTECT)
  lesson = models.ForeignKey(Lesson,verbose_name='ジャンル', on_delete=models.PROTECT)

  lesson_date = models.DateField('受講日')
  lesson_hour = models.PositiveIntegerField(
    '受講時間(h)',
    default = 1,
    validators=[
      MaxValueValidator(12),
      MinValueValidator(1)
    ]
  )

  def __str__(self):
    return self.lesson

class BillingPriceCalculator:

  def __init__(self, lesson, customer_lessons):
    self.lesson = lesson
    self.customer_lessons = customer_lessons

  @staticmethod
  def total_price(self):
    flat_price + measured_price


  def __flat_price(self):
    lesson.flat_price

  def __measured_price(self):
    measured_price_unit * total_hours

  def __total_hours(self):
    customer_lessons.sum(lesson_hour)

  def __measured_price_unit(self):
    lesson.calculate_measured_price(total_hours)
def invoice_index(request):

  today = datetime.today()

  #今月の月初日と月末日の算出
  month_start = today.replace(day=1)
  next_month_start = (today + relativedelta(months=1)).replace(day=1)
  month_end = next_month_start - timedelta(days=1)

  customers = Customer.objects.all()
  sum_template =  {'英語': 0, 'ファイナンス': 0, 'プログラミング': 0}
  invoice_list = []

  for customer in customers:
    columns = {}
    english_invoice = 0
    finance_invoice = 0
    programing_invoice = 0

    genre_sum = sum_template.copy()
    lesson_hour_sum = sum_template.copy()

    lessons = customer.customerlesson_set.all()
    this_month_lessons = lessons.filter(lesson_date__range=(month_start, month_end))
    lesson_sum = this_month_lessons.count()

    columns['id'] = customer.id
    columns['name'] = customer.name
    columns['lesson'] = lesson_sum

    for lesson in this_month_lessons:
      lesson_date = lesson.lesson_date
      columns['lesson_date'] = lesson_date

      genre = lesson.lesson.name
      genre_sum[genre] += 1
      columns['genre'] = genre_sum

      lesson_hour = lesson.lesson_hour
      lesson_hour_sum[genre] += lesson_hour
      columns['lesson_hour'] = lesson_hour_sum

      if genre == '英語':
        english_invoice = BillingPriceCalculator(genre, this_month_lessons).total_price
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

total_priceをstaticmethodにするならselfを引数に取ってはいけませんし、インスタンスメソッドならstaticmethodデコレータを付けてはいけません。

english_invoice = BillingPriceCalculator(genre, this_month_lessons).total_pricetotal_priceを呼び出していないので、メソッドオブジェクトがenglish_invoice変数に代入されるだけです。呼び出したければ後ろにかっこをつけます。

total_priceを呼び出したとしてもreturn文がありませんので、Noneが返り無意味というか動きません。

ほかにもdjango以前におかしい気がする部分は多数あるので、pythonの基礎をやるのが先という感じがします。rubyに慣れている人かもしれませんが、文法違うので。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/03 18:51

    hayataka2049さん
    total_priceを呼び出すことができました。
    まだPythonの学習を始めたばかりなので、改めて基礎文法から勉強し直します。

    キャンセル

0

関数の戻り値は、明示的にreturnで返す必要があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/03 18:50

    Meganezaruさん有難うございます。
    返り値がNoneではありましたが、returnで返ってきました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る