[PYTHON] Votre propre client Twitter réalisé avec Django

Je vais essayer de le faire

Comme c'était le cas avec Bottle, je pense que la compréhension de base de Django s'approfondira si vous commencez par créer un client Twitter. En passant, je vais faire quelque chose qui vous permet de voir les messages, les réponses et les chronologies personnelles sur un seul écran.

スクリーンショット 2016-10-25 13.09.09.png

Le résultat est une telle image.

  1. Affichage de la limite de l'API
  2. Afficher une chronologie
  3. Préparez-vous à répondre en cliquant sur le nom d'utilisateur ou l'image sur la chronologie
  4. Vous pouvez tweeter du texte

Ce sera une spécification telle que.

Si vous souhaitez l'essayer dans des conditions similaires, veuillez vous référer à l'article précédent. http://qiita.com/Gen6/items/735245423b65698428be

Contenu

.py

myapp/views.py


from requests_oauthlib import OAuth1Session
import time, calendar
import datetime
import json
import re
import os
import requests
import sys, codecs
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)

from django.http.response import HttpResponse
from django.shortcuts import render


def index(request):

    msg = request.GET.get('words')

    C_KEY = '********************'
    C_SECRET = '********************'
    A_KEY = '********************'
    A_SECRET = '********************'

    url = 'https://api.twitter.com/1.1/statuses/update.json'
    params = {'status': msg,'lang': 'ja'}
    tw = OAuth1Session(C_KEY,C_SECRET,A_KEY,A_SECRET)
    req = tw.post(url, params = params)


    url = 'https://api.twitter.com/1.1/statuses/home_timeline.json'
    params = {'count': 1}
    req = tw.get(url, params = params)

    if req.status_code == 200:
        timeline = json.loads(req.text)
        limit = req.headers['x-rate-limit-remaining']

        for tweet in timeline:
            Text = (tweet['text'])
            User = (tweet['user']['screen_name'])
            Name = (tweet['user']['name'])
            Img = (tweet['user']['profile_image_url'])
            Created_at = YmdHMS(tweet['created_at'])

            Message = {
                'Words': msg,
                'timeline': timeline,
                'API_limit': limit,
                'Text': Text,
                'User': User,
                'Name': Name,
                'Img': Img,
                'Created_at': Created_at,
            }

            return render(request, 'index.html', Message)

    else:
        Error = {
            'Error_message': 'API restreinte',
        }
        return render(request, 'index.html', Error)


def YmdHMS(created_at):
    time_utc = time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y')
    unix_time = calendar.timegm(time_utc)
    time_local = time.localtime(unix_time)
    return int(time.strftime('%Y%m%d%H%M%S', time_local))

YdmHMS.py


def YmdHMS(created_at):
    time_utc = time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y')
    unix_time = calendar.timegm(time_utc)
    time_local = time.localtime(unix_time)
    return str(time.strftime('%Y'+'Année'+'%m'+'Mois'+'%d'+'journée'+'%H'+'Temps'+'%M'+'Minutes', time_local))

HTML et CSS

templates/base.html


<!DOCTYPE html>
<html lang="la">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="../static/css/bootstrap.min.css" rel="stylesheet">
    <link href="../static/css/custom.css" rel="stylesheet">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="../static/js/bootstrap.min.js"></script>
    <title></title>
  </head>
  <body>
    {% block body %}
    {% endblock %}
  </body>
</html>

Il est difficile d'écrire une URL solide.

templates/index.html


{% extends "base.html" %}
{% block body %}
  <div class="container">
    <div class="row">
      <div class="col-md-6">
        <form action="" method="get" class="form-group">
          <label><input type="text" size="60" name="words" class="form-control" placeholder="Tweet"></label>
          <input type="submit" class="btn btn-primary" value="Envoyer">
          <input type="button" class="btn btn-warning" value="Recharger" onclick="location.reload();" />
        </form>

        {% if Words %}
        <p>「{{ Words }}J'ai tweeté.</p>
        {% endif %}
        <p class="error-message">{{ Error_message }}</p>
        <p><span class="status">API-Limit:{{ API_limit }}</p>
      </div>
      <script type="text/javascript">
      $(function() {
      $(".reply").click(function() {
        var newText = '@{{ User }} ';
        $(':text[name="words"]').val(newText);
      });
      });
      </script>

      <div class="col-md-6">
        {% if API_limit %}
        <dl>
          <dt><span class="reply"><img class="users-img" src="{{ Img }}">{{ User }}/{{ Name }}</span><span class="d-time">{{ Created_at }}</span></dt>
          <dd>{{ Text }}</dd>
        </dl>
        <ul id="output"></ul>
        {% endif %}
      </div>

    </div>
  </div>

