1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

無料サーバーにDjangoを使ったSNSサイトを簡単に公開する方法【pythonanywhere】

Posted at

pythonanywhereアカウント作成

アプリ作成でmysite2とうゆうdjangoのプロジェクトを作成

djang4.png

コンソールを開く

mysite2フォルダまで移動してコンソールを開く

djang6.png

snsとゆうアプリケーションを作成

djang7.png

アプリケーションをmysite2/setting.pyに登録する

mysite2/mysite2/settiong.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'sns', #これを足す
]

モデルを作成する

mysite2/sns/models.py
from django.db import models
from django.contrib.auth.models import User

# Messageクラス
class Message(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE, \
        related_name='message_owner')
    group = models.ForeignKey('Group', on_delete=models.CASCADE)
    content = models.TextField(max_length=1000)
    share_id = models.IntegerField(default=-1)
    good_count = models.IntegerField(default=0)
    share_count = models.IntegerField(default=0)
    pub_date = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return str(self.content) + ' (' + str(self.owner) + ')'
    
    def get_share(self):
        return Message.objects.get(id=self.share_id)

    class Meta:
        ordering = ('-pub_date',)

# Groupクラス
class Group(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE, \
        related_name='group_owner')
    title = models.CharField(max_length=100)
    
    def __str__(self):
        return '<' + self.title + '(' + str(self.owner) + ')>'

# Friendクラス
class Friend(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE, \
        related_name='friend_owner')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
        
    def __str__(self):
        return str(self.user) + ' (group:"' + str(self.group) + '")'

# Goodクラス
class Good(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE, \
        related_name='good_owner')
    message = models.ForeignKey(Message, on_delete=models.CASCADE)

    def __str__(self):
        return 'good for "' + str(self.message) + '" (by ' + \
            str(self.owner) + ')'

マイグレーションを実行

djang8.png

djang9.png

snsのテーブルを作成

mysite2/sns/admin.py
from django.contrib import admin
from .models import Message, Friend, Group, Good

admin.site.register(Message)
admin.site.register(Friend)
admin.site.register(Group)
admin.site.register(Good)

管理画面の管理ユーザーを作成

djang10.png

管理ユーザーでログイン
djang11.png

publicユーザーとpublicグループを作成、テストユーザーも作成
djang12.png

djang13.png

フォームの作成

mysite2/sns/forms.py
from django import forms
from.models import Message,Group,Friend,Good
from django.contrib.auth.models import User

# Messageのフォーム(未使用)
class MessageForm(forms.ModelForm):
    class Meta:
        model = Message
        fields = ['owner','group','content']

# Groupのフォーム(未使用)
class GroupForm(forms.ModelForm):
    class Meta:
        model = Group
        fields = ['owner', 'title']

# Friendのフォーム(未使用)
class FriendForm(forms.ModelForm):
    class Meta:
        model = Friend
        fields = ['owner', 'user', 'group']

# Goodのフォーム(未使用)
class GoodForm(forms.ModelForm):
    class Meta:
        model = Good
        fields = ['owner', 'message']

# Groupのチェックボックスフォーム
class GroupCheckForm(forms.Form):
    def __init__(self, user, *args, **kwargs):
        super(GroupCheckForm, self).__init__(*args, **kwargs)
        public = User.objects.filter(username='public').first()
        self.fields['groups'] = forms.MultipleChoiceField(
            choices=[(item.title, item.title) for item in \
                Group.objects.filter(owner__in=[user,public])],
            widget=forms.CheckboxSelectMultiple(),
        )

# Groupの選択メニューフォーム
class GroupSelectForm(forms.Form):
    def __init__(self, user, *args, **kwargs):
        super(GroupSelectForm, self).__init__(*args, **kwargs)
        self.fields['groups'] = forms.ChoiceField(
            choices=[('-','-')] + [(item.title, item.title) \
                for item in Group.objects.filter(owner=user)],
                widget=forms.Select(attrs={'class':'form-control'}),
        )

# Friendのチェックボックスフォーム
class FriendsForm(forms.Form):
    def __init__(self, user, friends=[], vals=[], *args, **kwargs):
        super(FriendsForm, self).__init__(*args, **kwargs)
        self.fields['friends'] = forms.MultipleChoiceField(
            choices=[(item.user, item.user) for item in friends],
            widget=forms.CheckboxSelectMultiple(),
            initial=vals
        )

