django-sortedm2m

repository·master·Indexed 19 days ago

https://github.com/jazzband/django-sortedm2m

A drop-in replacement for Django's ManyToManyField that remembers the order in which related objects are added. It provides the SortedManyToManyField for maintaining order via the .add() method, a specialized migration operation AlterSortedManyToManyField for transitioning from standard ManyToManyFields, and a drag-and-drop checkbox widget for the Django admin.

Tokens
941
Snippets
2
Records
4
Agent score
18%

What's inside django-sortedm2m

  1. Migrate ManyToManyField to SortedManyToManyField

    master

    Standard Django migrations created by makemigrations will not correctly handle the transition from ManyToManyField to SortedManyToManyField. To migrate:

    1. Change the field type in your models.py to SortedManyToManyField.
    2. Run python manage.py makemigrations to generate a migration file.
    3. Open the generated migration file and locate the operations list.
    4. Change migrations.AlterField to sortedm2m.operations.AlterSortedManyToManyField.
    5. Import AlterSortedManyToManyField from sortedm2m.operations within the migration file.

    This specialized operation ensures the intermediate table is updated, the ordering field is added, and default values are populated.

  2. Use SortedManyToManyField in Django models

    master

    Replace Django's standard ManyToManyField with SortedManyToManyField to maintain the order in which related objects are added. The order is preserved when using the .add() method.

    from django.db import models
    from sortedm2m.fields import SortedManyToManyField
    
    class Photo(models.Model):
        name = models.CharField(max_length=50)
        image = models.ImageField(upload_to='...')
    
    class Gallery(models.Model):
        name = models.CharField(max_length=50)
        photos = SortedManyToManyField(Photo)
    
    # Usage that preserves order:
    gallery = Gallery.objects.create(name='Photos ordered by name')
    for photo in Photo.objects.order_by('name'):
        gallery.photos.add(photo)
  3. Configure SortedManyToManyField in Django Admin

    master

    To use the drag-and-drop checkbox widget in the Django admin, follow these steps:

    1. Add 'sortedm2m' to your INSTALLED_APPS in settings.py to ensure CSS and JS assets are loaded.
    2. Important: Do NOT include the model in filter_horizontal or filter_vertical tuples in your ModelAdmin definition, as this will conflict with the custom widget.

    If you prefer using raw_id_fields, you can add the field name to that list. In this mode, the order in which IDs are entered into the input box determines the sort order.

    from django.contrib import admin
    
    # Option 1: Drag-and-drop widget (requires 'sortedm2m' in INSTALLED_APPS)
    class GalleryAdmin(admin.ModelAdmin):
        pass  # Do NOT use filter_horizontal
    
    # Option 2: Using raw_id_fields
    class GalleryAdmin(admin.ModelAdmin):
        raw_id_fields = ('photos',)
  4. Configure SortedManyToManyField arguments

    master

    The SortedManyToManyField accepts several arguments to customize its behavior:

    • sorted (bool, default: True): If set to False, it behaves like a standard Django ManyToManyField without any ordering or intermediate table fields for order.
    • sort_value_field_name (str, default: 'sort_value'): The name of the field in the intermediate database table used to store the ordering information. Useful for integrating with legacy databases.
    • base_class (class, default: None): The base class for the through model. You can provide an abstract base class with a __str__ method to improve string representations, or use it to add additional fields to the through model (note: manual migrations are required if adding custom fields).