Opened 19 years ago

Closed 17 years ago

#526 closed defect (duplicate)

Error when edit_inline model have unique_together constraint

Reported by: nesh <nesh [at] studioquattro [dot] co [dot] yu> Owned by: Adrian Holovaty
Component: Database layer (models, ORM) Version: dev
Severity: major Keywords:
Cc: jeff@…, nesh@…, gary.wilson@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Example:

class Locale(meta.Model):
    """ available languages """
    locale = meta.CharField(maxlength=5, unique=True)
    encoding = meta.CharField(maxlength=50, choices=ENCODINGS, default='utf_8')
    name = meta.CharField(maxlength=200, unique=True)
    plural = meta.TextField('plural form',
                            help_text='plural form expression, see: <a href="http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html" target="_blank">gettext</a>',
                            blank=True, null=True)
    nplurals = meta.PositiveSmallIntegerField('number of plural forms', blank=True, null=True)

    def __repr__(self):
        return self.name
    #

    def _manipulator_validate_plural(self, field_data, all_data):
        """ validate plurals """
        field_data = field_data.strip()
        if field_data == '':
            return ''

        if all_data['nplurals'].strip() == '':
            from django.core import validators
            raise validators.ValidationError('No nplurals is defined!')

        # try to compile plural expression
        try:
            from gettext import c2py
            c2py(field_data)
        except ValueError, err:
            from django.core import validators
            raise validators.ValidationError('Plural form expression error %s' % err)
    # _manipulator_validate_plural

    class META:
        ordering = ['locale']
        admin = meta.Admin(
            fields = (
                      (None, { 'fields': ('locale', 'encoding', 'name',),}),
                      ('Plurals', { 'fields': ('nplurals', 'plural'),}),
                      ),
            list_display = ('name', 'locale', 'encoding'),
        )
    # META
# Locale

class Message(meta.Model):
    """ messages """
    site = meta.ForeignKey(sites.Site, null=True)
    package = meta.ForeignKey(packages.Package, null=True)

    message = meta.CharField(maxlength=255)
    has_plural = meta.BooleanField(default=False)

    def __repr__(self):
        return self.message
    #

    class META:
        unique_together = (('site', 'package', 'message'),)
        admin = meta.Admin(
            fields = (
                      ('For', { 'fields': (('site', 'package'),),}),
                      (None, { 'fields': (('message', 'has_plural'),)}),
                      ),
            list_display = ('message', 'site', 'package', 'has_plural',),
            list_filter = ('site', 'has_plural',), #('site', 'package'),
           )
    # META
# Message

class Translation(meta.Model):
    """ translation of the message """
    locale = meta.ForeignKey(Locale)
    message = meta.ForeignKey(Message, edit_inline=meta.TABULAR, num_in_admin=2, num_extra_on_change=5)
    plural = meta.PositiveIntegerField(blank=True, null=True, default=None)
    text = meta.TextField(core=True)

    def _manipulator_validate_plural(self, field_data, all_data):
        """ validate plurals """
        field_data = field_data.strip()
        if field_data == '':
            return ''

        pl = int(field_data)
        locale = self.get_locale()
        message = self.get_message()

        if locale.nplurals is None:
            from django.core import validators
            raise validators.ValidationError('No plural form is defined for this locale!')

        if pl >= locale.nplurals:
            from django.core import validators
            raise validators.ValidationError('Plural form must be less than %s' % maxpl)

        if not message.has_plural:
            from django.core import validators
            raise validators.ValidationError("Message for this translation dosen't have has_plural set")
    # _manipulator_validate_plural

    def __repr__(self):
        if self.plural:
            return '%s[%d]: %s' % (self.get_locale().locale, self.plural, self.text)
        else:
            return '%s: %s' % (self.get_locale().locale, self.text)
    #

    class META:
        unique_together = (('locale', 'message', 'plural'),)
    # META

throws a exception in admin interface when I try to add new Message object.

There's been an error:

Traceback (most recent call last):

  File "/Users/nesh/devel/django/django/core/handlers/base.py", line 64, in get_response
    response = callback(request, **param_dict)

  File "/Users/nesh/devel/django/django/views/admin/main.py", line 766, in add_stage
    manipulator = mod.AddManipulator()

  File "/Users/nesh/devel/django/django/utils/functional.py", line 3, in _curried
    return args[0](*(args[1:]+moreargs), **dict(kwargs.items() + morekwargs.items()))

  File "/Users/nesh/devel/django/django/core/meta/__init__.py", line 1445, in manipulator_init
    self.fields.extend(f.get_manipulator_fields(rel_opts, self, change, name_prefix='%s.%d.' % (rel_opts.object_name.lower(), i), rel=True))

  File "/Users/nesh/devel/django/django/core/meta/fields.py", line 205, in get_manipulator_fields
    params['validator_list'].append(getattr(manipulator, 'isUnique%s' % '_'.join(field_name_list)))

