脱職エントリー

いつか退職エントリーを書いて一人前のエンジニアを名乗りたい

DjangoRest FrameWorkで違うSerializerのfieldを使い回す方法

タイトルが長いですね

何がやりたかったかというと簡単な話です

親のSerializer   
    fields =('項目A', '項目B', '項目B', '項目C')   
子のSerializer   
    親のFields に加えて 項目D

継承使えば簡単でしょって思ってたんですが結果的には継承では上手くいかないことが分かったので

class BaseSerializer(serializers.ModelSerializer):

    class Meta:
        model = Mymodel
        fields = ('field_a',  )

class ChildSerializer(BaseSerializer):
    field_b = serializers.CharField()

    class Meta:
        model = Mymodel

    def __init__(self, *args, **kwargs):
        self.Meta.fields = list(BaseSerializer.Meta.fields)
        self.Meta.fields.append('field_b')
        super(ChildSerializer, self).__init__(*args, **kwargs)

def init()で親のfieldsを読み込むなんて、これ継承の意味ないじゃんって気もします
Childの方のfieldsに何かを書くと上書きされてしまうので意味がないし、Baseのfieldsに全部書いておいて不要項目を取り除きながら使う方法もありますが、それだとSerializer呼ぶところ全部に必要項目渡さなきゃ行けないしちょっとめんどい、childの方にfield_aとbを宣言する方法も採れますが、いまいち感満載。

なんか良い方法あるんだろうなぁと思いつつとりあえず自分なりの解決方法だけ残しておきます

pythonチュートリアル メモ 後半

pythonチュートリアル第3版を読んでみてのメモになります。
付箋紙を貼りながら読み進めるスタイルだとブログにまとめる際に楽なので今後もこのスタイルで読書していこうと思います。
自分が知らなかったこと、気になった部分だけどを抽出しているだけなのでpythonを学ぶ上での普遍的な重要ポイントを書き出してるわけではないことをご了承ください。

www.oreilly.co.jp

6章 モジュール

特になし

7章 入出力

ゼロパディングするとき

'12'.zfill(5)
>>>'00012'

フォーマット関数にキーワード引数を取れる

"お賃金は{money}円です".format(money="5000兆")
8章 エラーと例外

tryにコードを追加せずにelseに後続処理を書いた方が、
後続処理で予期せず同じ例外をキャッチしてしまう問題を回避出来る。

→だいたいtryの後続にそのまま書いていたので、新鮮な書き方でした。
とはいえ0で割るエラーとかは割り算でしか起こりえないし、他の行で同じエラーが起こることってあんまりないような気もします。
個人的にはtry節にそのまま書いていってもいいんじゃないかなぁと

try:
    エラーを予見する処理
 except:
    例外処理
else:
   エラーにならなかった時の処理
9章 スコープと名前空間

説明が難しいけどこういうことができる。
外側のスコープの変数の値を更新出来る

def friends_test():
    def nonlocal_friends():
        nonlocal friend
        friend = "すっごーい"

    frined = "〜なフレンズなんだね"
    nonlocal_friends()
    print(friends)
>>>  "すっごーい"
10章 標準ライブラリめぐり

関数のコメントを実行出来る

def gacha_cost(cost)
    """
    >>> print(gacha_cost(3000))
    0
    """
    return 0
import doctest
doctest.testmod()
11章〜14章

特になし

15章 浮動小数点(float)の演算:その問題と限界

浮動小数点についての誤差とかの話が書かれてましたが正直よく分からない(分かろうという気がなかった)

付録 用語集

こういう表現をするんだってのを知ったものだけピックアップ
EAFP(ごめんなさいはお願いしますより楽):try〜catchするような処理
LBYL(飛ぶ前に見ろ/転ばぬ先の杖):キーがあるかどうか先に調べてif文なんかで先に聴いておくような書き方

感想

知っておくと便利だったなぁと思えることが色々出てきたので細かいところが読み飛ばして役立つところだけピックアップして読むにはよかったかなぁと思います。

正直名前空間の説明と浮動小数点の誤差とかの説明はよく分からなかったので基本情報ぐらい取ってコンピューターの基礎でも勉強した方がいいかなぁと思うばかり
pythonは標準モジュールや組み込み関数が充実してるのでその辺をもっと知れたらなぁと思うばかり

pythonチュートリアル メモ 5章まで

とりあえず読んでて知らなかったこと、知らなかったけど便利そうな書き方や考え方を見つけ次第メモしていこうと思います
いわゆるチラシの裏ってやつです

pythonチュートリアル

1章

特になし

2章

特になし

3章

・raw文字列を使うと正規表現を無視できる

r'c:\name'
\nの部分を改行として扱わなくなる

