diadia

興味があることをやってみる。自分のメモを残しておきます。

requestsメモ

少し整理してみる

requestsドキュメント

http://jp.python-requests.org/en/latest/

requests.get,postの引数params,dataの違い

paramsはurlをカスタマイズするイメージで捉えておけば良い。第一引数に加えてparamsのデータをurlに加える。
dataの場合はrequestsで取得したhtmlのフォームにdataの内容を送信する。dataを使うのはpostが前提である。

引数dataをもっと詳しく

 

URL = "https://**********"
contents = {"name":"Chiaki"}
requests.post(URL, data=contents)

この場合自動的にエンコードされて(byte型にかえて)送信される。
エンコードさせないで送りたい場合は以下のようにする。データ型をdictからstringに変えるだけで良い。これはAPIのときに使った。

URL = "https://**********"
contents = {"name":"Chiaki"}
requests.post(URL, data=json.dumps(contents))

mailchimpを使ってみる

mailchimpを使ってみて感じたこと

最近色々な種類のapiをいじった結果、感想がある。様々なサービスのapiを使うためにあまり負担をかけずに使うためのものだ。自分の場合、apiを使うために毎度たくさんの学習コストがかかるのが負担だった。しかし最終的に実現した過程を客観的に見ると今まで経験したものには一定の法則があった。独学でやっているためにおそらく常識的な内容だが、自分のために残しておこうと思う。

apiでの操作は、requestsでpostまたはgetして送りたいデータを送ることだ。そして送りたい先(url)が機能部分を担当している。だから機能部分が要求するデータを要求通りに送ると機能は実現される。

どのようにapiに取り組むべきか

まずAPIのサービスがなんの機能を提供しているのか把握すること。次に自分が実現したい機能はなんなのかはっきりさせる。そして自分が実現したい機能が当該APIの機能の何に当たるかを探し当てて、そのurlを特定する。でそのurlがなんのデータを必要としているのか確認する。最後にrequestsで送りたいデータ(要求されているデータ)をurlに送りつける。こんな感じでやっていくと大きなストレスがかからずに取り組めると思う。

mailchimp apiドキュメントの場所

my page→profile→Extrasタブ→APIKeys→Read the API Documentation

mailchimpの仕組み

メールを送る相手のリストを作成する。 そのリストに送りたい相手を追加する。 そのリストをもとにメールを送る。

リストに送りたい相手を追加

https://developer.mailchimp.com/documentation/mailchimp/reference/lists/members/#%20

POST /lists/{list_id}/membersと書いてあるので、まずrequests.POSTを使う事がわかる。
urlは"/lists/{list_id}/members"なので、以下のようなコードになることがイメージできる。

requests.post("/lists/{list_id}/members")

次にurlが不完全なので完全なurlにすること、なんのデータを送ればよいのか明確にする必要がある。

完全なurlにする

 

なんのデータを送ればよいのか

練習としてlistデータを取得する

mailchimp apiを使う練習として以下のurlを参考にする。
https://developer.mailchimp.com/documentation/mailchimp/reference/lists/#%20

まずエンドポイントを確定させる。リンク先では"/lists"と書いてある。これをベースのエンドポイントにくっつけるとエンドポイントになる。

base_endpoint = "あとで"
URL = base_endpoint + "/lists"

ベースのエンドポイントはなにか?

ベースエンドポイントは、https://< dc> .api.mailchimp.com/3.0 である。そして< dc>部分を自分のdata center部分に置き換える。参照先:https://developer.mailchimp.com/documentation/mailchimp/guides/get-started-with-mailchimp-api-3/のResourcesの部分。

送るdataはないので以下のようにすれば、すべてのlistのデータを取得できる。

import requests
APIKey = "****************"
base_endpoint = "************"
URL = base_endpoint + "/lists"
response = requests.get(URL,auth=("",APIKey))
print(response.text)

django stripe 支払い請求をする

stripeの使い方イメージ

まずお客さんのカード情報をstripeにcheckout.jsまたはelementを使って送信する。するとそのお客さんのトークンが発行される。このトークンを使って支払い請求するようだ。それが以下のコードになる。でこのコードはサーバーサイドに書かれるもので、stripe APIsdkを使う。それは直下のコマンドで任意の環境下に入れておく。

