Внедрить django-filter MultipleModelChoiceField для обратного поиска отношений?

Я использую django-фильтры для одного из своих проектов. В соответствии с документацией я реализовал фильтр продуктов (для цветов и материалов) для своих моделей продуктов. Но после многих попыток я все еще не могу реализовать обратный поиск размеров продукта, который находится в другой таблице ProductSize.

models.py

class Product(models.Model):
    product_name = models.CharField(max_length=500)
    product_color = models.ForeignKey(Colour,related_name='productcolor')
    product_material=models.ForeignKey(Material)

    def __str__(self):
        return self.product_name

class ProductSize(models.Model):
    product=models.ForeignKey('Product',related_name='details')
    value = models.CharField(max_length=50)
    stock= models.IntegerField(default=1)
    items_sold = models.IntegerField(default=0)
    description = models.TextField(blank=True)

    def __unicode__(self):
        return self.value 

class Colour(models.Model):
    colour=models.CharField(max_length=100)
    colour_code=models.CharField(max_length=100,null=True,blank=True)

    def __unicode__(self):
        return u'%s' %self.colour

class Material(models.Model):
    material=models.CharField(max_length=100)

    def __unicode__(self):
        return u'%s' %self.material

filters.py

class ProductFilter(django_filters.FilterSet):
    product_material=django_filters.ModelMultipleChoiceFilter(
        queryset=Material.objects.all(),
        widget=forms.CheckboxSelectMultiple
    )
    product_color=django_filters.ModelMultipleChoiceFilter(
        queryset=Colour.objects.all(),
        widget=forms.CheckboxSelectMultiple
    )

    class Meta:
        model = Product
        fields=['product_color','product_material']

views.py

def product_view(request):
    product=Product.objest.all()
    f = ProductMaterialFilter(request.GET, queryset=product)
    context={'filter':f,}
    return render(request,'product.html',context)

Версия Джанго:

django versions==1.10.8
django-filter==1.1.0

Мне нужно знать шаги для фильтрации размера по «значению» моделей ProductSize для ProductFilter.

см. здесь.

Любая помощь приветствуется.


person Arijit Mukherjee    schedule 15.03.2018    source источник
comment
value = models.CharField(max_length=50) обозначает размер? Я думаю, что это плохой дизайн данных...   -  person andilabs    schedule 15.03.2018
comment
Пожалуйста, скажите мне, насколько лучше может быть дизайн, учитывая, что запас продукта должен быть обновлен для определенного размера.   -  person Arijit Mukherjee    schedule 15.03.2018
comment
Я безумно быстрое обновление. Вопрос о фильтрации, а не о дизайне БД.   -  person andilabs    schedule 15.03.2018
comment
Посмотрите на github.com/andilabs/filters-demo.   -  person andilabs    schedule 16.03.2018


Ответы (1)


модели.py

from django.db import models


class Colour(models.Model):
    colour = models.CharField(max_length=100)
    colour_code = models.CharField(max_length=100,null=True,blank=True)

    def __unicode__(self):
        return u'%s' %self.colour


class Material(models.Model):
    material = models.CharField(max_length=100)

    def __unicode__(self):
        return u'%s' %self.material


class Size(models.Model):
    value = models.CharField(unique=True, max_length=4)

    def __unicode__(self):
        return self.value


class Product(models.Model):
    product_name = models.CharField(max_length=500)
    product_color = models.ForeignKey(Colour,related_name='productcolor')
    product_material = models.ForeignKey(Material)

    def __str__(self):
        return "{} ({}, {})".format(self.product_name, self.product_color, self.product_material)


class Stock(models.Model):
    product = models.ForeignKey('Product', related_name='details')
    size = models.ForeignKey('Size')
    stock = models.IntegerField(default=1)
    items_sold = models.IntegerField(default=0)
    description = models.TextField(blank=True)

    def __unicode__(self):
        return "{product_name}({material}, {color}) @size: {size}, available {available} out of: {stock}".format(
            product_name=self.size.value,
            material=self.product.product_material.material,
            color=self.product.product_color.colour,
            size=self.size.value,
            available=self.stock-self.items_sold,
            stock=self.stock
        )

фильтры.py

import django_filters
from django import forms

from products.models import Material, Colour, Stock, Size


class ProductFilter(django_filters.FilterSet):
    product__product_material = django_filters.ModelMultipleChoiceFilter(
        queryset=Material.objects.all(),
        widget=forms.CheckboxSelectMultiple
    )
    product__product_color = django_filters.ModelMultipleChoiceFilter(
        queryset=Colour.objects.all(),
        widget=forms.CheckboxSelectMultiple
    )

    size = django_filters.ModelMultipleChoiceFilter(
        queryset=Size.objects.all(),
        widget=forms.CheckboxSelectMultiple
    )

    class Meta:
        model = Stock
        fields = ['product__product_color', 'product__product_material', 'size']

демо:

https://github.com/andilabs/filters-demo

person andilabs    schedule 15.03.2018
comment
Мне нравится твой дизайн. Но просто в моем случае это невозможно, так как он уже находится в производстве, и изменение этого масштаба потребует изменений в кодовой базе для многих приложений, например. корзина, заказы, cms и т. д. Может быть, мне следует попробовать написать собственную логику в представлениях, чтобы сделать возможной фильтрацию по размеру. Большое спасибо за ваше время и предложение. Я постараюсь лучше спроектировать свои будущие проекты, чтобы избежать таких препятствий. - person Arijit Mukherjee; 16.03.2018