・文字列は変更不能体(immutable)
・リストは変更可能体(mutable)
・print関数にendを渡すと表示するたびの末尾に好きな文字を入れられる。
for i in range(100):
    print(i, end=",")

>>0,1,2,3,4・・・

四章

・range()などを反復可能態(itarable)と呼ぶ
・ラムダを使って配列内のタプルのソート
>>>sphere = [(1, 'toyosaki'), (2, 'kotobuki'), (3, 'takagaki'), (4, 'tomatsu')]
>>>sphere.sort(key=lamda member: member[1])
 [(2, 'kotobuki'),  (3, 'takagaki'), (4, 'tomatsu'), (1, 'toyosaki')]
関数名.docで関数の下のコメント行が呼び出せる

5章 リスト

・list名.pop()すると最後に追加された要素を取り出す
aqours= ["千歌", "曜"・・・]
aqours.append("黒澤ダイヤ")
aqours.pop()
黒沢ダイヤ
・辞書の作り方

tika_idle = dict(name="maison book girl ", rebel="tokuma", members=4)

個人的には下の書き方よりもクォーテーションを書かなくて済む分好きかもしれません。

{"name": "maison book girl",
 "rebel": "tokuma",
 "members": 4}

今回読書した分をブログにまとめるために改めて読み返しましたが、時間の無駄なので今後は読書のたび付箋紙とか貼り付けたほうがいいなぁと思いましたkindleとかって付箋紙的な機能あるのかな

オブジェクト指向設計実践ガイド 読書会 第二章のメモ

ギーラボで2週間に一回行っている読書会の第二章のまとめです

 

 

 

本書全体ですが具体例がギアがどうとかタイヤの直径を計算するクラスの実装で話が進むので自転車の仕組みに詳しい人のほうが読みやすいと思います。

自転車乗りでrubyに詳しい人なら一人で読みすすめられるんじゃないでしょうか。

 

gihyo.jp

 

第二章 単一責任のクラスを設計する

コードを書く上で重要なことはTrue

・見通しが良い(Transparent)

・合理的(Reasonable)

・利用性が高い(Usable)

・模範的(Exemplary)

 

自転車のコグ(cog)をギアの歯数(chainring)で割るとratio(車輪が何回転するか)が求められるので

ギアクラスを作ってcogとchainringを与えるとratioが帰ってくるクラスを作れば良いのですがそこにリムの直径とタイヤの厚みが入ってきて・・という話でどう書くかという話が進みます。

 

・class gear(歯数, コグ, リム, タイヤ)

 def ギア比

           return 歯数/コグ

 def ギアインチ

   return ギア比×(リム+ (タイヤ×2))

 

単純には引数を4つにすればいいんですけど、それだと従来の歯数とコグからratioを求める処理が落ちてしまう。

 

クラスが単一責任かどうか見極める

見極め方が乗っていました。今後参考にしてみたいと思います。

>クラスの役目を文章にしてみて、「それと」や「または」が入っていたら複数の責任を負っていることが分かる

 

クラスを分けるべきかどうか

本書ではクラスを分ける手間とコストによって分けてもわけなくても良いんじゃないか、決断を先延ばしでもいいじゃんという話が続きます。

別のクラスの作成

本書では最終的には他の要件がでてきたため、クラスをわけてwheelクラスを作ることになります。

まとめ

変更可能でメンテナンス性の高いオブジェクト指向ソフトウェアへの道のりは単一責任クラスから始まるということで、一つのクラスは一つの責任になるようにしましょうねということで締められていました。

 (でも分けるかどうか悩ましい段階なら決断先送りでもいいよねとも)

感想

rubyの知識がないので有識者の方に随分助けられましたが、その一方でrubyの言語仕様に気になってしまいそちらに話が流れてしまったのでもっとちゃんとオブジェクト指向についてあまり考えられなかったなぁと。

 

クラスへの引数にクラスを渡すって発想はなかったのでこれは活かしていきたいなと思いました。

 

第三回の登録はこちらから!

nseg.connpass.com

 

PyCon JP 2017のブース出展の反省点

09/08〜09/09に早稲田大学西早稲田キャンパスで行われた「PyCon JP 2017」にスポンサーブースとして参加したので反省点を書いていこうと思います。

 

hololensを展示したことについての反省点

弊社が清水の舞台から飛び降りるつもりで買ってしまったhololens、こいつを使わない手はないとhololensありきでイベント準備を進めましたが・・・結果的にはpyconのような手狭で時間も短いイベントでは使うべきではないという話になります。

(※hololens自体は神がかりガジェットですが何事も用途があります)

 

1.ユーザーに操作をさせるのは大変 

正直言って始めてhololens掛ける人に操作説明するのはとても大変でした。
2日目からは3秒経ったらアクションを開始するように修正しました。

2.一回の体験に時間が掛かる