# Group作成フォーム
class CreateGroupForm(forms.Form):
    group_name = forms.CharField(max_length=50, \
        widget=forms.TextInput(attrs={'class':'form-control'}))

# 投稿フォーム
class PostForm(forms.Form):
    content = forms.CharField(max_length=500, \
        widget=forms.Textarea(attrs={'class':'form-control', 'rows':2}))
    
    def __init__(self, user, *args, **kwargs):
        super(PostForm, self).__init__(*args, **kwargs)
        public = User.objects.filter(username='public').first()
        self.fields['groups'] = forms.ChoiceField(
            choices=[('-','-')] + [(item.title, item.title) \
                for item in Group.objects. \
                filter(owner__in=[user,public])],
                widget=forms.Select(attrs={'class':'form-control'}),
        )

urls.pyを作成

mysite2/sns/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('<int:page>', views.index, name='index'),
    path('groups', views.groups, name='groups'),
    path('add', views.add, name='add'),
    path('creategroup', views.creategroup, name='creategroup'),
    path('post', views.post, name='post'),
    path('share/<int:share_id>', views.share, name='share'),
    path('good/<int:good_id>', views.good, name='good'),
]

mysite2のurls.pyを修正

mysite2/urls.py
from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('sns/', include('sns.urls')),
]

views.pyを修正

mysite2/sns/views.py
from django.shortcuts import render
from django.shortcuts import redirect
from django.contrib.auth.models import User
from django.contrib import messages
from django.core.paginator import Paginator
from django.db.models import Q
from django.contrib.auth.decorators import login_required

from .models import Message,Friend,Group,Good
from .forms import GroupCheckForm,GroupSelectForm,\
    FriendsForm,CreateGroupForm,PostForm

# indexのビュー関数
@login_required(login_url='/admin/login/')
def index(request, page=1):
    # publicのuserを取得
    (public_user, public_group) = get_public()

    # POST送信時の処理
    if request.method == 'POST':

        # Groupsのチェックを更新した時の処理
        # フォームの用意
        checkform = GroupCheckForm(request.user,request.POST)
        # チェックされたGroup名をリストにまとめる
        glist = []
        for item in request.POST.getlist('groups'):
            glist.append(item)
        # Messageの取得
        messages = get_your_group_message(request.user, \
                glist, page)

    # GETアクセス時の処理
    else:
        # フォームの用意
        checkform = GroupCheckForm(request.user)
        # Groupのリストを取得
        gps = Group.objects.filter(owner=request.user)
        glist = [public_group.title]
        for item in gps:
            glist.append(item.title)
        # メッセージの取得
        messages = get_your_group_message(request.user, glist, page)

    # 共通処理
    params = {
        'login_user':request.user,
        'contents':messages,
        'check_form':checkform,
    }
    return render(request, 'sns/index.html', params)

@login_required(login_url='/admin/login/')
def groups(request):
    # 自分が登録したFriendを取得
    friends = Friend.objects.filter(owner=request.user)
    
    # POST送信時の処理
    if request.method == 'POST':
        
        # Groupsメニュー選択肢の処理
        if request.POST['mode'] == '__groups_form__':
            # 選択したGroup名を取得
            sel_group = request.POST['groups']
            # Groupを取得
            gp = Group.objects.filter(owner=request.user) \
                .filter(title=sel_group).first()
            # Groupに含まれるFriendを取得
            fds = Friend.objects.filter(owner=request.user) \
                .filter(group=gp)
            print(Friend.objects.filter(owner=request.user))
            # FriendのUserをリストにまとめる
            vlist = []
            for item in fds:
                vlist.append(item.user.username)
            # フォームの用意
            groupsform = GroupSelectForm(request.user,request.POST)
            friendsform = FriendsForm(request.user, \
                    friends=friends, vals=vlist)
        
        # Friendsのチェック更新時の処理
        if request.POST['mode'] == '__friends_form__':
            # 選択したGroupの取得
            sel_group = request.POST['group']
            group_obj = Group.objects.filter(title=sel_group).first()
            print(group_obj)
            # チェックしたFriendsを取得
            sel_fds = request.POST.getlist('friends')
            # FriendsのUserを取得
            sel_users = User.objects.filter(username__in=sel_fds)
            # Userのリストに含まれるユーザーが登録したFriendを取得
            fds = Friend.objects.filter(owner=request.user) \
                    .filter(user__in=sel_users)
            # すべてのFriendにGroupを設定し保存する
            vlist = []
            for item in fds:
                item.group = group_obj
                item.save()
                vlist.append(item.user.username)
            # メッセージを設定
            messages.success(request, ' チェックされたFriendを' + \
                    sel_group + 'に登録しました。')
            # フォームの用意
            groupsform = GroupSelectForm(request.user, \
                    {'groups':sel_group})
            friendsform = FriendsForm(request.user, \
                    friends=friends, vals=vlist)
    
    # GETアクセス時の処理  
    else:
        # フォームの用意
        groupsform = GroupSelectForm(request.user)
        friendsform = FriendsForm(request.user, friends=friends, \
                vals=[])
        sel_group = '-'
    
    # 共通処理
    createform = CreateGroupForm()
    params = {
        'login_user':request.user,
        'groups_form':groupsform,
        'friends_form':friendsform,
        'create_form':createform,
        'group':sel_group,
    }
    return render(request, 'sns/groups.html', params)

