Фильтр Django QuerySet не работает с представлениями, показывая пустое представление, даже если есть записи - PullRequest
0 голосов
/ 03 января 2019

Я пытаюсь просмотреть определенный набор объектов с определенным атрибутом, используя фильтрацию QuerySet, однако, когда я использую фильтр, представление возвращается пустым. Не уверен, что я использую этот конкретный фильтр неправильно, или если я вызываю атрибут неправильно, однако я получил доступ к другим атрибутам (как показано ниже, атрибуту «status») и обнаружил, что он работает нормально.

views.py:

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from .models import *
from .forms import *



@login_required
def vendorView(request):
    return render(request, 'inv/vendorInventory.html')

@login_required
def consumerView(request):
    return render(request, 'inv/consumerInventory.html')

def unauthenticatedView(request):
    return render(request, 'inv/unauthenticatedInventory.html')
################ need to edit other views to render consumer/vendor/unauth

def display_drinks(request):
    items = Drinks.objects.all()
    context = {
        'items': items,
        'header': 'Drinks',
    }

    if not request.user.is_authenticated:
        items = Drinks.objects.filter(status='AVAILABLE')
        context = {
            'items': items,
            'header': 'Drinks',
        }
        return render(request, 'inv/unauthenticatedInventory.html', context)

    elif request.user.profile.vendor:
        items = Drinks.objects.filter(donatorID=request.user.username)
        context = {
            'items': items,
            'header': 'Drinks',
        }
        return render(request, 'inv/vendorInventory.html', context)

    elif not request.user.profile.vendor:
        items = Drinks.objects.filter(status='AVAILABLE')
        context = {
            'items': items,
            'header': 'Drinks',
        }
        return render(request, 'inv/consumerInventory.html', context)

инвентарь / models.py:

from django.db import models
from django.contrib.auth.models import User
from users.models import *



# Create your models here.

class Donation(models.Model):

    description = models.CharField(max_length=200, blank=False, help_text='Describe your donation here')

    choices = ( #for status
        ('AVAILABLE', 'Item ready to be picked up'),
        ('RESERVED', 'Item reserved'),
    )

    expiry = models.CharField(max_length=200, blank=False, help_text="Enter expiration date here")
    status = models.CharField(max_length=10, choices=choices, default='AVAILABLE')
    misc = models.CharField(max_length=50, blank=False, help_text='Miscellaneous info about your donation')
    donatorID = models.CharField(max_length=50, default = User.username)



    class Meta:
        abstract = True

    def __str__(self):
        return '{0}'.format(self.description)


class Foods(Donation):
    pass

class Drinks(Donation):
    pass

class MiscObjects(Donation):
    pass

Как видно, в models.py, donatorID присваивается объекту Donation и является именем пользователя. В функции display_drinks (в views.py), в первом elif, он должен использовать имя пользователя для фильтрации любых элементов, не имеющих соответствующего атрибута, помещать элементы в QuerySet, которые соответствуют друг другу - однако он отображается пустым, даже если есть элементы с соответствующими атрибутами.

Кто-нибудь знает, почему это происходит?

Спасибо.

edit: по запросу, вот vendorInventory.html:

{% extends "blog/base.html" %}

{% block body %}



<center>  <div class="add_buttons">


    <div class="btn-group-vertical">
      <a href="{% url 'display_foods' %}" class="btn btn-outline-info" role="button"> View Food</a>
      <a href="{% url 'add_food' %}" class="btn btn-outline-info" role="button"> Add Food</a>
    </div>

    <div class="btn-group-vertical">
      <a href="{% url 'display_drinks' %}" class="btn btn-outline-info" role="button">View Drinks</a>
      <a href="{% url 'add_drink' %}" class="btn btn-outline-info" role="button"> Add Drink</a>
    </div>

    <div class="btn-group-vertical">
      <a href="{% url 'display_miscObjects' %}" class="btn btn-outline-info" role="button"> View Misc</a>
      <a href="{% url 'add_miscObject' %}" class="btn btn-outline-info" role="button"> Add Misc</a>
    </div>


  </div>

  </center>

  <div>

    <h4>Currently Viewing {{ header }}</h4>
  </div>

  <table class="table table-hover">
    <thead>
      <tr>
        <th>id</th>
        <th>Description</th>
        <th>Expiry Date</th>
        <th>Status</th>
        <th>Misc</th>
        <th>Edit/Delete</th>

      </tr>
    </thead>

    <tbody>

      {% for item in items %}

      <tr>
        <td>{{ item.pk }}
        <td>{{ item.description }}</td>
        <td>{{ item.expiry }} </td>
        <td>{{ item.status }}</td>
        <td>{{ item.misc }}</td>

        {% if header|lower == "drinks" %}
        <td>
            <a href="{% url 'edit_drink' item.pk %}" class="btn btn-outline-info" role="button" aria-pressed="true" > Edit</a>
            <a href="{% url 'delete_drink' item.pk%}" class="btn btn-danger btn-sm" role="button" aria-pressed="true" > x </a>
        </td>
        {% elif header|lower == "foods" %}
        <td>
            <a href="{% url 'edit_food' item.pk %}" class="btn btn-outline-info" role="button" aria-pressed="true" > Edit</a>
            <a href="{% url 'delete_food' item.pk%}" class="btn btn-danger btn-sm" role="button" aria-pressed="true" > x </a>
        </td>
        {% else %}
        <td>
            <a href="{% url 'edit_miscObject' item.pk %}" class="btn btn-outline-info" role="button" aria-pressed="true" > Edit</a>
            <a href="{% url 'delete_miscObject' item.pk%}" class="btn btn-danger btn-sm" role="button" aria-pressed="true" > x </a>
        </td>
        {% endif %}
      </tr>

      {% endfor %}

    </tbody>
  </table>

