Django-按字段比较用户对象

时间:2020-06-12 05:45:24

标签: python django python-3.x django-models django-views

我有一个Dictionary视图,其中显示了由特定(特殊)用户创建的单词列表:

class Dictionary(FilterView):
    model = Word
    template_name = 'vocab/dictionary.html'
    context_object_name = 'dict_list'
    paginate_by = 15
    filterset_class = WordFilter
    strict = False

    def get_queryset(self):
        qs = self.model.objects.filter(user__username__iexact='special_user')
        return qs

    def get_object(self):
        queryset = qs
        pk = self.kwargs.get('pk')
        if pk is None:
            raise AttributeError('pk expected in url')
        return get_object_or_404(queryset, pk=pk)

现在,我希望任何用户都可以访问此页面并添加他们想要的任何单词,例如:

def custom_create_word(request, object):
    if request.method == 'POST':
        pass
    if request.method =="GET":
        from .forms import WordForm
        from .models import Word
        word = Word.objects.get(pk=object)
        user = request.user
        target_word = word.target_word
        source_word = word.source_word
        deck_name = "My Words"
        fluency = 0
        new_word, created = Word.objects.get_or_create(user=user, target_word=target_word,
                                     source_word=source_word, deck_name=deck_name, fluency=fluency)

    return HttpResponseRedirect(reverse('vocab:dict'))

一切正常。但是在模板中,我希望按钮的外观有所不同,具体取决于登录用户是否已在其自己的列表中包含该单词(应该由target_word是否相同来判断)。我的模板如下所示:

<tr>
      {% for word in dict_list %}
      <td>{{word.target_word}}</td>
      <td>{{word.source_word}}</td>
      <td>
      {% if user_word %}
        <a href="" class="btn btn-success btn-sm" >Added</a>
      {% else %}
          <a href="javascript:" class="add-word btn btn-warning btn-sm" data-wordpk="{{word.pk}}">Add</a>
     {% endif %}
      </td>
    </tr>
    {% endfor %}

我想到的方法是在“字典”视图上覆盖get_context_data,以便我可以检查登录用户的target_word是否等于特殊用户的target_word ,并将此传递到上下文中。所以我的看法是:

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['filter'] = WordFilter(self.request.GET, queryset=self.get_queryset())
    special_user_word = Word.objects.filter(user__username__iexact='special_user', target_word='target_word')
    logged_user_word = Word.objects.filter(user=self.request.user, target_word='target_word')
    user_word = None
    if special_user_word == logged_user_word:
        user_word = True
    context['user_word'] = user_word
    return context

但是我到处都有None……有什么想法吗?

2 个答案:

答案 0 :(得分:1)

显然,它们不会相同,因为Word对象是完全不同的,因为它们是为custom_create_word内部的每个用户创建的。另外,user_word不适用于所有单词,您需要为每个单词提供它。您可以像这样使用conditional expression覆盖get_queryset方法:

from django.db.models import Value, Case, When, BooleanField

class WordListView(...):
    ...
    def get_queryset(self, **kwargs):
        queryset = super().get_queryset(**kwargs)
        special_user_word = Word.objects.filter(user__username__iexact='special_user', target_word='target_word').values('source_word', flat=True)
        return queryset.annotate(
            user_word=Case(
                When(source_word__in=special_user_word, then=Value(True)),
                default=Value(False),
                output_field=BoolenField()
           )
        )

在模板中的用法:

{% for word in dict_list %}
   {% if word.user_word %}
       already added
   {% else %}
       add
   {% endif %}
{% endfor %}

答案 1 :(得分:0)

终于让它起作用了!

def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['filter'] = WordFilter(self.request.GET, queryset=self.get_queryset())
        special_user_word = Word.objects.filter(user__username__iexact='special_user').values_list('target_word', flat=True)
        logged_user_word = Word.objects.filter(user=self.request.user).values_list('target_word', flat=True)
        user_word = list(set(special_user_word) & set(logged_user_word))
        context['user_word'] = user_word
        return context

在我的模板中:

{% if word.target_word in user_word %}