pyconの忙しいスケジュールを縫ってブースに訪れた人たちにhololens掛けてもらうのは貴重な時間を奪うことになります。

3.何をやってる会社か伝わらない

弊社はDjangoを中心としたwebの請負みたいな仕事をやっている会社なのですが、hololens+unityなんて展示物を出してしまったがために、何しにpyconに来てるのかよく分からない謎の会社になってしまったように思われてしまったのかも知れません。

一応、unityからDjango RestFrameworkで作ったレストフルなwebapiを呼んでるところがだったのですが、伝わりにくくなってしまいました。
ちなみに弊社は事業としてunityなどを扱ったことはありません。 

 

自社サービスもなく、基本なんでも作るのでお仕事くださいってスタンスなので見せられる製品がないコンプレックスの裏返しでみんなが驚くモノを作ろうと熱意が暴走した結果でもあります。

偶然弊社ブースにお越し頂いて偶然上手くいったMR体験出来た方はおめでとうございます。

うまく見えなかった方には申し訳ございません。きちんとした体験会に行けば素晴らしい体験ができます!弊社の力不足です。

 

 ブース出展よりもやるべき事があるのかも 

弊社はこんなことできますよ〜ってアピールするならやっぱり講演するLTするなどでプログラミングやインフラの知識をきちんとアピールすることが大事なのかも知れません。
本来はそれを見せるためにDjango製のアプリを出していましたが、 hololensという飛び道具に飛びついた結果失敗してしまったように感じます。

 

ブースにいると講演を聞き逃す

ブースにいて話込んでいるとつい時間を忘れて自分が聴こうと思っていた講演を聞き逃してしまいます(自分はそれで二つ聞き逃しました)

 

エンジニア兼ブース担当兼営業的な動きというフルスタックな動きには限界を感じました。

良いことも言っておかないと辛い

とりあえず、hololensだしてた変な会社ということで認知が頂ければ弊社としてはいいのかなぁと思ったり思わなかったり

後は反省点は多くとも結構な熱量をpyconに注ぐことができたので来年リトライする機会に恵まれたらもっとシンプルで驚きのある物を作りたいなぁと

 

0から1へ、というラブライブ!サンシャイン!!のテーマを旨に来年のpyconではもう少し色々自己顕示欲を形にできればなぁと思います。

pycon一週間前なので去年の反省点を残しておきたい

pycon一週間前ですね!
今年は弊社日本システム技研もスポンサーとして参加しております。
なんか色々やる予定ですので、是非無銭がっつきでお越しください!

 

自分は去年がpyconが初参加だったのですが、その時の反省点が多々あるので今年参加される方の参考になればと思い恥を忍んで色々書き出しておこうと思います。

1.ノートPCのバッテリーに注意

 普通に使っていると電源は一瞬で終わってしまいますので色々気をつけたほうが良いと思います。

 ・画面はぎりぎりまで暗くする←超大事
 ・chromeは使わない
 ・しかし、ツイートはやめない!!
 ・広い部屋の後ろの方は席は公演聞きながら充電できるよ!(一日目の後半などはみんな電源が少なくなってくるので取り合い必死か?)

2.懇親会で人間違い

 僕「○○の話をした人ですよね」
 その人「えっ違います」

 公演した人の顔と名前ぐらいちゃんと覚えておきましょう。
 自分で言うのもなんですが大変失礼な行為だと思っています。

 とはいうものの、人に話しかけないよりは良いのかなと思ってます。
 懇親会ぼっちで終わってしまうのはもったいないですよね。僕はぼっちで終わる人です。

3.有名人ぐらい覚えていこう

 僕「○○社の△△って方と名刺交換しました~」
 自社の先輩「おいその人って有名な△△さんやで!!」
 僕「まじっすか。しらんかったです」

 pythonコミュニティの人を全然知らなかったので、普通に接してしまいました。
 知っていれば会話ももっときっかけがあったのになぁと思ってしまいます。
 まぁでも有名人相手だと萎縮してしまうので無知はある意味強いのかもしれませんが有名人と話すときにあの本読みました~とかあのサービス使ってますとかあのプレゼン聞きました~とかきっかけが増えるので知ってた方がいいんだろうなと思いました。

4.あんまり他人に積極的になれなかった

f:id:darakunomiti:20170902141731p:plain

日本人って基本的にシャイだと言われていますがIT産業に従事する人はその傾向がより強いんじゃないかと思っています(僕はその中でもとりわけ強いです)

会話が始まるといいのですがきっかけが難しいですね。。だって誰だかわからないところに突然乱入していって、「僕長野の零細企業でDjangoでwebapi作ってます!アニメ見たり地下アイドル現場にかよってます!好きなアニメは大正野球娘。ラブライブ!サンシャイン!!です!」
なんて言っても「は?」って感じじゃないですか、どうやって会話に入るのか誰か教えください。多分、会話のきっかけになる要素が事前に分かってるといいんですよね。
はいえあれだけ人がいる中でFBのお友達やツイッターのお友達が全然増えないのはちょっともったいなかったなぁと、、絶対に接点さえあれば仲良く慣れる人はいるんじゃないかと思います。