{% endblock %}

static/css/custom.css


.container {
  width: 100%;
}

.row {
  margin: 40px auto;
}

.status {
  background: #E2264D;
  border-radius: 4px;
  color: #fff;
  padding: 4px;
  width: 100px;
  text-align: center;
  margin-right: 10px;
}

.reply {
  cursor: pointer;
  font-weight: bold;
}

.btn-primary {
  margin-right: 2px;
}

.d-time {
  margin-left: 10px;
  border: 1px solid #d8d8d8;
  border-radius: 4px;
  padding: 4px;
  font-weight: normal;
}

ul li {
  list-style: none;
}

.users-img {
  margin-right: 10px;
  border-radius: 4px;
}

dt {
  margin-bottom: 10px;
}

.error-message {
  color: #ff3300;
}

Si vous souhaitez l'enregistrer dans la base de données, veuillez consulter l'article suivant. http://qiita.com/Gen6/items/907d869cdf1d588a4751

Personnalisation supplémentaire

スクリーンショット 2016-10-26 13.06.43.png

Créez avec une image comme celle ci-dessus.

Vérifiez settings.py

J'écrirai vers la ligne 107.

mysite/settings.py


LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

USE_I18N = True

USE_L10N = True

USE_TZ = True

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

Ajouter views.py

C'est un modèle qui implémente la publication, la mention et la recherche. Puisqu'il est écrit dans un fichier de vues, il n'est pas facile à maintenir, mais veuillez vous y référer.

Vous pouvez mettre la CLE à l'extérieur ou l'écrire plus simplement, mais c'est facile à comprendre. Essayez différentes choses pour garder votre code propre.

Les résultats de la recherche seront un modèle enregistré dans la base de données.

myapp/views.py


from requests_oauthlib import OAuth1Session
import time, calendar
import datetime
import json
import re
import os
import requests
import sys, codecs
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)

from django.http.response import HttpResponse
from django.shortcuts import render
from myapp.models import Supermodel


def index(request):

    msg = request.GET.get('words')

    C_KEY = '********************'
    C_SECRET = '********************'
    A_KEY = '********************'
    A_SECRET = '********************'

    url = 'https://api.twitter.com/1.1/statuses/update.json'
    params = {'status': msg,'lang': 'ja'}
    tw = OAuth1Session(C_KEY,C_SECRET,A_KEY,A_SECRET)
    req = tw.post(url, params = params)


    url = 'https://api.twitter.com/1.1/statuses/home_timeline.json'
    params = {'count': 1}
    req = tw.get(url, params = params)

    if req.status_code == 200:
        timeline = json.loads(req.text)
        limit = req.headers['x-rate-limit-remaining']

        for tweet in timeline:
            Text = (tweet['text'])
            User = (tweet['user']['screen_name'])
            Name = (tweet['user']['name'])
            Img = (tweet['user']['profile_image_url'])
            Created_at = YmdHMS(tweet['created_at'])

            Message = {
                'Words': msg,
                'timeline': timeline,
                'API_limit': limit,
                'Text': Text,
                'User': User,
                'Name': Name,
                'Img': Img,
                'Created_at': Created_at,
            }

            return render(request, 'index.html', Message)

    else:
        Error = {
            'Error_message': 'API restreinte',
        }
        return render(request, 'index.html', Error)


def search(request):

    search_words = 'hogehoge'
    search_words = request.GET.get('words')

    C_KEY = '********************'
    C_SECRET = '********************'
    A_KEY = '********************'
    A_SECRET = '********************'
    tw = OAuth1Session(C_KEY,C_SECRET,A_KEY,A_SECRET)

    url = 'https://api.twitter.com/1.1/search/tweets.json?'
    params = {
    			'q': (search_words, 'utf-8'),
                'lang': 'ja',
    			'count': '1'
    			}
    req = tw.get(url, params = params)

    if req.status_code == 200:
        timeline = json.loads(req.text)
        limit = req.headers['x-rate-limit-remaining']

        for tweet in timeline['statuses']:
            Text = (tweet['text'])
            User = (tweet['user']['screen_name'])
            Name = (tweet['user']['name'])
            Img = (tweet['user']['profile_image_url'])
            Created_at = YmdHMS(tweet['created_at'])


            data = Supermodel()
            data.user_id = User
            data.user_name = Name
            data.user_img = Img
            data.user_text = Text
            data.user_created_at = Created_at
            data.save()

            Message = {
                'Words': search_words,
                'timeline': timeline,
                'API_limit': limit,
                'Text': Text,
                'User': User,
                'Name': Name,
                'Img': Img,
                'Created_at': Created_at,
            }

            return render(request, 'search.html', Message)

    else:
        Error = {
            'Error_message': 'API restreinte',
        }
        return render(request, 'search.html', Error)


