【问题标题】:Djnago, is it possible to create multiple status choice with a model?Django,是否可以使用模型创建多个状态选择?
【发布时间】:2020-08-06 18:25:02
【问题描述】:

这实际上是我的models.py,这使我可以创建多项选择的状态:

class Status(models.Model):
      slug = models.SlugField(unique=True)
      category = models.TextField()


class Example(models.Model):
      category= models.ForeignKey(Status)

我希望有可能添加一个子类别。换句话说,如果我在status model 中创建一个新类别“产品”,我希望能够创建子类别选项,从类别中选择 dipendet,并且可以在我的示例模型中名为 sub_category 的新字段中进行选择。

广告示例:使用 Status.models 客户端可以创建产品的类别,例如“汽车”和相关的子类别“车轮”、“方向盘”等。之后,当填写 Example.models 并在类别“汽车”中选择时,客户端只能选择之前存储的子类别(“车轮”,“方向盘”)。我希望现在我的解释更好

【问题讨论】:

    标签: django django-models django-rest-framework django-forms django-views


    【解决方案1】:

    您可以多次为同一个模型设置外键,但您需要包含related_name 参数。

    全 Python 方式

    # models.py
    
    class Status(models.Model):
        slug = models.SlugField(unique=True)
        category = models.TextField()
        # This allows us to have hierarchy of categories.
        parent =  models.ForeignKey(
            "self", 
            null=True,
            blank=True,
            related_name="children", 
            related_query_name="child",
            on_delete=models.PROTECT,
        )
    
    
    class Example(models.Model):
        category = models.ForeignKey(
            Status, 
            related_name="example_categories",
            limit_choices_to={'parent': None},
        )
        # This field is hidden on new objects.
        sub_category = models.ForeignKey(
            Status,
            related_name="example_sub_categories",
            null=True,
            blank=True,
        )
    
    # forms.py
    
    class ExampleForm(forms.ModelForm):
        class Meta:
            model = Example
            fields = '__all__'
    
        def __init__(self, *args, **kwargs):
            # When we instantiate the form, we check if the object 'instance' exists.
            # If it does not, we hide the `sub_category` field.
            # Otherwise we restrict the queryset to children of the `category` field.
    
            # NOTE: this will need to be properly cleaned. It does not prevent editing
            # the parent `category` after the `sub_category` has already been saved.
            instance = kwargs.get('instance')
            if not instance:
                self.fields.get('sub_category').widget = forms.HiddenInput()
            else:
                sub_cateogries = Status.objects.filter(parent=instance.category).all()
                self.fields.get('sub_category').queryset = sub_cateogries
    
    
    # admin.py
    
    @admin.register(Example)
    class ExampleAdmin(admin.ModelAdmin):
        form = ExampleForm
    

    这种方法的缺点是需要保存对象一次,然后才能编辑子类别。这并不理想,因为它为对象管理周期增加了第二步。

    更好的方法

    处理这个的更好的方法涉及更多,并且需要一些 JS,所以我不会在这里提供代码。但是,我将解释它是什么以及如何完成。

    您可以使用 Select2 对自定义管理视图执行 AJAX 请求,该视图将子类别列表作为 JSON 数组返回。

    添加自定义管理视图非常简单,只需确保检查user.is_staff 和适当的权限即可。您可以通过覆盖 ExampleAdmin 类中的 get_urls() 方法来添加 URL。像这样的工作......

    def get_urls(self):
        return [
            path(
                "auto_field/", 
                self.admin_site.admin_view(YourView.as_view()), 
                name='example_select2',),
        ] + super().get_urls()
    

    能够进行这些类型的更改是让您的 Django 更上一层楼的核心。第一个选项有效,但如果可以,请选择第二个。

    【讨论】:

    • 感谢@D.Morell,但也许我没有很好地解释自己。使用状态模型,我创建了我的类别和相关的 sub_category。之后,在示例模型中(使用表单模型)我选择类别,然后选择与类别相关的 sub_category。
    • 广告示例:使用 Status.models 客户端可以创建产品的类别,例如“汽车”和相关的子类别“车轮”、“方向盘”等。之后,当填写 Example.models 并在类别“汽车”中选择时,客户端只能选择之前存储的子类别(“车轮”,“方向盘”)。我希望现在我的解释更好
    猜你喜欢
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 2020-04-02
    相关资源
    最近更新 更多