まぁ僕自身友達づくりが苦手なフレンズってことは重々承知ですが・・

 

余談ですが声優さんのお渡し会のときはイベント関連作品のアニメに関するグッズなどを装着していればきっかけには困らないし相手の笑顔も見れるので成功体験になります。作品主体のお渡し会のときはおすすめ。

pyconの懇親会で話すのは声優さんでも地下アイドルちゃんでもありませんが)

5.去年聞いた話が全然活かされてない!

色々な話を聞いた気がしますが、実務に繋がったって話はなかったなぁと
まぁ、去年~今年はお仕事ではDjangoでwebapiを作っていただけだったので、活かすような話もなかったのですが、今年は講演を聞いてその中から一つだけでも手を動かして接してみようと思います。

6.PR

弊社日本システム技研のスポンサーブースが出ます!
※下記はイメージ画像です

f:id:darakunomiti:20170902140015j:plain

 

簡単なゲームや景品も用意していますので是非お立ち寄りください!

自分がいる時間には地下アイドルやアイドル声優事情や現代サブカルチャーの話題なんかを振っていただければ喜びます!

 

※こちらを恨めしそうに見つめているペッパーはこれません

DjangoRestFrameWork ネストしたフィールドにユニークキーが含まれる時、updateで一意制約違反

元ネタ stackoverflow.com

先に解決法だけ見たい人は

class MemberSerializer(serializers.ModelSerializer):
    """各メンバ-エリア"""

    class Meta:
        model = Member
        fields = ('id', 'name', 'birthday', 'coler')
     # ユニークキーの入力チェックを外す
        extra_kwargs = {
            'name': {'validators': []},
        }

やりたかったこと

例えば、アイドルの名前は、エゴサ、パブサで検知しやすいように、全作品でユニークになっていなければならないとします。
で、グループ名や結成時期とメンバーの情報をapi一本で更新したいとするじゃないですか。
そうするとシリアライザーは多分こんな感じ。

selializer.py

class MemberSerializer(serializers.ModelSerializer):
    """各メンバーエリア"""

    class Meta:
        model = Member
        fields = ('id', 'name', 'birthday', 'coler')


class UnderGroundIdleSerializer(serializers.ModelSerializer):
    """アイドルのグループ名"""

    members = MemberSerializer(many=True, source='members', required=False)

    class Meta:
        model = UnderGroudIdle
        fields = ('id', 'name', 'members')

View.py

class IdleViewSet(viewsets.ModelViewSet):

    pagination_class = PostPagination
    queryset = UnderGroundIdle.objects.all().prefetch_related('members')
    serializer_class = UnderGroundIdleSerializer
    parser_classes = (MultipartFormencodeParser, JSONParser,)

    @transaction.atomic
    def update(self, request, *args, **kwargs):
        """特に意味はないけど分かりやすく可視化"""
        responce = super().update(request, *args, **kwargs) ★ここが重要になってきます
        return responce

postする時のjsonはこんな感じ(他のメンバーごめんなさい)

{
    "name": "Aqours",
    "members": [
        {
            "birthday": "3-4", 
            "coler": "Yellow", 
            "name": "国木田花丸"
        }, 
        {
            "birthday": "4-17", 
            "coler": "Blue", 
            "name": "渡辺曜"
        }
    ]
}

なんですが、これをこのままputすると、一意制約違反エラーとなってしまいます。(国木田花丸渡辺曜がすでに存在するというエラー)

原因

Djangoの入力値のチェックで何故かinsert時と同じチェックをしている。。

responce = super().update(request, *args, **kwargs) ★ここから呼ばれるのが以下のクラス

class UpdateModelMixin(object):
    """
    Update a model instance.
    """
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True) ★ここでエラーが起きる
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

対策

リアライザーでチェック処理を外す指定ができる。

class MemberSerializer(serializers.ModelSerializer):
    """各メンバ-エリア"""

    class Meta:
        model = Member
        fields = ('id', 'name', 'birthday', 'coler')
   # この2行を追加
        extra_kwargs = {
            'name': {'validators': []},
        }

こうするとチェック処理が動かなくなるので自前でvalidateを書くなどの処理でupdateが出来るようにしました。
もちろんDjangoでチェックしなくてもデータベースから一意制約違反のエラーは出てくるので結果的には一意制約を保つことができます。(なんか嫌ですが)

ネストしたモデルシリアライザーって結局自前でupdateしなきゃ行けないのにチェック処理は全部クリエイト基準で行われるってなんか微妙な感じ。。