def mentions(request):

    msg = request.GET.get('words')

    C_KEY = '********************'
    C_SECRET = '********************'
    A_KEY = '********************'
    A_SECRET = '********************'

    url = 'https://api.twitter.com/1.1/statuses/update.json'
    params = {'status': msg,'lang': 'ja'}
    tw = OAuth1Session(C_KEY,C_SECRET,A_KEY,A_SECRET)
    req = tw.post(url, params = params)


    url = 'https://api.twitter.com/1.1/statuses/mentions_timeline.json'
    params = {'count': 1}
    req = tw.get(url, params = params)

    if req.status_code == 200:
        timeline = json.loads(req.text)
        limit = req.headers['x-rate-limit-remaining']

        for tweet in timeline:
            Text = (tweet['text'])
            User = (tweet['user']['screen_name'])
            Name = (tweet['user']['name'])
            Img = (tweet['user']['profile_image_url'])
            Created_at = YmdHMS(tweet['created_at'])

            Message = {
                'Words': msg,
                'timeline': timeline,
                'API_limit': limit,
                'Text': Text,
                'User': User,
                'Name': Name,
                'Img': Img,
                'Created_at': Created_at,
            }

            return render(request, 'mentions.html', Message)

    else:
        Error = {
            'Error_message': 'API restreinte',
        }
        return render(request, 'mentions.html', Error)


def YmdHMS(created_at):
    time_utc = time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y')
    unix_time = calendar.timegm(time_utc)
    time_local = time.localtime(unix_time)
    return int(time.strftime('%Y%m%d%H%M%S', time_local))

L'opération pour enregistrer dans la base de données est la suivante. Je pense que c'est simple, facile à comprendre et facile à comprendre ce que vous faites.

data = Supermodel()
data.user_id = User
data.user_name = Name
data.user_img = Img
data.user_text = Text
data.user_created_at = Created_at
data.save()

Écrire divers fichiers HTML

J'utilise bootstrap.

templates/base.html


<!DOCTYPE html>
<html lang="la">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="../static/css/bootstrap.min.css" rel="stylesheet">
    <link href="../static/css/custom.css" rel="stylesheet">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="../static/js/bootstrap.min.js"></script>
    <title></title>
  </head>
  <body>
    {% block body %}
    {% endblock %}
  </body>
</html>

templates/index.html


{% extends "base.html" %}
{% block body %}
  <div class="container">
    <nav class="nav">
      <ul>
        <li><a href="{% url 'index' %}">POST</a></li>
        <li><a href="{% url 'search' %}">SEARCH</a></li>
        <li><a href="{% url 'mentions' %}">MENTIONS</a></li>
      </ul>
    </nav>
    <div class="row">
      <div class="col-md-6">
        <form action="" method="get" class="form-group">
          <label><input type="text" size="60" name="words" class="form-control" placeholder="Tweet"></label>
          <input type="submit" class="btn btn-primary" value="Envoyer">
          <input type="button" class="btn btn-warning" value="Recharger" onclick="location.reload();" />
        </form>

        {% if Words %}
        <p>「{{ Words }}J'ai tweeté.</p>
        {% endif %}
        <p class="error-message">{{ Error_message }}</p>
        <p><span class="status">API-Limit:{{ API_limit }}</p>
      </div>
      <script type="text/javascript">
      $(function() {
      $(".reply").click(function() {
        var newText = '@{{ User }} ';
        $(':text[name="words"]').val(newText);
      });
      });
      </script>

      <div class="col-md-6">
        {% if API_limit %}
        <dl>
          <dt><span class="reply"><img class="users-img" src="{{ Img }}">{{ User }}/{{ Name }}</span><span class="d-time">{{ Created_at }}</span></dt>
          <dd>{{ Text }}</dd>
        </dl>
        {% endif %}
      </div>

    </div>
  </div>