pip install --upgrade stripe

#  https://github.com/stripe/stripe-python#installation

ドキュメント

stripe docs

https://stripe.com/docs/charges

stripe api reference

https://stripe.com/docs/api/charges/create?lang=python

メモ

# Set your secret key: remember to change this to your live secret key in production
# See your keys here: https://dashboard.stripe.com/account/apikeys
stripe.api_key = "sk_test_itU70BnUBk3oTQN3WiGzTh8T"

# Token is created using Checkout or Elements!
# Get the payment token ID submitted by the form:
token = request.form['stripeToken'] # Using Flask

charge = stripe.Charge.create(
    amount=999,
    currency='usd',
    description='Example charge',
    source=token,
)

amountはカートのトータル額を入れる。ここでamountを2000とすると、2000usd徴収することになる。
これはお客さんに提示する金額(formタグの金額)が999であってもこのamountが2000なら2000usd徴収することになる。
Cartオブジェクトのインスタンスとformタグ内の金額、そしてChargeのamountを連動するように結びつけるコードが必要となる。

運用のイメージ

まずカート精算時、またはその直前にstripeのChargeオブジェクトをcreateする。ChargeオブジェクトのデータをdjangoのChargeインスタンスにする。

Django stripe カード情報を登録する

stripeソースurl

https://stripe.com/docs/api/cards/create?lang=python

メモ

import stripe
stripe.api_key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"

customer = stripe.Customer.retrieve("cus_EPPm06zGJs6haY")
customer.sources.create(source="tok_mastercard")

これをCardクラスインスタンスに登録すればよいのか?わかったら更新する。。。

django stripeでpaymentページ作成

paymentのページを作成

djangoのhtmlファイルに書く場合を想定する。メモとして残す。

{% extends "base.html" %}
< >
{% block content %}


{% end block %}

block content にstripeで提供されるコードをコピペで実現できる。stripeのコードはこちらに有る。
https://stripe.com/docs/stripe-js/elements/quickstart
このページにResult, HTML, CSS, JavaScriptのタブがあり、それらを押すとコードが出てくるのでそれを次のように貼っていく。

HTMLコード貼り付け

{% extends "base.html" %}

{% block content %}
<script src="https://js.stripe.com/v3/"></script>

<form action="/charge" method="post" id="payment-form">
  <div class="form-row">
    <label for="card-element">
      Credit or debit card
    </label>
    <div id="card-element">
      <!-- A Stripe Element will be inserted here. -->
    </div>

    <!-- Used to display form errors. -->
    <div id="card-errors" role="alert"></div>
  </div>

  <button>Submit Payment</button>
</form>
{% end block %}

 

CSSコード貼り付け

cssコードはstyleタグでくるんで以下のように貼り付ける。

 

{% extends "base.html" %}

{% block content %}
<script src="https://js.stripe.com/v3/"></script>
<style >
/**
 * The CSS shown here will not be introduced in the Quickstart guide, but shows
 * how you can use CSS to style your Element's container.
 */
.StripeElement {
  background-color: white;
  height: 40px;
  padding: 10px 12px;
  border-radius: 4px;
  border: 1px solid transparent;
  box-shadow: 0 1px 3px 0 #e6ebf1;
  -webkit-transition: box-shadow 150ms ease;
  transition: box-shadow 150ms ease;
}

.StripeElement--focus {
  box-shadow: 0 1px 3px 0 #cfd7df;
}

.StripeElement--invalid {
  border-color: #fa755a;
}

.StripeElement--webkit-autofill {
  background-color: #fefde5 !important;
}
</style >
<form action="/charge" method="post" id="payment-form">
  <div class="form-row">
    <label for="card-element">
      Credit or debit card
    </label>
    <div id="card-element">
      <!-- A Stripe Element will be inserted here. -->
    </div>

    <!-- Used to display form errors. -->
    <div id="card-errors" role="alert"></div>
  </div>

  <button>Submit Payment</button>
</form>
{% end block %}

JavaScriptコード貼り付け

{% extends "base.html" %}