# Friendの追加処理
@login_required(login_url='/admin/login/')
def add(request):
    # 追加するUserを取得
    add_name = request.GET['name']
    add_user = User.objects.filter(username=add_name).first()
    # Userが本人だった場合の処理
    if add_user == request.user:
        messages.info(request, "自分自身をFriendに追加することは\
                できません。")
        return redirect(to='/sns')
    # publicの取得
    (public_user, public_group) = get_public()
    # add_userのFriendの数を調べる
    frd_num = Friend.objects.filter(owner=request.user) \
            .filter(user=add_user).count()
    # ゼロより大きければ既に登録済み
    if frd_num > 0:
        messages.info(request, add_user.username + \
                ' は既に追加されています。')
        return redirect(to='/sns')
    
    # ここからFriendの登録処理
    frd = Friend()
    frd.owner = request.user
    frd.user = add_user
    frd.group = public_group
    frd.save()
    # メッセージを設定
    messages.success(request, add_user.username + ' を追加しました!\
        groupページに移動して、追加したFriendをメンバーに設定して下さい。')
    return redirect(to='/sns')

# グループの作成処理
@login_required(login_url='/admin/login/')
def creategroup(request):
    # Groupを作り、Userとtitleを設定して保存する
    gp = Group()
    gp.owner = request.user
    gp.title = request.user.username + '' + request.POST['group_name']
    gp.save()
    messages.info(request, '新しいグループを作成しました。')
    return redirect(to='/sns/groups')

# メッセージのポスト処理
@login_required(login_url='/admin/login/')
def post(request):
    # POST送信の処理
    if request.method == 'POST':
        # 送信内容の取得
        gr_name = request.POST['groups']
        content = request.POST['content']
        # Groupの取得
        group = Group.objects.filter(owner=request.user) \
                .filter(title=gr_name).first()
        if group == None:
            (pub_user, group) = get_public()
        # Messageを作成し設定して保存
        msg = Message()
        msg.owner = request.user
        msg.group = group
        msg.content = content
        msg.save()
        # メッセージを設定
        messages.success(request, '新しいメッセージを投稿しました!')
        return redirect(to='/sns')
    
    # GETアクセス時の処理
    else:
        form = PostForm(request.user)
    
    # 共通処理
    params = {
        'login_user':request.user,
        'form':form,
    }
    return render(request, 'sns/post.html', params)

# 投稿をシェアする
@login_required(login_url='/admin/login/')
def share(request, share_id):
    # シェアするMessageの取得
    share = Message.objects.get(id=share_id)
    print(share)
    # POST送信時の処理
    if request.method == 'POST':
        # 送信内容を取得
        gr_name = request.POST['groups']
        content = request.POST['content']
        # Groupの取得
        group = Group.objects.filter(owner=request.user) \
                .filter(title=gr_name).first()
        if group == None:
            (pub_user, group) = get_public()
        # メッセージを作成し、設定をして保存
        msg = Message()
        msg.owner = request.user
        msg.group = group
        msg.content = content
        msg.share_id = share.id
        msg.save()
        share_msg = msg.get_share()
        share_msg.share_count += 1
        share_msg.save()
        # メッセージを設定
        messages.success(request, 'メッセージをシェアしました!')
        return redirect(to='/sns')
    
    # 共通処理
    form = PostForm(request.user)
    params = {
        'login_user':request.user,
        'form':form,
        'share':share,
    }
    return render(request, 'sns/share.html', params)