{% endblock %}

templates/search.html


{% extends "base.html" %}
{% block body %}
  <div class="container">
    <nav class="nav">
      <ul>
        <li><a href="{% url 'index' %}">POST</a></li>
        <li><a href="{% url 'search' %}">SEARCH</a></li>
        <li><a href="{% url 'mentions' %}">MENTIONS</a></li>
      </ul>
    </nav>
    <div class="row">
      <div class="col-md-6">
        <form action="" method="get" class="form-group">
          <label><input type="text" size="60" name="words" class="form-control" placeholder="Chercher"></label>
          <input type="submit" class="btn btn-primary" value="Envoyer">
          <input type="button" class="btn btn-warning" value="Recharger" onclick="location.reload();" />
        </form>

        {% if Words %}
        <p>「{{ Words }}A été recherché.</p>
        {% endif %}
        <p class="error-message">{{ Error_message }}</p>
        <p><span class="status">API-Limit:{{ API_limit }}</p>
      </div>
      <script type="text/javascript">
      $(function() {
      $(".reply").click(function() {
        var newText = '@{{ User }} ';
        $(':text[name="words"]').val(newText);
      });
      });
      </script>

      <div class="col-md-6">
        {% if API_limit %}
        <dl>
          <dt><span class="reply"><img class="users-img" src="{{ Img }}">{{ User }}/{{ Name }}</span><span class="d-time">{{ Created_at }}</span></dt>
          <dd>{{ Text }}</dd>
        </dl>
        {% endif %}
      </div>

    </div>
  </div>

{% endblock %}

templates/mentions.html


{% extends "base.html" %}
{% block body %}
  <div class="container">
    <nav class="nav">
      <ul>
        <li><a href="{% url 'index' %}">POST</a></li>
        <li><a href="{% url 'search' %}">SEARCH</a></li>
        <li><a href="{% url 'mentions' %}">MENTIONS</a></li>
      </ul>
    </nav>
    <div class="row">
      <div class="col-md-6">
        <form action="" method="get" class="form-group">
          <label><input type="text" size="60" name="words" class="form-control" placeholder="Tweet"></label>
          <input type="submit" class="btn btn-primary" value="Envoyer">
          <input type="button" class="btn btn-warning" value="Recharger" onclick="location.reload();" />
        </form>

        {% if Words %}
        <p>「{{ Words }}J'ai tweeté.</p>
        {% endif %}
        <p class="error-message">{{ Error_message }}</p>
        <p><span class="status">API-Limit:{{ API_limit }}</p>
      </div>
      <script type="text/javascript">
      $(function() {
      $(".reply").click(function() {
        var newText = '@{{ User }} ';
        $(':text[name="words"]').val(newText);
      });
      });
      </script>

      <div class="col-md-6">
        {% if API_limit %}
        <dl>
          <dt><span class="reply"><img class="users-img" src="{{ Img }}">{{ User }}/{{ Name }}</span><span class="d-time">{{ Created_at }}</span></dt>
          <dd>{{ Text }}</dd>
        </dl>
        {% endif %}
      </div>

    </div>
  </div>

{% endblock %}

CSS

static/css/custom.css


.container {
  width: 100%;
}

.nav {
  background: rgba(0,0,0,0.7);
  color: #fff;
  width: 100%;
  margin: 0 auto;
}

.nav ul li {
  list-style: none;
  margin: 10px auto;
}

.nav ul {
  margin-left: -20px;
}

.nav li {
  float: left;
  margin-right: 10px!important;
}

.nav li a:link, .nav li a:visited {
  color: #fff!important;
}

.row {
  margin: 40px auto;
}

.status {
  background: #E2264D;
  border-radius: 4px;
  color: #fff;
  padding: 4px;
  width: 100px;
  text-align: center;
  margin-right: 10px;
}

.reply {
  cursor: pointer;
  font-weight: bold;
}

.btn-primary {
  margin-right: 2px;
}

.d-time {
  margin-left: 10px;
  border: 1px solid #d8d8d8;
  border-radius: 4px;
  padding: 4px;
  font-weight: normal;
}

ul li {
  list-style: none;
}

.users-img {
  margin-right: 10px;
  border-radius: 4px;
}