{% block content %}
<script src="https://js.stripe.com/v3/"></script>
<style >
/**
 * The CSS shown here will not be introduced in the Quickstart guide, but shows
 * how you can use CSS to style your Element's container.
 */
.StripeElement {
  background-color: white;
  height: 40px;
  padding: 10px 12px;
  border-radius: 4px;
  border: 1px solid transparent;
  box-shadow: 0 1px 3px 0 #e6ebf1;
  -webkit-transition: box-shadow 150ms ease;
  transition: box-shadow 150ms ease;
}

.StripeElement--focus {
  box-shadow: 0 1px 3px 0 #cfd7df;
}

.StripeElement--invalid {
  border-color: #fa755a;
}

.StripeElement--webkit-autofill {
  background-color: #fefde5 !important;
}
</style >
<form action="/charge" method="post" id="payment-form">
  <div class="form-row">
    <label for="card-element">
      Credit or debit card
    </label>
    <div id="card-element">
      <!-- A Stripe Element will be inserted here. -->
    </div>

    <!-- Used to display form errors. -->
    <div id="card-errors" role="alert"></div>
  </div>

  <button>Submit Payment</button>
</form>
<script>
// Create a Stripe client.
var stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');

// Create an instance of Elements.
var elements = stripe.elements();

// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
  base: {
    color: '#32325d',
    lineHeight: '18px',
    fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
    fontSmoothing: 'antialiased',
    fontSize: '16px',
    '::placeholder': {
      color: '#aab7c4'
    }
  },
  invalid: {
    color: '#fa755a',
    iconColor: '#fa755a'
  }
};

// Create an instance of the card Element.
var card = elements.create('card', {style: style});

// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');

// Handle real-time validation errors from the card Element.
card.addEventListener('change', function(event) {
  var displayError = document.getElementById('card-errors');
  if (event.error) {
    displayError.textContent = event.error.message;
  } else {
    displayError.textContent = '';
  }
});

// Handle form submission.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
  event.preventDefault();

  stripe.createToken(card).then(function(result) {
    if (result.error) {
      // Inform the user if there was an error.
      var errorElement = document.getElementById('card-errors');
      errorElement.textContent = result.error.message;
    } else {
      // Send the token to your server.
      stripeTokenHandler(result.token);
    }
  });
});

// Submit the form with the token ID.
function stripeTokenHandler(token) {
  // Insert the token ID into the form so it gets submitted to the server
  var form = document.getElementById('payment-form');
  var hiddenInput = document.createElement('input');
  hiddenInput.setAttribute('type', 'hidden');
  hiddenInput.setAttribute('name', 'stripeToken');
  hiddenInput.setAttribute('value', token.id);
  form.appendChild(hiddenInput);

  // Submit the form
  form.submit();
}
</script>
{% end block %}

django contenttypesフレームワークについて

contenttypesのドキュメントの理解をしてみる

djangoのシグナルを学習しているうちにcontenttypeを用いる可能性が出てきたのでドキュメントを読んで見る。

https://docs.djangoproject.com/ja/2.1/ref/contrib/contenttypes/

まずcontenttypesって言葉は?

この言葉はdjangoのみで使われる特殊な言葉かIT業界で一般に使われる言葉なのか?これが引っかかった。djangoを除いてcontenttypeと検索すると以下のように、ファイルの種類を表す概念だとわかる。
参照: https://qiita.com/AkihiroTakamura/items/b93fbe511465f52bffaa
したがってdjangoにおけるcontenttypeはdjango特有の概念であり、言葉である。

contenttypesについて

簡単なイメージはこうである。djangoにはContentTypeモデルが存在する。(django.contrib.contenttypes.models.ContentType)
このContentTypeモデルのインスタンスはprojectで作成したモデルの情報を貯えたりそのモデルを表す。そしてこのインスタンスはprojectのモデルを返してくれたり、モデルのインスタンスを返してくれたりする機能を持つ。

It's generally a good idea to have the contenttypes framework installed; several of Django's other bundled applications require it: The admin application uses it to log the history of each object added or changed through the admin interface. Django's authentication framework uses it to tie user permissions to specific models.

上記のようなことがdjango contenttypesを使うことで実現してほしい内容のようだ。

セットアップ