{% endblock %}

forms.py:

from django import forms
from .models import *


class DrinkForm(forms.ModelForm):
    class Meta:
        model = Drinks
        fields = ('description', 'expiry', 'status', 'misc', 'donator')


class FoodForm(forms.ModelForm):
    class Meta:
        model = Foods
        fields = ('description', 'expiry', 'status', 'misc')


class MiscObjectForm(forms.ModelForm):
    class Meta:
        model = MiscObjects
        fields = ('description', 'expiry', 'status', 'misc')

class ReserveDrinkForm(forms.ModelForm):
    class Meta:
        model = Drinks
        fields = ('status',)


class ReserveFoodForm(forms.ModelForm):
    class Meta:
        model = Foods
        fields = ('status',)


class ReserveMiscObjectForm(forms.ModelForm):
    class Meta:
        model = MiscObjects
        fields = ('status',)

Ответы [ 2 ]

0 голосов
/ 03 января 2019
# models.py
from django.db import models
from users.models import *
# or if User model is not overwritten: from django.contrib.auth.models import User


class Donation(models.Model):
    choices = (  # for status
        ('AVAILABLE', 'Item ready to be picked up'),
        ('RESERVED', 'Item reserved'),
    )

    description = models.CharField(max_length=200, help_text='Describe your donation here')
    expiry = models.CharField(max_length=200, help_text="Enter expiration date here")
    status = models.CharField(max_length=10, choices=choices, default='AVAILABLE')
    misc = models.CharField(max_length=50, help_text='Miscellaneous info about your donation')
    donator = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        abstract = True

    def __str__(self):
        return self.description


class Foods(Donation):
    pass

class Drinks(Donation):
    pass

class MiscObjects(Donation):
    pass


# views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from users.models import *
# or if User model is not overwritten: from django.contrib.auth.models import User
from .models import *
from .forms import *



@login_required
def vendorView(request):
    return render(request, 'inv/vendorInventory.html')

@login_required
def consumerView(request):
    return render(request, 'inv/consumerInventory.html')

def unauthenticatedView(request):
    return render(request, 'inv/unauthenticatedInventory.html')
################ need to edit other views to render consumer/vendor/unauth

def display_drinks(request):
    items = Drinks.objects.all()
    context = {
        'items': items,
        'header': 'Drinks',
    }

    if not request.user.is_authenticated:
        items = Drinks.objects.filter(status='AVAILABLE')
        context = {
            'items': items,
            'header': 'Drinks',
        }
        return render(request, 'inv/unauthenticatedInventory.html', context)

    elif request.user.profile.vendor:
        items = Drinks.objects.filter(donator__username=request.user.username)
        context = {
            'items': items,
            'header': 'Drinks',
        }
        return render(request, 'inv/vendorInventory.html', context)

    elif not request.user.profile.vendor:
        items = Drinks.objects.filter(status='AVAILABLE')
        context = {
            'items': items,
            'header': 'Drinks',
        }
        return render(request, 'inv/consumerInventory.html', context)

Это будет работать, НО лучше использовать представления на основе классов здесь, например: официальная документация: https://docs.djangoproject.com/en/dev/topics/class-based-views/

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
from django.views.generic.list import ListView

# Better naming for model will be a "Drink" instead of "Drinks" (Django code style)
from .models import Drinks


class VendorView(LoginRequiredMixin, TemplateView):
    # better to use 'inv/vendor_inventory.html' naming style for PEP8 compatibility.
    template_name = 'inv/vendorInventory.html'


class ConsumerView(LoginRequiredMixin, TemplateView):
    template_name = 'inv/consumerInventory.html'

# Name for view, I think looks terrible ;)
class UnauthenticatedView(TemplateView):
    template_name = 'inv/unauthenticatedInventory.html'


class DrinksListView(ListView):
    model = Drinks
    context_object_name = 'items'    # Variable in template, better to use something like: context_object_name = 'drinks'

    def get_queryset(self):
        if self.request.user.is_authenticated():
            return Drinks.objects.filter(status='AVAILABLE')
        elif self.request.user.profile.vendor:
            return Drinks.objects.filter(donator__username=self.request.user.username)
        # Better to use "else:" here instead of "elif" (for all other logic).
        elif not self.request.user.profile.vendor:
            return Drinks.objects.filter(status='AVAILABLE')

Ответы на вопросы из комментариев:

Если вы хотите автоматически добавлять пользователя для каждого нового объекта Drinks, вы должны сделать что-то вроде этого: Прежде всего, вы должны исключить поле «донатор» в вашей форме:

# forms.py
class MyForm(forms.ModelForm):
    #.....
    class Meta: 
        model = Drinks
        exclude = ('donator', )

Если вы используете функциональные представления: Вы должны добавить что-то вроде этого:

# views.py
if request.GET: 
    form = MyForm()
if request.POST:
    form = MyForm(request.POST)
    if form.is_valid():
        drinks = form.save(commit=False)
        drinks.donator = request.user
        drinks.save()
return render(request, 'my_temlate.html', {'form': form}) 

Если вы используете представления на основе классов: вы должны переписать метод "post" таким же образом. Вы можете узнать больше здесь, также есть примеры: Как использовать CreateView с ModelForm

0 голосов
/ 03 января 2019

заменить это в модели donatorID = models.ForeignKey(User, on_delete=models.CASCADE)

При сохранении данных передают объект Users: variable_name = User.objects.get(username=request.user)

...