首页 > 解决方案 > 以 django 形式访问 ebay 等产品子类别

问题描述

我正在尝试复制 Ebay 等发布产品时使用的类别结构网站。例如,如果你想发布一个 iPhone 出售,你去发布一个广告,从表单上的下拉菜单中选择一个类别('电子和计算机'),然后选择“电话”的子类别,然后“iphone”的最后一个子类别。为了创建这个结构,我使用了 django-categories。在管理页面工作文件中创建产品,管理表单允许我从每个类别的下拉菜单中进行选择,但是我似乎无法在我自己的表单上复制相同的过程,让用户能够选择许多类别。

如果您不知道 django-categories 它是修改后的预序树遍历。

这是我的广告模型

class Advert(models.Model):

    title = models.CharField(max_length=100, blank=False, null=False)
    author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL)
    image = models.ImageField(upload_to='media/', blank=True, null=True)  
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
    quantity = models.IntegerField(blank=False, null=False)
    condition = models.CharField(max_length=10, choices=COND_CATEGORIES, blank=False, null=False)
    price = models.DecimalField(decimal_places=2, max_digits=14, blank=False, null=False)
    description = models.TextField(blank=False, null=False)
    date_posted = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    active = models.BooleanField(default=True)
    featured = models.BooleanField(default=False)
    search_vector = SearchVectorField(null=True, blank=True)

这是类别模型

class Category(CategoryBase):


    class Meta:
        verbose_name_plural = 'categories'

这是允许用户发布广告的表格

class PostAdvertForm(forms.ModelForm):

    title = forms.CharField(label='Ad Title', required=True)
    category = forms.ChoiceField(choices=Advert.category, label='Choose a category', required=True)
    price = forms.DecimalField(label='Price', required=True, widget=forms.TextInput())                                  
    description = forms.CharField(widget=forms.Textarea(attrs={'placeholder':
                                          ('Please provide a detailed description'),
                                          'autofocus': 'autofocus'}), label='Description', required=True)
    condition = forms.ChoiceField(choices=Advert.COND_CATEGORIES, label='Condition', required=True)
    quantity = forms.IntegerField(label='Quantity', required=True, widget=forms.TextInput())
    image = forms.ImageField(label='Upload an image', required=False)
    class Meta:
        model = Advert
        fields = (
            'title', 'category', 'quantity', 'condition', 'price', 'description', 
            'image')

由于“ForwardManyToOneDescriptor'对象不可迭代”,在选择字段上使用 advert.category 不起作用。

我的问题是如何让类别列表出现在选择字段上?

编辑:只是想知道,这是否可以在前端完全使用 jquery 实现,并通过清理后的数据发送选择的类别?这样我什至不需要在后端使用 django-categories,我可以存储大量的类别。

第二次编辑:

看起来我已经完成了第一部分的工作,我在下面粘贴了新的表单代码:

at = Advert.category.get_queryset()


class PostAdvertForm(forms.ModelForm):

    title = forms.CharField(label='Ad Title', required=True)
    category = forms.ModelChoiceField(queryset=cat, label='Choose a category', required=True)
    price = forms.DecimalField(label='Price', required=True, widget=forms.TextInput())                                  
    description = forms.CharField(widget=forms.Textarea(attrs={'placeholder':
                                          ('Please provide a detailed description'),
                                          'autofocus': 'autofocus'}), label='Description', required=True)
    condition = forms.ChoiceField(choices=Advert.COND_CATEGORIES, label='Condition', required=True)
    quantity = forms.IntegerField(label='Quantity', required=True, widget=forms.TextInput())
    image = forms.ImageField(label='Upload an image', required=False)
    class Meta:
        model = Advert
        fields = (
            'title', 'category', 'quantity', 'condition', 'price', 'description', 
            'image')

我以前从未使用过 jquery,这是创建流动下拉式菜单的最佳选择吗?我必须做到,这样他们就不能选择父类别,只能选择底部的子类别。

标签: djangoforms

解决方案


定义一个函数update_form_field_choices(例如在 中utils.py):

def update_form_field_choices(field, choices):
    """
    Update both field.choices and field.widget.choices to the same value (list of choices).
    """
    field.choices = choices
    field.widget.choices = choices

__init__然后,在中定义方法PostAdvertForm

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)

在这个函数中,调用这个函数,并your_choices()用一个返回正确选择的函数替换。记住选择格式(元组的元组)。

    update_form_field_choices(field=self.fields['category'], choices=your_choices())

另请记住,ModelForm为您定义表单字段,因此您不必显式定义它们,除非您想更改默认定义中的某些内容。


推荐阅读