【问题标题】:One-way delete delete Django Channels thread单向删除删除 Django Channels 线程
【发布时间】:2019-08-09 20:37:58
【问题描述】:

我正在尝试让用户可以从收件箱中删除与其他用户的线程。

我已经关注了 Django Docs DeleteView 虽然这可能是完全错误的。

views.py

class InboxView(LoginRequiredMixin, ListView):
    template_name = 'chat/inbox.html'
    context_object_name = 'threads'
    def get_queryset(self):
        return Thread.objects.by_user(self.request.user).order_by('-timestamp')
        # by_user(self.request.user)

class ThreadView(LoginRequiredMixin, FormMixin, DetailView):
    template_name = 'chat/thread.html'
    form_class = ComposeForm
    success_url = '#'

    def get_queryset(self):
        return Thread.objects.by_user(self.request.user)

    def get_object(self):
        other_username  = self.kwargs.get("username")
        obj, created    = Thread.objects.get_or_new(self.request.user, other_username)
        if obj == None:
            raise Http404
        return obj

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['form'] = self.get_form()
        return context

    def post(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return HttpResponseForbidden()
        self.object = self.get_object()
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

    def form_valid(self, form):
        thread = self.get_object()
        user = self.request.user
        message = form.cleaned_data.get("message")
        ChatMessage.objects.create(user=user, thread=thread, message=message)
        return super().form_valid(form)

class ThreadDeleteView(DeleteView):
    model = Thread
    success_url = reverse_lazy('inbox')

models.py

class ThreadManager(models.Manager):
    def by_user(self, user):
        qlookup = Q(first=user) | Q(second=user)
        qlookup2 = Q(first=user) & Q(second=user)
        qs = self.get_queryset().filter(qlookup).exclude(qlookup2).distinct()
        return qs

    # method to grab the thread for the 2 users
    def get_or_new(self, user, other_username): # get_or_create
        username = user.username
        if username == other_username:
            return None
        # looks based off of either username
        qlookup1 = Q(first__username=username) & Q(second__username=other_username)
        qlookup2 = Q(first__username=other_username) & Q(second__username=username)
        qs = self.get_queryset().filter(qlookup1 | qlookup2).distinct()
        if qs.count() == 1:
            return qs.first(), False
        elif qs.count() > 1:
            return qs.order_by('timestamp').first(), False
        else:
            Klass = user.__class__
            user2 = Klass.objects.get(username=other_username)
            if user != user2:
                obj = self.model(
                        first=user,
                        second=user2
                    )
                obj.save()
                return obj, True
            return None, False

class Thread(models.Model):
    first        = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_first')
    second       = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_second')
    updated      = models.DateTimeField(auto_now=True)
    timestamp    = models.DateTimeField(auto_now_add=True)

    objects      = ThreadManager()

    def __str__(self):
        return f'{self.id}'

    @property
    def room_group_name(self):
        return f'chat_{self.id}'

    def broadcast(self, msg=None):
        if msg is not None:
            broadcast_msg_to_chat(msg, group_name=self.room_group_name, user='admin')
            return True
        return False

带有删除按钮的html线程页面

<!-- Delete Thread -->
          <form action="{% url 'chat:thread_delete' user.username %}" method='post'>  {% csrf_token %}
            <button type='submit' class='btn btn-light'>
              <i class="fas fa-trash-alt" style="color:royalblue"></i>
            </button>
          </form>

urls.py

app_name = 'chat'
urlpatterns = [
    path('', chat_views.InboxView.as_view(), name='inbox'),
    re_path(r"^(?P<username>[\w.@+-]+)", chat_views.ThreadView.as_view(), name='thread'),
    re_path(r"^(?P<username>[\w.@+-]+)/delete/", chat_views.ThreadDeleteView.as_view(), name='thread_delete'),
]

我不断收到错误

TypeError at /messages/userthree/delete/ cannot unpack non-iterable NoneType object

这是由views.py 行引起的

self.object = self.get_object()
obj, created    = Thread.objects.get_or_new(self.request.user, other_username)

【问题讨论】:

  • 你试过打印出“other_username”吗?
  • 是的,它会打印登录用户

标签: python django django-views django-channels


【解决方案1】:

我认为这里的问题是您的 get_or_new() 方法中有一个没有返回元组的 return 语句:

if username == other_username:
    return None

这会导致视图崩溃,因为它希望将一个元组解包为两个变量。返回一个元组应该解决:

if username == other_username:
    return None, None

【讨论】:

  • 谢谢,我明白你的意思了。在我更改返回元组的方法并调用DeleteView 后,url 从ThreadView url http://127.0.0.1:8000/messages/newuser3 其中newuser3 是另一个用户到DeleteView url http://127.0.0.1:8000/messages/trilla/delete/ 其中trilla 是我,或登录用户。然后我得到一个404 not found。发生此错误是因为 DeleveView url 配置不正确吗?
  • 我已将DeleteView url 更改为{% url 'chat:thread_delete' thread.second %},这不会引发任何错误,但仍然保持线程完好,并且不会重定向到inbox
  • 你能发布整个views.py吗?似乎当obj 为 None 时,视图将重定向到无法查找的 URL。
  • DeleteView 表单似乎要转到正确的 URL,但它在 request.POST 之后仍停留在 ../username/delete/ URL 上
  • 好吧,问题是当当前用户试图删除自己的线程时,username == other_usernameTrue,我们返回None, None。然后会导致来自if obj == None: raise Http404 的 404。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多