# goodボタンの処理
@login_required(login_url='/admin/login/')
def good(request, good_id):
    # goodするMessageを取得
    good_msg = Message.objects.get(id=good_id)
    # 自分がメッセージにGoodした数を調べる
    is_good = Good.objects.filter(owner=request.user) \
            .filter(message=good_msg).count()
    # ゼロより大きければ既にgood済み
    if is_good > 0:
        messages.success(request, '既にメッセージにはGoodしています。')
        return redirect(to='/sns')
    
    # Messageのgood_countを1増やす
    good_msg.good_count += 1
    good_msg.save()
    # Goodを作成し、設定して保存
    good = Good()
    good.owner = request.user
    good.message = good_msg
    good.save()
    # メッセージを設定
    messages.success(request, 'メッセージにGoodしました!')
    return redirect(to='/sns')


# これ以降は普通の関数==================


# 指定されたグループおよび検索文字によるMessageの取得
def get_your_group_message(owner, glist, page):
    page_num = 10 #ページあたりの表示数
    # publicの取得
    (public_user,public_group) = get_public()
    # チェックされたGroupの取得
    groups = Group.objects.filter(Q(owner=owner) \
            |Q(owner=public_user)).filter(title__in=glist)
    # Groupに含まれるFriendの取得
    me_friends = Friend.objects.filter(group__in=groups)
    # FriendのUserをリストにまとめる
    me_users = []
    for f in me_friends:
        me_users.append(f.user)
    # UserリストのUserが作ったGroupの取得
    his_groups = Group.objects.filter(owner__in=me_users)
    his_friends = Friend.objects.filter(user=owner) \
            .filter(group__in=his_groups)
    me_groups = []
    for hf in his_friends:
        me_groups.append(hf.group)
    # groupがgroupsに含まれるか、me_groupsに含まれるMessageの取得
    messages = Message.objects.filter(Q(group__in=groups) \
        |Q(group__in=me_groups))
    # ページネーションで指定ページを取得
    page_item = Paginator(messages, page_num)
    return page_item.get_page(page)

# publicなUserとGroupを取得する
def get_public():
    public_user = User.objects.filter(username='public').first()
    public_group = Group.objects.filter \
            (owner=public_user).first()
    return (public_user, public_group)

templatesを作成

mysite2/sns/templates/snsディレクトリを作成、 layout.html,index.html,groups.html,post.html,share.htmlを作成
mysite2/sns/templates/sns/layout.html
{% load static %}
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" 
    href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" 
    crossorigin="anonymous">
</head>
<body class="container">
    <nav class="navbar navbar-expand navbar-light bg-light">
    <ul class="navbar-nav mr-auto">
        <li class="nav-item">
            <a class="nav-link" href="{% url 'index' %}">top</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="{% url 'post' %}">post</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="{% url 'groups' %}">group</a>
        </li>
    </ul>
    <span>logined: <span class="h6">"{{login_user}}".</span></span>
    </nav>

    <div>{% block header %}
        {% endblock %}</div>
    <div class="content">{% block content %}
        {% endblock %}</div>

    <hr>
    <div class="my-3">
        <span class="font-weight-bold">
            <a href="/admin/logout?next=/sns/">
                [ logout ]</a></span>
        <span class="float-right">copyright 2020 
            SYODA-Tuyano.</span>
    </div>
</body>
</html>

mysite2/sns/templates/sns/index.html
{% extends 'sns/layout.html' %}

{% block title %}Index{% endblock %}

{% block header %}
<script>
function sendGroupForm(page) {
    document.group_form.action += page;
    document.group_form.submit();
}
</script>
<h1 class="display-4 text-primary">SNS</h1>
<p>※グループのチェックをONにしてupdateすると、
そのグループに登録されている利用者のメッセージだけが表示されます。</p>
{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} 
        class="{{ message.tags }}"
        {% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}
{% endblock %}

{% block content %}
<hr>
<div>
    <form action="{% url 'index' %}" method="post" name="group_form">
        {% csrf_token %}
        {{check_form}}
        <div>
            <button class="btn btn-primary">update</button>
        </div>
    </form>
</div>
<table class="table mt-3">
    <tr><th>Messages</th></tr>
{% for item in contents %}
    <tr><td>
    <p class="my-0">
        {% if item.group.title == 'public' %}
        <span class="bg-info text-light px-1">Public</span>
        {% endif %}
        {{item.content}}</p>
    <p class=""> ({{item.pub_date}})</p>
    {% if item.share_id > 0 %}
    <ul><li class="text-black-50">"{{item.get_share}}"</li></ul>
    {% endif %}
    <span class="float-left text-info">
        share={{item.share_count}} good={{item.good_count}}
    </span>
    <span class="float-right">
        "{{item.owner}}"(<a href="{% url 'add' %}?name={{item.owner}}">
            add friend</a>)
        <a href="{% url 'share' item.id %}">
            <button class="py-0">share</button></a>
        <a href="{% url 'good' item.id %}">
            <button class="py-0">good!</button></a>
    </span>
