python、djangoの初心者で、参考書を参考し、SNSアプリを写経しているのですが

Cannot resolve keyword 'groups' into field.

というエラーに行き詰っています。
anaconda。windows10を使用しています。

だれか心優しい方助けていただけないでしょうか。
エラーコード

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/sns/

Django Version: 2.2.5
Python Version: 3.7.4
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'sns']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\core\handlers\base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\core\handlers\base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
  21.                 return view_func(request, *args, **kwargs)

File "C:\Users\tumek\Desktop\django_app\sns\views.py" in index
  65.         messages = get_your_group_message(request.user,glist,None)

File "C:\Users\tumek\Desktop\django_app\sns\views.py" in get_your_group_message
  299.             |Q(groups__in=me_groups))[:100]

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\db\models\manager.py" in manager_method
  82.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\db\models\query.py" in filter
  892.         return self._filter_or_exclude(False, *args, **kwargs)

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\db\models\query.py" in _filter_or_exclude
  910.             clone.query.add_q(Q(*args, **kwargs))

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\db\models\sql\query.py" in add_q
  1290.         clause, _ = self._add_q(q_object, self.used_aliases)

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\db\models\sql\query.py" in _add_q
  1312.                     current_negated, allow_joins, split_subq, simple_col)

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\db\models\sql\query.py" in _add_q
  1318.                     split_subq=split_subq, simple_col=simple_col,

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\db\models\sql\query.py" in build_filter
  1190.         lookups, parts, reffed_expression = self.solve_lookup_type(arg)

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\db\models\sql\query.py" in solve_lookup_type
  1049.         _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())

File "C:\Users\tumek\Anaconda3\envs\myspace\lib\site-packages\django\db\models\sql\query.py" in names_to_path
  1420.                                      "Choices are: %s" % (name, ", ".join(available)))

Exception Type: FieldError at /sns/
Exception Value: Cannot resolve keyword 'groups' into field. Choices are: content, good, good_count, group, group_id, id, owner, owner_id, pub_date, share_count, share_id

ソースコード

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']

#検索フォーム

class SearchForm(forms.Form):
    search = forms.CharField(max_length=100)


#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)],
        )


#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)

#投稿フォーム

class PostForm(forms.Form):
    content = forms.CharField(max_length=500, \
            widget = forms.Textarea)
    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])],
        )

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.models import Message,Friend,Group,Good
from.forms import GroupCheckForm,GroupSelectForm, \
    SearchForm,FriendsForm,CreateGroupForm,PostForm

from django.db.models import Q
from django.contrib.auth.decorators import login_required

#indexのview関数

@login_required(login_url='/admin/login/')
def index(request):
    #publicのuserを取得
    (public_user, public_group)=get_public()

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


        #Groupsのチェックを更新した時の処理
        if request.POST['mode'] == '__check_form__':
            #フォームの用意
            searchform = SearchForm()
            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, None)
        #Groupsメニューを変更したときの処理
        if request.POST['mode'] == '__search_form__':
            # フォームの用意
            searchform = SearchForm(request.POST)
            checkform = GroupCheckForm(request.user)
            #Groupのリストを取得
            gps = Group.objects.filter(owner=request.user)
            glist = [public_group]
            for item in gps:
                glist.append(item)
            #メッセージを取得
            message = get_your_group_message(request.user, glist, \
                    request.POST['search'])
    #GETアクセス時の処理
    else:
        #フォームの用意
        searchform = SearchForm()
        checkform = GroupCheckForm(request.user)
        #Groupのリストを取得
        gps =Group.objects.filter(owner=request.user)
        glist = [public_group]
        for item in gps:
            glist.append(item)
        #メッセージの取得
        messages = get_your_group_message(request.user,glist,None)
    #共通処理
    params = {
            'login_user':request.user,
            'contents':messages,
            'check_form':checkform,
            'search_form':searchform,
        }
    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':
        #Groupメニュー選択肢の処理
        if request.POST['mode'] == '__groups_form__':
            #選択したGroup名を取得
            sel_group = request.POST['groups']
            #Groupを取得
            gp = Group.objests.filter(owner=request.user) \
                .filter(title=sel_group).first()
            #Groupに含まれるFriendsを取得
            fds = Friend.objects.filter(owner=request.user) \
                .filter(group=gp)
            #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()
            #チェックしたFriendsを取得
            sel_fds = request.POST.getlist('friends')
            #FriendsのUserを取得
            sel_users = User.objects.filter(username__in=sel_fds)
            #Userのリストに含まれるユーザーが登録したFriendsを取得
            fds = Friends.objects.filter(owner.request.user) \
                .filter(user__in=sel_users)
            #すべてのFriendsに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')

    # ここからFriendの登録処理
    frd = Friend()
    frd.owner = request.user
    frd.user = add_user
    frd.group = public_group
    frd.save()

    # メッセージを設定

    message.success(request, add_user.username +'を追加しました \
        group ページに移動して、追加したfriendをメンバーに設定して下さい')
    return redirect(to='/sns')

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

#メッセージのポスト処理
@login_required(login_url='/admin/login/')
def post(requset):
    #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):
    #shareするmessageの取得
    share = Message.objects.get(id=share_id)

    #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.succces(request,'すでにメッセージにgoodしています')
        return redirect(to='sns/')
    #messaseの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/')

#これ以降はview関数ではなく普通の関数==================================
#指定されたグループおよび検索文字によるmessageの取得
def get_your_group_message(owner, glist, find):
        #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)   
    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の取得
    if find == None:
        messages = Message.objects.filter(Q(group__in=groups) \
            |Q(groups__in=me_groups))[:100]
    else:
        messages = Message.objects.filter(Q(group__in=groups) \
            |Q(groups__in=me_groups)).filter(content__contains=find)[:100]
    return messages 
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)