#フォローしているユーザーをDMのトップ画面に設定しそのページに遷移するようにしたい。
現在Djangoでアプリ制作を行なっております。そこでDM機能の実装を行いました。
DM機能は上手く動くもののurlで自分以外のユーザーを指定するとエラーになってしまいます。
そこでDM機能にトップページを実装しフォローしているユーザーの一覧とユーザーをクリックした際にそのユーザーとのDM画面に遷移するような仕組みを作りたいと考えております。
複雑な構造ではございますがご教授頂きたいです。
##該当のコード
views.py(下記のDmListViewが機能しておりません)
python
1class ChannelFormMixin(FormMixin): 2 form_class = ChannelMessageForm 3 4 # success_url = './' 5 def get_success_url(self): 6 return self.request.path 7 8 # handle the form with this mixin 9 def post(self, request, *args, **kwargs): 10 if not request.user.is_authenticated: 11 raise PermissionDenied 12 form = self.get_form() 13 if form.is_valid(): 14 channel = self.get_object() 15 user = self.request.user 16 content = form.cleaned_data.get("content") 17 channel_obj = ChannelMessage.objects.create(channel=channel, user=user, content=content) 18 if request.is_ajax(): 19 # Django Rest Framework 20 return JsonResponse({"content": channel_obj.content, "username": channel_obj.user.username}, status=201) 21 return super().form_valid(form) 22 else: 23 if request.is_ajax(): 24 return JsonResponse({"errors": form.errors}, status=400) 25 return super().form_invalid(form) 26 27 28class ChannelDetailView(LoginRequiredMixin, ChannelFormMixin, DetailView): 29 template_name = 'private_message.html' 30 queryset = Channel.objects.all() 31 32 def get_context_data(self, *args, **kwargs): 33 context = super().get_context_data(*args, **kwargs) 34 obj = context['object'] 35 # if self.request.user not in obj.users.all(): 36 # raise PermissionDenied 37 context['is_channel_member'] = self.request.user in obj.users.all() 38 return context 39 40 # def get_queryset(self): 41 # user = self.request.user # definitely a user 42 # username = user.username 43 # qs = Channel.objects.all().filter_by_username(username) 44 # return qs 45 46 47class PrivateMessageDetailView(LoginRequiredMixin, ChannelFormMixin, DetailView): 48 template_name = 'dm/private_message.html' 49 50 # def get_template_names(self, *args, **kwargs): 51 # return ['dm/private_message.html'] 52 def get_object(self, *args, **kwargs): 53 username = self.kwargs.get("username") 54 my_username = self.request.user.username 55 if username == my_username: 56 my_channel_obj, _ = Channel.objects.get_or_create_current_user_private_message(self.request.user) 57 return my_channel_obj 58 channel_obj, _ = Channel.objects.get_or_create_private_message(my_username, username) 59 if channel_obj == None: 60 raise Http404 61 return channel_obj 62 63 64def private_message_view(request, username, *args, **kwargs): 65 if not request.user.is_authenticated: 66 return HttpResponse("Nope..") 67 my_username = request.user.username 68 channel_obj, created = Channel.objects.get_or_create_private_message(my_username, username) 69 if created: 70 print("yes it was") 71 channel_users = channel_obj.channeluser_set.all().values("user__username") 72 print(channel_users) 73 channel_messages = channel_obj.channelmessage_set.all() 74 print(channel_messages.values("content")) 75 return HttpResponse(f"channel items - {channel_obj.id}") 76 77 78# フォロー一覧 79class DmListView(LoginRequiredMixin, generic.ListView): 80 model = Connection 81 template_name = 'dm/dm_list.html' 82 context_object_name = 'users' 83 84 def get_queryset(self, **kwargs): 85 username = self.kwargs.get("username") 86 return Connection.objects.filter(follower__username=username)
urls.py
python
1app_name = 'dm' 2 3UUID_CHANNEL_REGEX = r'channel/(?P<pk>[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12})' 4 5urlpatterns = [ 6 path('', views.DmListView.as_view(), name='dm'), 7 re_path(UUID_CHANNEL_REGEX, views.ChannelDetailView.as_view()), 8 path("<str:username>/", views.PrivateMessageDetailView.as_view()), 9]
models.py
python
1User = settings.AUTH_USER_MODEL 2 3 4# Create your models here. 5class BaseModel(models.Model): 6 # 1, 2, 3, 4, 5, 6 7 id = models.UUIDField(default=uuid.uuid4, primary_key=True, db_index=True, editable=False) 8 timestamp = models.DateTimeField(auto_now_add=True) 9 updated = models.DateTimeField(auto_now=True) 10 11 # foreignkey 12 # textfield 13 14 class Meta: 15 abstract = True 16 17 18class ChannelMessage(BaseModel): 19 channel = models.ForeignKey("Channel", null=True, on_delete=models.SET_NULL) 20 user = models.ForeignKey(User, on_delete=models.CASCADE) 21 content = models.TextField() 22 23 24class ChannelUser(BaseModel): 25 channel = models.ForeignKey("Channel", on_delete=models.CASCADE) 26 user = models.ForeignKey(User, on_delete=models.CASCADE) 27 # permissions? 28 29 30# jon_snow -> ned_stark 31# ned_stark -> jon_snow 32 33# oursite.com/dm/jon_snow 34# oursite.com/dm/ned_stark 35 36class ChannelQuerySet(models.QuerySet): 37 def only_one(self): 38 return self.annotate(num_users=Count("users")).filter(num_users=1) 39 40 def only_two(self): 41 return self.annotate(num_users=Count("users")).filter(num_users=2) 42 43 def filter_by_username(self, username): 44 return self.filter(channeluser__user__username=username) 45 46 47class ChannelManager(models.Manager): 48 def get_queryset(self, *args, **kwargs): 49 return ChannelQuerySet(self.model, using=self._db) 50 51 def filter_by_private_message(self, username_a, username_b): 52 return self.get_queryset().only_two().filter_by_username(username_a).filter_by_username(username_b).order_by( 53 "timestamp") 54 55 def get_or_create_current_user_private_message(self, user): 56 qs = self.get_queryset().only_one().filter_by_username(user.username) 57 if qs.exists(): 58 return qs.order_by("timestamp").first(), False 59 channel_obj = Channel.objects.create() 60 ChannelUser.objects.create(user=user, channel=channel_obj) 61 return channel_obj, True 62 63 def get_or_create_private_message(self, username_a, username_b): 64 qs = self.filter_by_private_message(username_a, username_b) 65 if qs.exists(): 66 return qs.order_by("timestamp").first(), False # obj, created 67 User = apps.get_model("auth", model_name='User') 68 user_a, user_b = None, None 69 try: 70 user_a = User.objects.get(username=username_a) 71 except User.DoesNotExist: 72 return None, False 73 try: 74 user_b = User.objects.get(username=username_b) 75 except User.DoesNotExist: 76 return None, False 77 if user_a == None or user_b == None: 78 return None, False 79 channel_obj = Channel.objects.create() 80 ch_u_a = ChannelUser(user=user_a, channel=channel_obj) 81 ch_u_b = ChannelUser(user=user_b, channel=channel_obj) 82 ChannelUser.objects.bulk_create([ch_u_a, ch_u_b]) 83 return channel_obj, True 84 85 86class Channel(BaseModel): # models.model 87 # slack-like 88 # 1 user 89 # 2 users 90 # 2+ users 91 users = models.ManyToManyField(User, blank=True, through=ChannelUser) 92 # channel_type 93 # max_users 94 # status -> private, public 95 # slug -> Lookup slug 96 # title -> Channel name/title 97 98 objects = ChannelManager() 99 100 class Meta: 101 ordering = ['timestamp'] 102
dm_list.html
html
1{% block content %} 2 3<div class="col-6 tweet"> 4 <h1>DM</h1> 5 {% for user in users %} 6 <h3><a href="">{{ user.following.username }}</a></h3> 7 {% endfor %} 8 <a href="{% url 'app:tweet_list' %}"> 9 <button type="button" class="btn btn-lg btn-secondary mt-5">戻る<i class="fas fa-backward"></i></button> 10 </a> 11</div> 12 13{% endblock %}
private_message.html
python
1{% block content %} 2 3</style> 4 5<div class="col-6"> 6 Channel - {{ object.id }} 7 <h1>DM機能</h1> 8 9 <div id='message-container'> 10 {% for message in object.channelmessage_set.all %} 11 <div class='my-3 w-35 px-1 rounded {% if request.user == message.user %}mr-0 bg-primary text-white {% else %}bg-secondary ml-0{% endif %}'> 12 <b>{{ message.user.username }}</b> 13 14 <p>{{ message.content }}</p> 15 </div> 16 {% endfor %} 17 </div> 18 19 20 <h1>Channel Users</h1> 21 {% for channel_user in object.channeluser_set.all %} 22 <div> 23 {{ channel_user.user.username }} {% if request.user == channel_user.user %}this is you {% endif %} 24 </div> 25 26 {% endfor %} 27 28 <form id='message-form' action="{{ request.path }}" method='POST'> {% csrf_token %} 29 {{ form.as_p }} 30 <input id="content" type='submit' value='Message'/> 31 </form> 32</div> 33 34 35{% endblock %}
####自分以外のユーザーを指定した際に発生するエラー
Exception Type: AttributeError
Exception Value:Manager isn't available; 'auth.User' has been swapped for 'accounts.MyUser'
###試したこと
フォローユーザーの一覧を作成すべく、DmListViewを作成しましたが、機能しませんでした。ただエラーは出ておりません。
ここまで読んで下さりありがとう。
複雑な質問で申し訳ありません。
解決方法をご教授頂ければ幸いです。
####追記
view
python
1class DmListView(LoginRequiredMixin, generic.ListView): 2 model = Connection 3 template_name = 'dm/dm_list.html' 4 context_object_name = 'users' 5 6 def get_queryset(self, **kwargs): 7 username = self.kwargs['username'] 8 return Connection.objects.filter(follower__username=username)
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/06/01 15:15
2021/06/02 11:14
2021/06/02 13:09