https://docs.djangoproject.com/ja/2.1/ref/contrib/contenttypes/#installing-the-contenttypes-framework
contenttypesはdjango-admin startproject **コマンドを打ち込んだら自動的にsettings.pyのINSTALLED_APPSのリストに加えられる。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',  #コレ
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',

INSTALLED‗APPSから消した場合でも'django.contrib.contenttypes'を付け加えればcontenttypesを使うことができる。

django signal (set of built-in signals)について

set of built-in signalsとは

djangoが提供しているできあいのシグナルである。これを使うとシグナルを自身でカスタムする手間が省け、開発のスピードとコーディングの精度を担保できる。具体的にはpre_save,post_save,request_finished等が挙げられる。これらについて分かったことを記載する。

request_finishedと自作シグナルはどのような違いが有るか?

違いを理解するためにまず自作(カスタム)シグナルでconnect()を使う場面を考えてみる。connect()の使い方は以下から確認することができる。
https://docs.djangoproject.com/ja/2.1/topics/signals/#listening-to-signals

自作(カスタム)シグナルでconnect()を使うまでの手順

まずconnect()とはSignalのインスタンスメソッドである。だから以下のように使うことが想定される。

Signalインスタンス.connect(引数)

上記で必要なのはSignalインスタンスを準備すること、そしてconnect()の引数を準備することだ。

Signalインスタンスを準備する

以下のようにするとSignalのインスタンスを作成できる。

from django.dispatch import Signal
signal_instance = Signal(providing_args=["hoge","HoGe"])

これでシグナルインスタンスが作れる。詳しいことはこちらのドキュメントを読むと良い。
https://docs.djangoproject.com/ja/2.1/topics/signals/#defining-signals

connect()の引数を準備する

connect()の引数はレシーバ(receiver)関数だ。

Signalインスタンス.connect(レシーバ関数)

レシーバ関数はdjangoに存在するものではなく自分で定めるものだ。通常の関数を定義するようにdefを使ってレシーバを定めれば良い。ただレシーバ関数を定めるときの条件として特定の引数を定めることが条件としてある。それはsenderと**kwargsである。詳しくは以下に書いてある。
https://docs.djangoproject.com/ja/2.1/topics/signals/#receiver-functions

def receiver(sender, **kwargs):
    return print("success")
カスタムシグナルのconnect()を使った例

上記の準備したものを組み合わせると以下のようになる。

signal_instance..connect(receiver)

request_finishedでconnect()を使うまでの手順

レシーバの準備
def receiver(sender, **kwargs):
    return print("success")

レシーバを準備すればもうconnect()を使える。

request_finished.connect(receiver)

これから言えることはrequest_finishedはsignalインスタンスとして扱う。だからsignalインスタンスを作る手間を省くことができる。

django signal(シグナル)について

シグナル関連記事

post_save,pre_saveの使い分けについて[仮説]

本題

私の場合djangoがはじめてのwebフレームワークで、djangoの仕組みを理解することは かなりハードルが高い。それはwebアプリケーションの仕組みの理解やフレームワークの概念の理解、フレームワークの運用上の知識、pythonの知識、サーバーの知識をいっぺんに求められることに起因していると思われる。そしてシグナルもよくわからない概念だったが少しずつ分かってきた。ドキュメントを読んでもピンとこないのはその概念をイメージできないことが原因だと思われる。日本人の誰かの概念のイメージに役立てば嬉しい。

シグナルについての参考資料

https://code-examples.net/ja/docs/django~2.0/topics/signals
受信と受信機機能の接続というものがあるらしい。ここでpre_save,post_save,m2m_changedを使う。シグナルの定義とか送信という別のテーマがある。これについてはpre_save,post_save,m2m_changedを使わない...?

m2m_changedについて

https://docs.djangoproject.com/ja/2.1/ref/signals/#m2m-changed

他のものと違ってactionという引数がある。受信に記載する。 senderにthrough等を追加して書かないといけない。
あと理解している人には当たり前だが、m2m_changedを使う場面でpost_saveを使っても期待通りの挙動は得られない。ManyToManyFieldにおいてシグナルを扱いたい場合はm2m_changedを使うこと。save()のあとにシグナルを発するからと言ってpost_savedでは上手くいかない。

