允许对django模型进行排序,并提供一个简单的管理界面来重新排序它们。
django-ordered-model的Python项目详细描述
Django订购型号
django有序模型允许对模型进行排序,并提供一个简单的管理 用于重新排序它们的接口。
基于https://djangosnippets.org/snippets/998/和 https://djangosnippets.org/snippets/259/
请参阅我们的compatability notes,以获得与旧的django和python版本一起使用的适当版本。
安装
$ python setup.py install
您可以使用pip:
$ pip install django-ordered-model
用法
将ordered_model
添加到SETTINGS.INSTALLED_APPS
中。
从OrderedModel
继承模型以使其有序:
fromdjango.dbimportmodelsfromordered_model.modelsimportOrderedModelclassItem(OrderedModel):name=models.CharField(max_length=100)classMeta(OrderedModel.Meta):pass
模型实例现在有一组方法来相对移动它们。
为了演示这些方法,我们创建了两个实例Item
:
foo=Item.objects.create(name="Foo")bar=Item.objects.create(name="Bar")
互换头寸
foo.swap(bar)
这将交换两个对象的位置。
在位置上向上移动位置
foo.up()foo.down()
上下移动一个物体只会使它与相邻物体交换位置 物体的正上方或正下方取决于方向。
移动到任意位置
foo.to(12)bar.to(13)
将对象移动到堆栈中的任意位置。这基本上设置了 将值排序为指定的整数。对象介于原始对象和新对象之间 位置按方向增减顺序值 移动。
将对象移动到参考上方或下方
foo.above(bar)foo.below(bar)
将对象直接移动到引用对象的上方或下方,增加或 减小两者之间所有对象的顺序值,具体取决于 移动方向。
移动到堆栈顶部
foo.top()
这会将order值设置为堆栈中的最低值并增加 高于移动对象一的所有对象的顺序值。
移动到堆栈底部
foo.bottom()
这会将order值设置为堆栈中的最高值并减少 低于移动对象1的所有对象的顺序值。
正在更新save()期间将更新的字段
出于性能原因,delete()、to()、below()、above()、top()和bottom() 方法使用django的update()方法更改 由于其中一个调用而被转移。如果模型中的字段 通常在自定义的save()方法中或通过其他应用程序级别进行更新 功能,如datetimefield(auto_now=true),您可以添加其他字段 传递给update()。这只会影响对象的顺序 由于对目标对象而不是目标对象的操作而被移动 对象本身。
foo.to(12,extra_update={'modified':now()}
获取上一个或下一个对象
foo.previous()foo.next()
previous()和next()获取下面正上方的相邻对象 在有序堆栈中,取决于方向。
子集排序
在某些情况下,仅在对象的子集上需要对对象排序。例如,
在多对一/多关系中为用户管理联系人列表的应用程序,
希望允许每个用户订购其联系人,而不管其他用户如何订购
选择他们的顺序。通过order_with_respect_to
参数支持此选项。
一个简单的例子如下:
classContact(OrderedModel):user=models.ForeignKey(User,on_delete=models.CASCADE)phone=models.CharField()order_with_respect_to='user'
如果对象相对于多个字段排序,order_with_respect_to
支持
定义多个字段的元组:
classModel(OrderedModel)# ...order_with_respect_to=('field_a','field_b')
在多对多关系中,您需要使用从OrderedModel派生的独立直通模型。 例如,管理带有配料的比萨饼的应用程序。
一个简单的例子如下:
classTopping(models.Model):name=models.CharField(max_length=100)classPizza(models.Model):name=models.CharField(max_length=100)toppings=models.ManyToManyField(Topping,through='PizzaToppingsThroughModel')classPizzaToppingsThroughModel(OrderedModel):pizza=models.ForeignKey(Pizza,on_delete=models.CASCADE)topping=models.ForeignKey(Topping,on_delete=models.CASCADE)order_with_respect_to='pizza'classMeta:ordering=('pizza','order')
您还可以为相关模型上的字段指定order_with_respect_to
。可以使用以下模型创建一个示例用例:
classItemGroup(models.Model):user=models.ForeignKey(User,on_delete=models.CASCADE)general_info=models.CharField(max_length=100)classGroupedItem(OrderedModel):group=models.ForeignKey(ItemGroup,on_delete=models.CASCADE)specific_info=models.CharField(max_length=100)order_with_respect_to='group__user'
这里的项被放在组中,组中的项使用了一些常规信息,但是项的顺序与项所在的组无关。
当您希望在基类上而不是在各种类的对象的有序列表中的子类上进行排序时,请指定完整的模块pa基类的th:
classBaseQuestion(OrderedModel):order_class_path=__module__+'.BaseQuestion'question=models.TextField(max_length=100)classMeta:ordering=('order',)classMultipleChoiceQuestion(BaseQuestion):good_answer=models.TextField(max_length=100)wrong_answer1=models.TextField(max_length=100)wrong_answer2=models.TextField(max_length=100)wrong_answer3=models.TextField(max_length=100)classOpenQuestion(BaseQuestion):answer=models.TextField(max_length=100)
自定义管理器和查询集
fromordered_model.modelsimportOrderedModelManager,OrderedModelclassItemManager(OrderedModelManager):passclassItem(OrderedModel):objects=ItemManager()
管理集成
若要在“管理更改列表”页中添加箭头以进行重新排序,可以使用
OrderedModelAdmin
和move_up_down_links
字段:
fromdjango.contribimportadminfromordered_model.adminimportOrderedModelAdminfrommodelsimportItemclassItemAdmin(OrderedModelAdmin):list_display=('name','move_up_down_links')admin.site.register(Item,ItemAdmin)
对于多对多关系,您需要以下内联线之一。
OrderedTabularInline
或OrderedStackedInline
就像django管理员一样。
对于OrderedTabularInline
它将如下所示:
fromdjango.contribimportadminfromordered_model.adminimportOrderedTabularInline,OrderedInlineModelAdminMixinfrommodelsimportPizza,PizzaToppingsThroughModelclassPizzaToppingsThroughModelTabularInline(OrderedTabularInline):model=PizzaToppingsThroughModelfields=('topping','order','move_up_down_links',)readonly_fields=('order','move_up_down_links',)extra=1ordering=('order',)classPizzaAdmin(OrderedInlineModelAdminMixin,admin.ModelAdmin):list_display=('name',)inlines=(PizzaToppingsThroughModelTabularInline,)admin.site.register(Pizza,PizzaAdmin)
对于OrderedStackedInline
它将如下所示:
fromdjango.contribimportadminfromordered_model.adminimportOrderedStackedInline,OrderedInlineModelAdminMixinfrommodelsimportPizza,PizzaToppingsThroughModelclassPizzaToppingsThroughModelStackedInline(OrderedStackedInline):model=PizzaToppingsThroughModelfields=('topping','order','move_up_down_links',)readonly_fields=('order','move_up_down_links',)extra=1ordering=('order',)classPizzaAdmin(OrderedInlineModelAdminMixin,admin.ModelAdmin):list_display=('name',)inlines=(PizzaToppingsThroughModelStackedInline,)admin.site.register(Pizza,PizzaAdmin)
测试套件
需要Docker。
$ script/test
与django和python的兼容性
django-ordered-model version | Django version | Python version |
---|---|---|
3.3.x | 2.x | 3.4 and above |
3.2.x | 2.x | 3.4 and above |
3.1.x | 2.x | 3.4 and above |
3.0.x | 2.x | 3.4 and above |
2.1.x | 1.x | 2.7 to 3.6 |
2.0.x | 1.x | 2.7 to 3.6 |