dt {
  margin-bottom: 10px;
}

.error-message {
  color: #ff3300;
}

Écrivez urls.py

myapp/urls.py


from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^search/', views.search, name='search'),
    url(r'^mentions/', views.mentions, name='mentions'),
]

Écrivez models.py et admin.py

Si vous n'enregistrez pas les résultats de la recherche de tweet dans la base de données, ce qui suit n'est pas nécessaire, mais juste au cas où cela serait décrit dans views.py. Puisque SQLITE est utilisé, laissez les paramètres de base.py par défaut.

myapp/models.py


from django.db import models


class Supermodel(models.Model):
    user_name = models.CharField(max_length=140)
    user_id = models.CharField(max_length=140)
    user_img = models.CharField(max_length=140)
    user_text = models.TextField(null=True)
    user_created_at = models.CharField(max_length=140)

    def __str__(self):
        return self.user_name

myapp/admin.py


from django.contrib import admin
from myapp.models import Supermodel


class SupermodelAdmin(admin.ModelAdmin):
    list_display = ('id','user_id','user_name','user_img','user_text','user_created_at')

admin.site.register(Supermodel,SupermodelAdmin)

Configuration finale

スクリーンショット 2016-10-26 13.20.58.png

Ça ressemble à ça.

Après cela, veuillez migrer et exécuter le serveur.

Recommended Posts

Votre propre client Twitter réalisé avec Django
Application de publication sur Twitter réalisée avec Django
Client de recherche Twitter fait avec bouteille
Twitter OAuth avec Django
Exécutez avec un navigateur. Client Twitter réalisé avec une bouteille (POST uniquement
Créez votre propre middleware Django
Client de publication Twitter créé avec Flask avec une fonction de connexion simple
Résolvez votre propre labyrinthe avec Q Learning
[Django] Créez votre propre page d'erreur 403, 404, 500
Entraînez UGATIT avec votre propre jeu de données
Résolvez votre propre labyrinthe avec DQN
Lecteur RSS simple réalisé avec Django
[Renforcer l'apprentissage] DQN avec votre propre bibliothèque
Client API Slack simple réalisé avec Python
Créez votre propre serveur DNS avec Twisted
Créez votre propre valeur composite avec SQLAlchemy
Pour importer votre propre module avec jupyter
Création de la première application avec Django startproject
Publiez votre propre bibliothèque Python sur Homebrew
J'ai fait une application WEB avec Django
Essayez de créer votre propre AWS-SDK avec bash
Jusqu'à ce que vous définissiez ce que vous avez fait avec Django avec Jenkins
Divisez les données en unités de type projet avec Django (3)
Internationalisation avec Django
J'ai essayé de créer un bloqueur de filles pourries sur Twitter avec Python ①
Créez rapidement votre propre module avec setuptools (python)
Divisez les données en unités de type projet avec Django
CRUD avec Django
Entraînez Stanford NER Tagger avec vos propres données
Créez votre propre lecteur de musique avec Bottle0.13 + jPlayer2.5!
Étapes pour installer votre propre bibliothèque avec pip
Flux de création de votre propre package avec setup.py avec python
Mémo pour créer votre propre Box avec le Python de Pepper
J'ai fait un Twitter BOT avec GAE (python) (avec une référence)
Appelez votre propre bibliothèque de langage C avec Go en utilisant cgo
Écrivez votre propre fonction d'activation avec Pytorch (sigmoïde dur)
Accédez à l'API Twitter après l'authentification Oauth avec Django
Appelons votre propre bibliothèque C ++ avec Python (Préférences)
Définissez votre propre fonction de distance avec k-means de scikit-learn
Application Web réalisée avec Python3.4 + Django (Construction de l'environnement Part.1)
Authentification unique à l'application Django avec AWS SSO
Déployer l'application Django créée avec PTVS sur Azure
Authentifier Google avec Django
Django 1.11 a démarré avec Python3.6
Télécharger des fichiers avec Django
Créez votre propre exception
Résumé du développement avec Django
Sortie PDF avec Django
En forme de conteneur réalisé avec C # 1
Sortie Markdown avec Django
Utiliser Gentelella avec Django
Initialiser l'application Django
Premiers pas avec Django 1
Envoyer des e-mails avec Django
Téléchargement de fichiers avec django
Utilisez LESS avec Django
La mutualisation mécanise avec Django
Utiliser MySQL avec Django