シグナルはどこで記述するのか?

models.pyに記述する。 今の所わかっていること シグナルの定義 シグナルの発信 シグナルのレシーブ(コネクション?) これらがある。 これらを書く場所 signals.pyにシグナルの定義 views.pyにシグナルの発信 models.pyにレシーバの定義 コネクト 書き方 user_login=Signal(providing_args=["instance","request"]) user_login.send(sender=self.__class__, instance=user,request=request) def user_login_reciever(sender,instance,request,*args,**kwargs) user_login.connect(user_login_reciever)

シグナルの使い方少しわかった

シグナルのsend(),connect()について

send(),connect()はシグナルクラスのインスタンスメソッドである。だからsend(),connect()を使うためにはインスタンスを作らなければならない。

シグナルクラスのインスタンスを作る方法

以下のようにclass Signalを呼び出してインスタンスを作成する。

from django.dispatch import Signal
signal_instance = Signal(providing_args=["任意","にんい"])

connect()について

connect()の引数にはレシーバーを入れる。レシーバーはどんな動きをしてほしいかの内容をdefを用いて書く。

 レシーバーの定義に関しては引数に関する条件がある。引数はsenderと**kwargsである。

send()について

send()メソッドではsignalインスタンスで定義したproviding_argsの内容(これがkey)に対する値(value)を引数に設定する。またsenderもvalueを決めてあげる。send()を使う文脈だが、views.py内でシグナルを送りたいタイミングでsend()文を挿入する。

signal_instance.send(sender="ここを設定",任意="ここを設定",にんい="ここを設定")

pre_save(),post_save(),m2m_changedのシグナルの立ち位置について

今までpre_save(),post_save()についてシグナルの定義をしないで使っていたけど、よく考えればおかしい。どうして定義してインスタンスを作らなくても期待通りの動きをしてくれたのか?これについては、djangoの公式ドキュメントに記載されていた。
ドキュメント:https://docs.djangoproject.com/ja/2.1/topics/signals/

Django provides a set of built-in signals that let user code get notified by Django itself of certain actions. These include some useful notifications: django.db.models.signals.pre_save & django.db.models.signals.post_save Sent before or after a model's save() method is called. django.db.models.signals.pre_delete & django.db.models.signals.post_delete Sent before or after a model's delete() method or queryset's delete() method is called. django.db.models.signals.m2m_changed Sent when a ManyToManyField on a model is changed. django.core.signals.request_started & django.core.signals.request_finished Sent when Django starts or finishes an HTTP request.

最初の一文のDjango provides a set of built-in signals that let user code get notified by Django itself of certain actions.は、できあいのシグナルをdjangoは準備してくれていることを意味していて、その下に続く文章はdjangoが準備してくれているシグナルを表している。

要するに?

djangoでシグナルの機能を実装する際に、まず期待する挙動がdjango自体が用意してくれた下記のsignalで対応できるか考える。

  • django.db.models.signals.pre_save
  • django.db.models.signals.post_save
  • django.db.models.signals.pre_delete
  • django.db.models.signals.post_delete
  • django.db.models.signals.m2m_changed
  • django.core.signals.request_started
  • django.core.signals.request_finished

これらのシグナルで実現できない場合は、自分自身でカスタムしたシグナルを作成することになる。それはつまり、この段階でシグナルの定義(インスタンスを作った)りする。

シグナルの各要素の役割

Signalの定義で何の要素を渡すかを定義する。sendメソッドを使ってシグナルの発射タイミングを規定する。レシーバーで送られたシグナルの要素を加工する(挙動を指定)。そしてconnectメソッドでレシーバーとシグナルをつなげる。

GenericForeignKeyについてのメモ

GenericForeignKeyのメモ

GenericForeignKeyを調べる機会があったので重要そうなところをメモしておく。なおGenericForeignKeyはwebアプリケーションのデータ分析に役立つかもしれないと調べているが、その可否についても分かり次第記載したい。

参考url

https://docs.djangoproject.com/ja/2.1/ref/contrib/contenttypes/#generic-relations
Djangoで、GenericForeignKeyを使う

メモ

