Django 管理页面:通过多个模型选择而不是原始文本来自定义 ID 的字典(JSONField)
Django admin page: Customize dictionary (JSONField) of IDs through multiple Models selects instead of raw text
我有一个模型,其中一个字段是 postgres.fields.JSONField。
要存储的 Json 有一个可变的 ID 字典引用数据库中的其他项目(可能 relations/attributes)。
请允许我说得更具体一点:
基本上,我正在尝试创建一个折扣系统,其中一些折扣适用于某些产品。 JSON 字段包含了解哪些产品可以获得折扣的约束条件。
例如:
如果我想对属于 "Beverages" 类别的所有产品应用 50% 的折扣,并且 "Beverages" 类别在数据库,折扣记录如下:
discount_type='percent'
discount='0.5'
filter_by={
'category': [5]
}
如果我想对 "Beverages" 类别 AND 中由比方说 CocaCola 制造的所有产品减价 20 美元,filter_by
字典看起来像:
discount_type='fixed amount'
discount='20'
filter_by={
'category': [5],
'manufacturer': [2] # Assuming coca-cola is the Manufacturer
# with id==2 in the 'Manufacturers'
# table of the database (NOTE: this is
# needed since CocaCola manufactures
# products besides "Beverages")
}
如果我想对特定产品应用 25% 的折扣(假设 id
为 3
的产品),字典将如下所示:
discount_type='percent'
discount='0.25'
filter_by={
'id': [3]
}
这个想法似乎足够灵活,可以满足我的需要,我(到目前为止)对此很满意。
现在,问题是如何在 Discount
模型的 Django 管理区域中 输入 这些值。
正如预期的那样,filter_by
字典呈现为最初看起来像这样的文本字段:
如果我想向它添加字段,我需要写下我想要的确切 JSON...这意味着如果我想对 "Beverages"类别,我需要去弄清楚该类别在数据库中的ID,然后手动输入{"category": [5]}
,同时在输入'
时要格外小心, :
,确保我不会错过 ]
或 [
...
Thaaaat...好吧,这不是很有帮助...
因为我只会按几个字段(category
、manufacturer
、product
...)进行过滤,这些字段实际上是数据库,我想为我可以过滤的每个 thingy 显示一个大的 MultiSelect 框,这样我就可以看到一个用户友好的列表,其中包含我可以过滤的所有元素,select一些,然后,当我点击 "Create discount" 时,我会得到 filter_by
字典(我还远没有担心如何生成字典,因为我什至不知道如何正确呈现管理表单)。
类似于 Django Admin 自动为我的产品类别所做的事情:
这真是太好了:一个产品可以属于多个类别。为此,Django 并排呈现两个 <select multiple
框,其中包含可用类别以及产品已经属于的类别...我可以通过鼠标划动 add/remove 个类别。 .. 真的,真的很好。但是 Django 可以做到这一点,因为它知道 categories
是 Product
模型中的 ManyToMany
关系。
class Product(models.Model):
parent = models.ForeignKey('self', null=True, blank=True)
manufacturer = models.ForeignKey('Manufacturer')
categories = models.ManyToManyField('Category',
related_name='products', blank=True)
Discount
模型的问题是 category
、manufacturer
或 product
没有 ManyToMany
字段。可怜的 Django 不知道 Discount
与所有这些东西相关:它只知道有一个 Json
字段。
我真的很想能够在 Django 区域中展示一堆 <select>
列出所有可能的过滤器(Category
、Manufacturer
、ID
...) 可以存储在 filter_by
字典中(一个带有双 <select>
的条目表示 Category
显示数据库中所有可用的类别,一个条目表示 Manufacturer
,显示所有可用的制造商......等等)。但是我真的,真的不知道该怎么做。
我可能会用我做过的一堆尝试让你厌烦,使用 Widgets
,试图通过 form
,通过 forms.ModelMultipleChoiceField
来表示 JSON 字段(顺便说一下,这似乎是最接近我想要的东西,虽然仍然很远)......但我认为这有点毫无意义,因为没有什么能接近我想要的。
像往常一样,感谢您阅读这封巨大的电子邮件,并提前致谢。任何提示都将不胜感激,即使只是 你也应该看看 "this"
您将需要一些 javascript 来将 json 字典放入一个漂亮的 HTML 小部件中,然后在 Django 处理程序中对其进行处理。
如果你想使用 Django admin 的 "magic",你必须给它提供它需要的输入以呈现漂亮的 UI 并为你的折扣系统创建模型:
class Discount(models.Model):
discount_type = models.TextField()
discount_percentage = models.FloatField()
class DiscountElement(models.Model):
discount = models.ForeignKey(Discount)
manufacturer = models.ForeignKey(Manufacturer, null=True)
category = models.ForeignKey(Category, null=True)
所以...我很欣赏@alfonso.kim的,但是为"rendering"[=116创建一个全新的Django模型的想法=] 目的对我来说听起来有点矫枉过正。请!不要误会我的意思:这可能是 "canonical" 的做法(我已经多次看到这种方法被推荐)并且可能比 I 做的更好,但我想展示 I 如何解决我的特定问题:
我查看了 Django 的源代码,特别是 ManyToMany
关系在 Admin 中的显示方式。如果你看看我上面的原始问题,我想弄清楚 Django 在编辑一个 product[=116= 时使用哪个 class 来显示 categories ](那个"double column select",给它起一个我非常喜欢的名字)。原来它是一个 django.forms.models.ModelMultipleChoiceField, "seasoned" with a hint of a FilteredSelectMultiple 小部件。
根据这些信息,我为我的 Coupon
class 创建了一个自定义管理 表单 ,手动添加我想要显示的字段:
class CouponAdminForm(forms.ModelForm):
brands = forms.ModelMultipleChoiceField(
queryset=Brand.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Brands", is_stacked=False))
categories = forms.ModelMultipleChoiceField(
queryset=Category.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Categories", is_stacked=False))
products = forms.ModelMultipleChoiceField(
queryset=Product.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Products", is_stacked=False))
def __init__(self, *args, **kwargs):
# ... we'll get back to this __init__ in a second ...
class Meta:
model = Coupon
exclude = ('filter_by',) # Exclude because we're gonna build this field manually
然后告诉 ModelAdmin
class 我的优惠券使用该表格而不是默认表格:
class CouponsAdmin(admin.ModelAdmin):
form = CouponAdminForm
# ... #
admin.site.register(Coupon, CouponsAdmin)
这样做会在处方集的 root 处显示三个表单的手动添加字段(brand
、categories
和 products
)。换句话说:这产生了与我的 Coupon
模型中其余字段处于同一级别的三个新字段。但是:它们并不是真正的 "first class" 字段,因为它们实际上是要确定我的模型(Coupon.filter_by
字段)中一个特定字段的内容,让我们记住,它看起来或多或少是一本字典喜欢:
filter_by = {
"brands": [2, 3],
"categories": [7]
}
为了向使用管理网页的人表明这三个字段不是优惠券模型中的 "really" 第一级字段,我决定将它们分组显示。
为此,我需要更改字段的 CouponsAdmin
布局。我不希望此分组影响我的 Coupon
模型的其他字段的显示方式,即使后来将新字段添加到模型中也是如此,所以我让表单的所有其他字段保持不变(换句话说:仅将 special/grouped 布局应用于表单中的 brands
、categories
和 products
字段)。令我惊讶的是,我无法在 ModelForm
class 中执行此操作。我不得不去 ModelAdmin
而不是(我真的不确定为什么...):
class CouponsAdmin(admin.ModelAdmin):
def get_fieldsets(self, request, obj=None):
fs = super(CouponsAdmin, self).get_fieldsets(request, obj)
# fs now contains only [(None, {'fields': fields})] meaning, ungrouped fields
filter_by_special_fields = (brands', 'categories', 'products')
retval = [
# Let every other field in the model at the root level
(None, {'fields': [f for f in fs[0][1]['fields']
if f not in filter_by_special_fields]
}),
# Now, let's create the "custom" grouping:
('Filter By', {
'fields': ('brands', 'categories', 'products')
})
]
return retval
form = CouponAdminForm
更多信息 fieldsets
here
成功了:
现在,当管理员用户通过此表单创建新的 Coupon
时(换句话说:当用户单击页面上的 "Save" 按钮时)我将获得一个额外的查询集我在自定义表单中声明的字段(一个查询集用于 brands
,另一个查询集用于 categories
,另一个用于 products
),但实际上我需要将该信息转换为字典。我能够通过覆盖模型的 Form:
的 save
方法来实现这一点
class CouponAdminForm(forms.ModelForm):
brands = forms.ModelMultipleChoiceField(queryset=Brand.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Brands", is_stacked=False))
categories = forms.ModelMultipleChoiceField(queryset=Category.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Categories", is_stacked=False))
products = forms.ModelMultipleChoiceField(queryset=Product.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Products", is_stacked=False))
def __init__(self, *args, **kwargs):
# ... Yeah, yeah!! Not yet, not yet...
def save(self, commit=True):
filter_by_qsets = {}
for key in ['brands', 'categories', 'products']:
val = self.cleaned_data.pop(key, None) # The key is always gonna be in 'cleaned_data',
# even if as an empty query set, so providing a default is
# kind of... useless but meh... just in case
if val:
filter_by_qsets[key] = val # This 'val' is still a queryset
# Manually populate the coupon's instance filter_by dictionary here
self.instance.filter_by = {key: list(val.values_list('id', flat=True).order_by('id'))
for key, val in filter_by_qsets.items()}
return super(CouponAdminForm, self).save(commit=commit)
class Meta:
model = Coupon
exclude = ('filter_by',)
在 "Save".
上正确填充了优惠券的 filter_by
字典
还有一些细节(使管理表单对用户更友好):在编辑 现有 Coupon
时,我想要 [=表格的 26=]、categories
和 products
字段将预填充优惠券 filter_by
字典中的值。
这里是修改 Form 的 __init__
方法的地方(请记住,我们正在修改的实例可以在 self.instance
表单的属性)
class CouponAdminForm(forms.ModelForm):
brands = forms.ModelMultipleChoiceField(queryset=Brand.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Brands", is_stacked=False))
categories = forms.ModelMultipleChoiceField(queryset=Category.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Categories", is_stacked=False))
products = forms.ModelMultipleChoiceField(queryset=Product.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Products", is_stacked=False))
def __init__(self, *args, **kwargs):
# For some reason, using the `get_changeform_initial_data` method in the
# CouponAdminForm(forms.ModelForm) didn't work, and we have to do it
# like this instead? Maybe becase the fields `brands`, `categories`...
# are not part of the Coupon model? Meh... whatever... It happened to me the
# same it happened to this OP in Whosebug:
super(CouponAdminForm, self).__init__(*args, **kwargs)
self.fields["brands"].initial = self.instance.filter_by.get('brands')
self.fields["categories"].initial = self.instance.filter_by.get('categories')
self.fields["products"].initial = self.instance.filter_by.get('products')
def save(self, commit=True):
filter_by_qsets = {}
for key in ['brands', 'categories', 'products']:
# ... explained above ...
就是这样。
截至目前(右现在,2017 年 3 月 19 日)这似乎可以很好地满足我的需要。
作为 alfonso.kim points out in his answer, I can not dynamically filter the different fields unless I change the window's Javascrip (or maybe I use the ChainedForeignKey
自定义模型?不知道:没试过)我的意思是,通过这种方法,我无法过滤管理网页上的 select 框,删除仅属于 selected 类别的产品,例如,我不能做 "if a user selects a brand
, filter categories
and products
so they only show elements that belong to that brand" 这样的事情。发生这种情况是因为当用户 select 是品牌时,浏览器和服务器之间没有 XHR (Ajax) 请求。基本上:流程是你获取表格 --> 你填写表格 --> 你POST 表单,当用户在表单上单击 "things" 时,浏览器 <--> 服务器之间没有通信。如果 brands
select 中的用户 selects "Coca cola",products
select 被过滤,并删除 plastic bags
来自可用的产品(例如)但是好吧......这种方法 "good enough" 满足我的需要。
请注意:此答案中的代码可能包含一些多余的操作,或者可以写得更好的东西,但到目前为止,它似乎工作正常(谁知道,也许我必须几天后编辑我的答案说 "I was completely wrong!! Please don't do this!" 但 到目前为止 似乎没问题)不用说:我欢迎任何评论建议任何人都必须说 :-)
我希望这对以后的人有所帮助。
我有一个模型,其中一个字段是 postgres.fields.JSONField。
要存储的 Json 有一个可变的 ID 字典引用数据库中的其他项目(可能 relations/attributes)。
请允许我说得更具体一点:
基本上,我正在尝试创建一个折扣系统,其中一些折扣适用于某些产品。 JSON 字段包含了解哪些产品可以获得折扣的约束条件。
例如:
如果我想对属于 "Beverages" 类别的所有产品应用 50% 的折扣,并且 "Beverages" 类别在数据库,折扣记录如下:
discount_type='percent' discount='0.5' filter_by={ 'category': [5] }
如果我想对 "Beverages" 类别 AND 中由比方说 CocaCola 制造的所有产品减价 20 美元,
filter_by
字典看起来像:discount_type='fixed amount' discount='20' filter_by={ 'category': [5], 'manufacturer': [2] # Assuming coca-cola is the Manufacturer # with id==2 in the 'Manufacturers' # table of the database (NOTE: this is # needed since CocaCola manufactures # products besides "Beverages") }
如果我想对特定产品应用 25% 的折扣(假设
id
为3
的产品),字典将如下所示:discount_type='percent' discount='0.25' filter_by={ 'id': [3] }
这个想法似乎足够灵活,可以满足我的需要,我(到目前为止)对此很满意。
现在,问题是如何在 Discount
模型的 Django 管理区域中 输入 这些值。
正如预期的那样,filter_by
字典呈现为最初看起来像这样的文本字段:
如果我想向它添加字段,我需要写下我想要的确切 JSON...这意味着如果我想对 "Beverages"类别,我需要去弄清楚该类别在数据库中的ID,然后手动输入{"category": [5]}
,同时在输入'
时要格外小心, :
,确保我不会错过 ]
或 [
...
Thaaaat...好吧,这不是很有帮助...
因为我只会按几个字段(category
、manufacturer
、product
...)进行过滤,这些字段实际上是数据库,我想为我可以过滤的每个 thingy 显示一个大的 MultiSelect 框,这样我就可以看到一个用户友好的列表,其中包含我可以过滤的所有元素,select一些,然后,当我点击 "Create discount" 时,我会得到 filter_by
字典(我还远没有担心如何生成字典,因为我什至不知道如何正确呈现管理表单)。
类似于 Django Admin 自动为我的产品类别所做的事情:
这真是太好了:一个产品可以属于多个类别。为此,Django 并排呈现两个 <select multiple
框,其中包含可用类别以及产品已经属于的类别...我可以通过鼠标划动 add/remove 个类别。 .. 真的,真的很好。但是 Django 可以做到这一点,因为它知道 categories
是 Product
模型中的 ManyToMany
关系。
class Product(models.Model):
parent = models.ForeignKey('self', null=True, blank=True)
manufacturer = models.ForeignKey('Manufacturer')
categories = models.ManyToManyField('Category',
related_name='products', blank=True)
Discount
模型的问题是 category
、manufacturer
或 product
没有 ManyToMany
字段。可怜的 Django 不知道 Discount
与所有这些东西相关:它只知道有一个 Json
字段。
我真的很想能够在 Django 区域中展示一堆 <select>
列出所有可能的过滤器(Category
、Manufacturer
、ID
...) 可以存储在 filter_by
字典中(一个带有双 <select>
的条目表示 Category
显示数据库中所有可用的类别,一个条目表示 Manufacturer
,显示所有可用的制造商......等等)。但是我真的,真的不知道该怎么做。
我可能会用我做过的一堆尝试让你厌烦,使用 Widgets
,试图通过 form
,通过 forms.ModelMultipleChoiceField
来表示 JSON 字段(顺便说一下,这似乎是最接近我想要的东西,虽然仍然很远)......但我认为这有点毫无意义,因为没有什么能接近我想要的。
像往常一样,感谢您阅读这封巨大的电子邮件,并提前致谢。任何提示都将不胜感激,即使只是 你也应该看看 "this"
您将需要一些 javascript 来将 json 字典放入一个漂亮的 HTML 小部件中,然后在 Django 处理程序中对其进行处理。
如果你想使用 Django admin 的 "magic",你必须给它提供它需要的输入以呈现漂亮的 UI 并为你的折扣系统创建模型:
class Discount(models.Model):
discount_type = models.TextField()
discount_percentage = models.FloatField()
class DiscountElement(models.Model):
discount = models.ForeignKey(Discount)
manufacturer = models.ForeignKey(Manufacturer, null=True)
category = models.ForeignKey(Category, null=True)
所以...我很欣赏@alfonso.kim的
我查看了 Django 的源代码,特别是 ManyToMany
关系在 Admin 中的显示方式。如果你看看我上面的原始问题,我想弄清楚 Django 在编辑一个 product[=116= 时使用哪个 class 来显示 categories ](那个"double column select",给它起一个我非常喜欢的名字)。原来它是一个 django.forms.models.ModelMultipleChoiceField, "seasoned" with a hint of a FilteredSelectMultiple 小部件。
根据这些信息,我为我的 Coupon
class 创建了一个自定义管理 表单 ,手动添加我想要显示的字段:
class CouponAdminForm(forms.ModelForm):
brands = forms.ModelMultipleChoiceField(
queryset=Brand.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Brands", is_stacked=False))
categories = forms.ModelMultipleChoiceField(
queryset=Category.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Categories", is_stacked=False))
products = forms.ModelMultipleChoiceField(
queryset=Product.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Products", is_stacked=False))
def __init__(self, *args, **kwargs):
# ... we'll get back to this __init__ in a second ...
class Meta:
model = Coupon
exclude = ('filter_by',) # Exclude because we're gonna build this field manually
然后告诉 ModelAdmin
class 我的优惠券使用该表格而不是默认表格:
class CouponsAdmin(admin.ModelAdmin):
form = CouponAdminForm
# ... #
admin.site.register(Coupon, CouponsAdmin)
这样做会在处方集的 root 处显示三个表单的手动添加字段(brand
、categories
和 products
)。换句话说:这产生了与我的 Coupon
模型中其余字段处于同一级别的三个新字段。但是:它们并不是真正的 "first class" 字段,因为它们实际上是要确定我的模型(Coupon.filter_by
字段)中一个特定字段的内容,让我们记住,它看起来或多或少是一本字典喜欢:
filter_by = {
"brands": [2, 3],
"categories": [7]
}
为了向使用管理网页的人表明这三个字段不是优惠券模型中的 "really" 第一级字段,我决定将它们分组显示。
为此,我需要更改字段的 CouponsAdmin
布局。我不希望此分组影响我的 Coupon
模型的其他字段的显示方式,即使后来将新字段添加到模型中也是如此,所以我让表单的所有其他字段保持不变(换句话说:仅将 special/grouped 布局应用于表单中的 brands
、categories
和 products
字段)。令我惊讶的是,我无法在 ModelForm
class 中执行此操作。我不得不去 ModelAdmin
而不是(我真的不确定为什么...):
class CouponsAdmin(admin.ModelAdmin):
def get_fieldsets(self, request, obj=None):
fs = super(CouponsAdmin, self).get_fieldsets(request, obj)
# fs now contains only [(None, {'fields': fields})] meaning, ungrouped fields
filter_by_special_fields = (brands', 'categories', 'products')
retval = [
# Let every other field in the model at the root level
(None, {'fields': [f for f in fs[0][1]['fields']
if f not in filter_by_special_fields]
}),
# Now, let's create the "custom" grouping:
('Filter By', {
'fields': ('brands', 'categories', 'products')
})
]
return retval
form = CouponAdminForm
更多信息 fieldsets
here
成功了:
现在,当管理员用户通过此表单创建新的 Coupon
时(换句话说:当用户单击页面上的 "Save" 按钮时)我将获得一个额外的查询集我在自定义表单中声明的字段(一个查询集用于 brands
,另一个查询集用于 categories
,另一个用于 products
),但实际上我需要将该信息转换为字典。我能够通过覆盖模型的 Form:
save
方法来实现这一点
class CouponAdminForm(forms.ModelForm):
brands = forms.ModelMultipleChoiceField(queryset=Brand.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Brands", is_stacked=False))
categories = forms.ModelMultipleChoiceField(queryset=Category.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Categories", is_stacked=False))
products = forms.ModelMultipleChoiceField(queryset=Product.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Products", is_stacked=False))
def __init__(self, *args, **kwargs):
# ... Yeah, yeah!! Not yet, not yet...
def save(self, commit=True):
filter_by_qsets = {}
for key in ['brands', 'categories', 'products']:
val = self.cleaned_data.pop(key, None) # The key is always gonna be in 'cleaned_data',
# even if as an empty query set, so providing a default is
# kind of... useless but meh... just in case
if val:
filter_by_qsets[key] = val # This 'val' is still a queryset
# Manually populate the coupon's instance filter_by dictionary here
self.instance.filter_by = {key: list(val.values_list('id', flat=True).order_by('id'))
for key, val in filter_by_qsets.items()}
return super(CouponAdminForm, self).save(commit=commit)
class Meta:
model = Coupon
exclude = ('filter_by',)
在 "Save".
上正确填充了优惠券的filter_by
字典
还有一些细节(使管理表单对用户更友好):在编辑 现有 Coupon
时,我想要 [=表格的 26=]、categories
和 products
字段将预填充优惠券 filter_by
字典中的值。
这里是修改 Form 的 __init__
方法的地方(请记住,我们正在修改的实例可以在 self.instance
表单的属性)
class CouponAdminForm(forms.ModelForm):
brands = forms.ModelMultipleChoiceField(queryset=Brand.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Brands", is_stacked=False))
categories = forms.ModelMultipleChoiceField(queryset=Category.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Categories", is_stacked=False))
products = forms.ModelMultipleChoiceField(queryset=Product.objects.all().order_by('name'),
required=False,
widget=FilteredSelectMultiple("Products", is_stacked=False))
def __init__(self, *args, **kwargs):
# For some reason, using the `get_changeform_initial_data` method in the
# CouponAdminForm(forms.ModelForm) didn't work, and we have to do it
# like this instead? Maybe becase the fields `brands`, `categories`...
# are not part of the Coupon model? Meh... whatever... It happened to me the
# same it happened to this OP in Whosebug:
super(CouponAdminForm, self).__init__(*args, **kwargs)
self.fields["brands"].initial = self.instance.filter_by.get('brands')
self.fields["categories"].initial = self.instance.filter_by.get('categories')
self.fields["products"].initial = self.instance.filter_by.get('products')
def save(self, commit=True):
filter_by_qsets = {}
for key in ['brands', 'categories', 'products']:
# ... explained above ...
就是这样。
截至目前(右现在,2017 年 3 月 19 日)这似乎可以很好地满足我的需要。
作为 alfonso.kim points out in his answer, I can not dynamically filter the different fields unless I change the window's Javascrip (or maybe I use the ChainedForeignKey
自定义模型?不知道:没试过)我的意思是,通过这种方法,我无法过滤管理网页上的 select 框,删除仅属于 selected 类别的产品,例如,我不能做 "if a user selects a brand
, filter categories
and products
so they only show elements that belong to that brand" 这样的事情。发生这种情况是因为当用户 select 是品牌时,浏览器和服务器之间没有 XHR (Ajax) 请求。基本上:流程是你获取表格 --> 你填写表格 --> 你POST 表单,当用户在表单上单击 "things" 时,浏览器 <--> 服务器之间没有通信。如果 brands
select 中的用户 selects "Coca cola",products
select 被过滤,并删除 plastic bags
来自可用的产品(例如)但是好吧......这种方法 "good enough" 满足我的需要。
请注意:此答案中的代码可能包含一些多余的操作,或者可以写得更好的东西,但到目前为止,它似乎工作正常(谁知道,也许我必须几天后编辑我的答案说 "I was completely wrong!! Please don't do this!" 但 到目前为止 似乎没问题)不用说:我欢迎任何评论建议任何人都必须说 :-)
我希望这对以后的人有所帮助。