From fc511abac083fa57171ddd39b9ec6d410f4104ea Mon Sep 17 00:00:00 2001 From: Rohith Asrk Date: Fri, 17 Mar 2017 12:40:33 +0530 Subject: [PATCH] Fixes #96: Improve string representation of sortedm2m relationships --- README.rst | 10 ++++++++++ example/testapp/models.py | 8 +++++++- sortedm2m/fields.py | 19 ++++++++++++++----- sortedm2m_tests/models.py | 8 +++++++- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 3c95d19..18dbc20 100644 --- a/README.rst +++ b/README.rst @@ -77,6 +77,16 @@ Specifies how the field is called in the intermediate database table by which the relationship is ordered. You can change its name if you have a legacy database that you need to integrate into your application. +``base_class`` +~~~~~~~~~~~~~~ + +**Default:** ``None`` + +You can set the ``base_class``, which is the base class of the through model of +the sortedm2m relationship between models to an abstract base class containing +a ``__str__`` method to improve the string representations of sortedm2m +relationships. + Migrating a ``ManyToManyField`` to be a ``SortedManyToManyField`` ================================================================= diff --git a/example/testapp/models.py b/example/testapp/models.py index 4e6848a..98a89ec 100644 --- a/example/testapp/models.py +++ b/example/testapp/models.py @@ -10,9 +10,15 @@ def __unicode__(self): return self.plate +class m2mprint: + + def __unicode__(self): + return unicode(self.car) + " in " + unicode(self.parkingarea) + + class ParkingArea(models.Model): name = models.CharField(max_length=50) - cars = SortedManyToManyField(Car) + cars = SortedManyToManyField(Car, base_class=m2mprint) def __unicode__(self): return self.name diff --git a/sortedm2m/fields.py b/sortedm2m/fields.py index a6a34b1..661ca9c 100644 --- a/sortedm2m/fields.py +++ b/sortedm2m/fields.py @@ -216,13 +216,19 @@ class SortedManyToManyField(_ManyToManyField): Accept a boolean ``sorted`` attribute which specifies if relation is ordered or not. Default is set to ``True``. If ``sorted`` is set to ``False`` the field will behave exactly like django's ``ManyToManyField``. + + Accept a class ``base_class`` attribute which specifies the base class of + the intermediate model. It allows to customize the intermediate model. ''' - def __init__(self, to, sorted=True, **kwargs): + def __init__(self, to, sorted=True, base_class=None, **kwargs): self.sorted = sorted self.sort_value_field_name = kwargs.pop( 'sort_value_field_name', SORT_VALUE_FIELD_NAME) + # Base class of through model + self.base_class = base_class + super(SortedManyToManyField, self).__init__(to, **kwargs) if self.sorted: self.help_text = kwargs.get('help_text', None) @@ -376,16 +382,19 @@ def get_intermediate_model_to_field(self, klass): def create_intermediate_model_from_attrs(self, klass, attrs): name = self.get_intermediate_model_name(klass) - return type(str(name), (models.Model,), attrs) + base_classes = (models.Model, self.base_class) if self.base_class else (models.Model,) + + return type(str(name), base_classes, attrs) def create_intermediate_model(self, klass): # Construct and return the new class. from_field_name, from_field = self.get_intermediate_model_from_field(klass) to_field_name, to_field = self.get_intermediate_model_to_field(klass) sort_value_field_name, sort_value_field = self.get_intermediate_model_sort_value_field(klass) - - meta = self.get_intermediate_model_meta_class( - klass, from_field_name, to_field_name, sort_value_field_name) + meta = self.get_intermediate_model_meta_class(klass, + from_field_name, + to_field_name, + sort_value_field_name) attrs = { 'Meta': meta, diff --git a/sortedm2m_tests/models.py b/sortedm2m_tests/models.py index 170e8e0..f09cf69 100644 --- a/sortedm2m_tests/models.py +++ b/sortedm2m_tests/models.py @@ -3,8 +3,14 @@ from sortedm2m.fields import SortedManyToManyField +class m2mprint: + + def __unicode__(self): + return unicode(self.book) + + class Shelf(models.Model): - books = SortedManyToManyField('Book', related_name='shelves') + books = SortedManyToManyField('Book', related_name='shelves', base_class=m2mprint) class Book(models.Model):