なんとなくforeignkeyと同じような機能をもちつつ、一つのモデルしかつながっていないForeignKeyをいろいろなモデルに繋げられるようにしたのがGenericForeignKeyだと思われる。こいつはmodels.pyでテーブルを作成するときに使われる。以下のようにしてモジュールを引っ張ってくる。

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

models.pyでの書き方

Class Hoge(models.Model):
    ...
    content_type   = models.ForeignKey(ContentType)
    object_id      = models.PositiveIntegerField()
    content_object = GenericforeignKey("content_type", "object_id")

ここで注意したいことは今までフィールド定義はmodels.のあとにCharfield,IntegerFieldやForeignKeyなど書いてきた。GenericForeignKeyにおいてはmodels.の記述無しで書くこと。これはimportでGenericForeignKeyを引っ張ってきているから当たり前なのだけれどもいつもの流れで書こうとすると間違ってしまうので注意。

また3行で1セット のようだ。content_type:モデルの種類、object_id:データの主キー、content_object:左記2つを統合する。

There are three parts to setting up a GenericForeignKey: 1. Give your model a ForeignKey to ContentType. The usual name for this field is "content_type". 2. Give your model a field that can store primary key values from the models you'll be relating to. For most models, this means a PositiveIntegerField. The usual name for this field is "object_id". 3. Give your model a GenericForeignKey, and pass it the names of the two fields described above. If these fields are named "content_type" and "object_id", you can omit this -- those are the default field names GenericForeignKey will look for.

1ではforeignKey()にContentTypeを渡す。で普通はそれをcontent_typeと呼ぶ。

content_type   = models.ForeignKey(ContentType)

 

2では関連付けたいと考えているモデルから得られるプライマリキー(主キー)の値を保存するフィールドを設定する。ほとんどのモデルでは主キーの値はPositiveIntegerFieldを意味する。そして普通はそれをobject_idと呼ぶ。

object_id      = models.PositiveIntegerField()

がん検診の受け方、使い方

がん検診の受け方、使い方を読んだ

がんは人類の解決すべき問題の一つだと感じている。がんを解決することでもっと大きく世界が広がっていくと思う。 ただ人類ががんに対してどこまで研究を進めてきているか知らないと思ったので、今後がんについての本も意識的に読んでみようと思う。

読んだ本:https://www.amazon.co.jp/dp/4822256243

メモ

タバコは肺がんの原因だと思っていたけど、その他の多くのがんの原因になる。アルコール、アセトアルデヒド、酢酸という流れでアルコールは代謝される。この流れのうちアルコール、アセトアルデヒドは発がん性がある。飲酒もまたおおくのがんの原因となることが知られている。一般的にしられているのは肝臓がんだけれども膵がんのリスクも高くなる。お酒を飲んだ場合、早く酢酸に変換できる人はガンのリスクは低いが顔が赤くなってしまう自分は他人よりガンリスクが高いことがわかった。

centos7にpythonやpipを入れる

centos7にepelを使う

以下のコマンドでepelをいれることができる。このepelを使ってpithon,pipを入れていく。各コマンドはrootユーザ出ない場合、sudoを付け加えること。

参考:https://cjsawer.whitewillow.co.uk/2018/08/29/epel-python-3-6-with-pip-on-centos-7/

yum install epel-release
# Install Python 3.6
yum install python36

# Install Pip from the RPM's internal "ensurepip" module
python3.6 -m ensurepip

# Symlink pip3 into /usr/bin for consistency and ease of use with sudo
ln -s /usr/local/bin/pip3 /usr/bin/pip3

epelの場合pythonを起動するときはpython36として起動する。
ちなみにiusの場合はpython3.6として起動する。

epelをいれる理由

centos7では保守的なリポジトリで構成されているので、使いたいソフトウェアが入っていないことが多い。centos7に相性の良いリポジトリの一つがepelである。epelをインストールすると、もともとインストールできなかったソフトウエアをyumで実現できるようになる。

 

epelについて

epelについての情報:https://fedoraproject.org/wiki/About_EPEL/ja

epelはfedoraで使っている環境(パッケージ)をcentosなどの互換ディストリビューションでも使えるようにすることが目的のようだ。

epel以外のpython,pipをcentosに入れる方法は?

