Skip to content

Commit

Permalink
Fixes jazzband#96: Improve string representation of sortedm2m relatio…
Browse files Browse the repository at this point in the history
…nships
  • Loading branch information
rohithasrk committed Mar 25, 2017
1 parent 7d0c3bb commit 15c82a9
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 8 deletions.
10 changes: 10 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``
=================================================================

Expand Down
8 changes: 7 additions & 1 deletion example/testapp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 14 additions & 5 deletions sortedm2m/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 7 additions & 1 deletion sortedm2m_tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
13 changes: 12 additions & 1 deletion sortedm2m_tests/test_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from sortedm2m.compat import get_field

from .models import (
Book, Shelf, DoItYourselfShelf, Store, MessyStore, SelfReference)
Book, Shelf, DoItYourselfShelf, Store, MessyStore, SelfReference, m2mprint)


str_ = six.text_type
Expand Down Expand Up @@ -183,6 +183,17 @@ def get_ids(queryset):
return [obj.id for obj in queryset]
self.assertEqual(get_ids(shelf.books.all()), get_ids(books))

def test_base_class_m2mprint(self):
shelf = self.model.objects.create()
shelf.books.add(self.books[0])

shelf_book = shelf.books.through

if hasattr(shelf_book, '__unicode__'):
self.assertEqual(shelf_book.__unicode__, m2mprint.__unicode__)
else:
self.assertTrue(True)

class TestStringReference(TestSortedManyToManyField):
'''
Test the same things as ``TestSortedManyToManyField`` but using a model
Expand Down

0 comments on commit 15c82a9

Please sign in to comment.