AttributeError: MessageManipulatorAdd instance has no attribute 'isUniquelocale_message_plural'

Attachments (3)

manipulator_test.diff (1.6 KB ) - added by nesh <nesh [at] studioquattro [dot] co [dot] yu> 18 years ago.
manupulator tests
manipulator_test.2.diff (1.6 KB ) - added by nesh <nesh [at] studioquattro [dot] co [dot] yu> 18 years ago.
some errors fixed
manipulator_test.3.diff (2.3 KB ) - added by nesh <nesh [at] studioquattro [dot] co [dot] yu> 18 years ago.
final ;) tests -- pls, ignore previous

Download all attachments as: .zip

Change History (18)

comment:1 by jforcier@…, 19 years ago

I'm seeing the exact same issue (very similar Model, identical traceback) in the latest trunk checkout as of this date.

Additionally, #265 appears to address a similar issue, but its patch does not fix this specific form of the problem.

(sorry for the bolding, not trying to sound like a jerk, just needing emphasis =))

comment:2 by anonymous, 19 years ago

Cc: jforcier@… added

comment:3 by anonymous, 19 years ago

I'm getting the same error as well using trunk as of today. 'date' is a foreign key edited inline in my model.

AttributeError at /admin/news/newslists/add/
NewsListManipulatorAdd instance has no attribute 'isUniqueurl_date'
Request Method: GET
Request URL: http://localhost:8000/admin/news/newslists/add/
Exception Type: AttributeError
Exception Value: NewsListManipulatorAdd instance has no attribute 'isUniqueurl_date'
Exception Location: /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django/core/meta/fields.py in get_manipulator_fields, line 255

comment:4 by bshi@…, 19 years ago

Hi - I found the same thing; is there a workaround?

class PhotoTag( meta.Model ):
    tid = meta.ForeignKey( Tag, core = True )
    pid = meta.ForeignKey( Photo, core = True, verbose_name = "Photo Tag", edit_inline = meta.TABULAR, num_in_admin=1, num_extra_on_change=1 )
    
    class META:
        # following prevents identical tags on photo TODO: doesn't work
        unique_together = ( ( "tid", "pid" ), )

Results in

AttributeError at /admin/photo/photos/add/
PhotoManipulatorAdd instance has no attribute 'isUniquetid_pid'

comment:5 by nesh <nesh [at] studioquattro [dot] co [dot] yu>, 18 years ago

Cc: nesh@… added
Component: Admin interfaceDatabase wrapper
priority: normalhigh
Severity: normalmajor
Version: SVN

I almost forgot about this one, until bites me again :(

Any solution?

comment:6 by Jeff Forcier, 18 years ago

Cc: jeff@… added; jforcier@… removed

comment:7 by nesh <nesh [at] studioquattro [dot] co [dot] yu>, 18 years ago

unique_together = ( ( "tid", "pid" ), )

Strange, if you reverse order to ('pid', 'tid') then it works.

I'm trying to make test for that (in tests/modeltests/manipulators/models.py)

by nesh <nesh [at] studioquattro [dot] co [dot] yu>, 18 years ago

Attachment: manipulator_test.diff added

manupulator tests

by nesh <nesh [at] studioquattro [dot] co [dot] yu>, 18 years ago

Attachment: manipulator_test.2.diff added

some errors fixed

comment:8 by nesh <nesh [at] studioquattro [dot] co [dot] yu>, 18 years ago

I investigated a little further and it seems that there are two distinct bugs.

  • You must have related field in unique_together or you will get the same error.
  • order of fields in unique_together is important (second test). If you have related field after any other field you'll get this error.

p.s. Can someone with TRAC_ADMIN delete original example?

comment:9 by nesh <nesh [at] studioquattro [dot] co [dot] yu>, 18 years ago

You must have related field in unique_together or you will get the same error.

Update (and test update):

You must have filed for witch edit_inline=True in unique_together and this field must come first.

by nesh <nesh [at] studioquattro [dot] co [dot] yu>, 18 years ago

Attachment: manipulator_test.3.diff added

final ;) tests -- pls, ignore previous

comment:10 by nesh <nesh [at] studioquattro [dot] co [dot] yu>, 18 years ago

Summary: Exception when using unique_together in edit_inline modelError when edit_inline model have unique_together constraint

comment:11 by Gary Wilson <gary.wilson@…>, 18 years ago

Cc: gary.wilson@… added

comment:12 by Ramiro Morales, 18 years ago

see also #2415, #2470

comment:13 by Gary Wilson <gary.wilson@…>, 18 years ago

Triage Stage: UnreviewedAccepted

comment:14 by Nebojša Đorđević <nesh@…>, 18 years ago

Cc: nesh@… added; nesh@… removed

comment:15 by Simon G. <dev@…>, 17 years ago

Resolution: duplicate
Status: newclosed

Duplicate of #565

Note: See TracTickets for help on using tickets.
Back to Top