</td></tr>
{% endfor %}
</table>

<ul class="pagination justify-content-center">
    {% if contents.has_previous %}
    <li class="page-item">
        <a class="page-link" href="javascript:sendGroupForm(1);">
            &laquo; first</a>
    </li>
    <li class="page-item">
        <a class="page-link" 
        href="javascript:sendGroupForm({{contents.previous_page_number}});">
            &laquo; prev</a>
    </li>
    {% else %}
    <li class="page-item">
        <a class="page-link">&laquo; first</a>
    </li>
    <li class="page-item">
        <a class="page-link">&laquo; prev</a>
    </li>
    {% endif %}
    <li class="page-item">
        <a class="page-link">
        {{contents.number}}/{{contents.paginator.num_pages}}</a>
    </li>
    {% if contents.has_next %}
    <li class="page-item">
        <a class="page-link" 
        href="javascript:sendGroupForm({{contents.next_page_number }});">
            next &raquo;</a>
    </li>
    <li class="page-item">
        <a class="page-link" 
        href="javascript:sendGroupForm({{contents.paginator.num_pages}});">
            last &raquo;</a>
    </li>
    {% else %}
    <li class="page-item">
        <a class="page-link">next &raquo;</a>
    </li>
    <li class="page-item">
        <a class="page-link">last &raquo;</a>
    </li>
    {% endif %}
</ul>
{% endblock %}
mysite2/sns/templates/sns/groups.html
{% extends 'sns/layout.html' %}

{% block title %}Groups{% endblock %}

{% block header %}
<h1 class="display-4 text-primary">Group</h1>
<p class="caption">※グループを選択してselect memberすると、
    そのグループに登録されている利用者がONになります。
    利用者のチェックをONにしてset memberすると、ONにしてある
    利用者がグループに追加されます。</p>
{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"
        {% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}
{% endblock %}

{% block content %}
<form action="{% url 'groups' %}" method="post">
{% csrf_token %}
<input type="hidden" name="mode" value="__groups_form__">
{{groups_form}}
<button class="btn btn-primary mt-1">select members</button>
</form>
<hr>
<form action="{% url 'groups' %}" method="post">
{% csrf_token %}
<input type="hidden" name="mode" value="__friends_form__">
<input type="hidden" name="group" value="{{group}}">
{{friends_form}}
<button class="btn btn-primary mt-0">set members</button>
</form>
<hr>
<p>※新しいGroupの登録</p>
<form action="{% url 'creategroup' %}" method="post">
{% csrf_token %}
{{create_form}}
<button class="btn btn-primary mt-1">create new group</button>
</form>
{% endblock %}
mysite2/sns/templates/sns/post.html
{% extends 'sns/layout.html' %}

{% block title %}Post{% endblock %}

{% block header %}
<h1 class="display-4 text-primary">Post</h1>
<p  class="caption">※投稿先のグループを選択し、
    メッセージを投稿します。</p>
{% if messages %}
<ul class="list-group">
    {% for message in messages %}
    <li{% if message.tags %} class="list-group-item {{ message.tags }}"
        {% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}
{% endblock %}

{% block content %}
<form action="{% url 'post' %}" method="post">
{% csrf_token %}
{{form.as_p}}
<button class="btn btn-primary">Post!</button>
</form>
{% endblock %}
mysite2/sns/templates/sns/share.html
{% extends 'sns/layout.html' %}

{% block title %}Share{% endblock %}

{% block header %}
<h1 class="display-4 text-primary">Share</h1>
<p  class="caption">※投稿先のグループを選択し、
    下のメッセージをシェアします。</p>
{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"
        {% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}
{% endblock %}

{% block content %}
<p class="bg-light p-3">
    "{{share.content}} ({{share.owner}})"</p>
<form action="{% url 'share' share.id %}" method="post">
{% csrf_token %}
{{form.as_p}}
<button class="btn btn-primary mt-2">Share!</button>
</form>
{% endblock %}

Webタブの Reload:をしてから、
https://****.pythonanywhere.com/sns/ にアクセス、

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?