レポジトリとしてius,PostgreSQLの公式レポジトリ,remiがepel以外にあるようだ。
PostgreSQLの公式レポジトリ:https://yum.postgresql.org/

https://xn--o9j8h1c9hb5756dt0ua226amc1a.com/?p=3196

yum install https://centos7.iuscommunity.org/ius-release.rpm
yum info python36u

pipは別なのでpipもインストールする

yum install python36u python36u-pip python36u-devel

pipのバージョンが古いのでアップグレードしておく。rootにユーザーを変える必要ある。sudoでもできるか??

# pip3.6 install --upgrade pip

rootにしておかないとpipのアップグレードでエラーが起きてしまうので注意しておくこと。エラー内容は、PermissionError: [Errno 13] Permission denied: '/usr/bin/pip3.6'がでる。コマンドは

$ python3.6 -m pip install --upgrade pip

どうやらpermission deniedとなっているこのエラーは、管理者権限に関するエラーのようだ。

参考:https://teratail.com/questions/142008#reply-214645
https://teratail.com/questions/179746#reply-267445

django ログインユーザしか見れない構造の作り方

ユーザログインしているときだけ見える構造を構築する方法

実装例

views.py

def hoge():
    context = { }
        return render(request, "index.html",context )

#又はclass-based-viewを使う場合には、
class Diary(ListView):
    model = diaries
    template_name = "index.html"

index.html

{% if request.user.is_authenticated %}
もしユーザーなら見られる
{% else %}
this is test
{% endif %}

注意点はdjango2.0以前はis_authenticated() だったけど以降はis_authenticatedになったっぽい。

ディレクトリの指定

現状のパス問題点

ディレクトリの操作、ファイルの操作に関して個別具体的なパスで記述している。そのためスクリプトを移動してしまうと途端に関連するスクリプトにファイルを読み込めなくなってしまう。具体性を排除して、汎用的なファイル操作ができるようにしたい。

操作確認

C:\Users\user\program\dir_test.pyで試してみる。

test1

print(os.getcwd())

結果

C:\Users\user\program

test2

print(__name__)

結果

__main__

test3

print(__file__)

結果

dir_test.py

この__file__はモジュールファイルのパスを文字列として保存してあるらしい。byみんなのpython

test4

print(os.path.abspath(__file__))

結果

C:\Users\user\program\dir_test.py

test5

print(os.path.dirname(os.path.abspath(__file__)))

結果

C:\Users\user\program

os.path.dirname(os.path.abspath(__file__))とos.getcwd()の結果が同じだった。でこれはカレントディレクトリを示す。

カレントディレクトリに新たにディレクトリを作る場合

os.mkdir("dir1")

カレントディレクトリにdir1を作成することができた。mkdir(パス)なのでmkdir(フルパス)にするには以下のようにする。

os.mkdir(os.path.join(os.path.dirname(os.path.abspath(__file__)),"dir2"))

新たに作ったディレクトリに画像ファイルを保存する

まず新たに作ったディレクトリのパスを取得する。それにつなげてurllib.request.retrieve()を用いる。
新たに作ったディレクトリのパスは以下のように書く。

os.path.dirname(os.path.abspath(__file__))

画像urlは以下のものにする。https://www.google.co.jp/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png。だから画像のダウンロード自体は以下になる。

import urllib.request
url ="https://www.google.co.jp/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
save_name = "image.png"
urllib.request.retrieve(url,save_name)

これらを合わせるとこうなる。

import urllib.request
url ="https://www.google.co.jp/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
save_name = "image.png"
save_name = os.path.join(os.path.dirname(os.path.abspath(__file__)),"dir2",save_name)
urllib.request.retrieve(url,save_name)

指定のディレクトリの画像ファイルすべて削除する

指定のディレクトリ今回は"image"のファイルすべてを削除する

for t in os.listdir("image"):
    file = os.path.join(os.path.dirname(os.path.abspath(__file__)),"image",t)
    os.remove(file)

ちなみに以下の方法だと正確にフルパスを検出できずに、削除する事ができなかった。

for t in os.listdir("image"):
    print(os.path.abspath(t))
    os.remove(os.path.abspath(t))

関連メモ

ディレクトリ、ファイルの削除