Code

Opened 9 years ago

Closed 6 years ago

#565 closed defect (fixed)

Unique fields don't work on edit_inline models

Reported by: kyrrigle@… Owned by: nobody
Component: contrib.admin Version: master
Severity: normal Keywords: admin edit inline unique error nfa-fixed
Cc: kyrrigle@…, ep@…, christoph.rauch@…, frankie@…, mail@…, jarek.zgoda@…, avinash@…, Django565@…, matiassurdi@…, duke@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

There seems to be a bug with validating inline editable items that have unique=true.

To reproduce:

1) Modify the tutorial polls app so that the Choice model defines choice as:

    choice = meta.CharField(maxlength=200, core=True, unique=True)

2) Create a poll with two choices, click 'save and continue editing'

3) Add a third choice (with unique name) and click 'save'

You should see a "Choice with this choice already exists." validation error for the second choice.

Attachments (0)

Change History (20)

comment:1 Changed 8 years ago by david@…

  • Keywords admin edit inline unique error added
  • Version set to magic-removal

This seems to apply to models that don't themselves contain a unique field but references a model that does.

For example, I've got a model NetworkAddressMap that relates 3 separate models: NetworkIpAddress, NetworkMacAddress, and Hardware. NetworkAddressMap has foreign keys for all of these models, and the one that points to Hardware specifies edit_inline=models.TABULAR. With this setup, I can add entries from the Hardware interface, but when I attempt to edit it after saving, I get this error:

Traceback (most recent call last):
File "/usr/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/core/handlers/base.py" in get_response

  1. response = callback(request, *callback_args, callback_kwargs)

File "/usr/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/contrib/admin/views/decorators.py" in _checklogin

  1. return view_func(request, *args, kwargs)

File "/usr/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/views/decorators/cache.py" in _wrapped_view_func

  1. response = view_func(request, *args, kwargs)

File "/usr/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/contrib/admin/views/main.py" in change_stage

  1. new_object = manipulator.save(new_data)

File "/usr/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/manipulators.py" in save

  1. if rel_new_data[related.opts.pk.name][0]:

KeyError at /admin/trak/hardware/3/
'id'

I can edit any of these models individually, but when edited "inline" I get the above error.

comment:2 Changed 8 years ago by david@…

Disregard my previous addendum to this ticket. The error I described has nothing to do with this.

comment:3 Changed 8 years ago by anonymous

Similar goes here:

SVN: rev. 3002 (MR)

from django.db import models

class Customer( models.Model ):

name = models.CharField( maxlength=20, blank=False, unique=True )
def str( self ):

return self.name

class Admin:

pass

class Komputer( models.Model ):

Customer = models.ForeignKey( Customer, edit_inline=models.TABULAR, num_in_admin=1)
hwaddr = models.CharField( maxlength=17, unique=True, core=True )

def str(self):

return self.hwaddr

class Admin:

pass

Adding new Customer(and Komputer)... when added individually no problem occurs

Traceback (most recent call last):
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/core/handlers/base.py" in get_response

  1. response = callback(request, *callback_args, callback_kwargs)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/contrib/admin/views/decorators.py" in _checklogin

  1. return view_func(request, *args, kwargs)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/views/decorators/cache.py" in _wrapped_view_func

  1. response = view_func(request, *args, kwargs)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/contrib/admin/views/main.py" in add_stage

  1. errors = manipulator.get_validation_errors(new_data)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/forms/init.py" in get_validation_errors

  1. errors.update(field.get_validation_errors(new_data))

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/forms/init.py" in get_validation_errors

  1. self.run_validator(new_data, validator)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/forms/init.py" in run_validator

  1. validator(new_data.get(self.field_name, ), new_data)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/fields/init.py" in manipulator_validator_unique

  1. old_obj = self.manager.get({lookup_type: field_data})

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/manager.py" in get

  1. return self.get_query_set().get(*args, kwargs)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/query.py" in get

  1. obj_list = list(clone)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/query.py" in iter

  1. return iter(self._get_data())

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/query.py" in _get_data

  1. self._result_cache = list(self.iterator())

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/query.py" in iterator

  1. select, sql, params = self._get_sql_clause()

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/query.py" in _get_sql_clause

  1. tables2, joins2, where2, params2 = self._filters.get_sql(opts)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/query.py" in get_sql

  1. tables2, joins2, where2, params2 = val.get_sql(opts)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/query.py" in get_sql

  1. return parse_lookup(self.kwargs.items(), opts)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/query.py" in parse_lookup

  1. tables2, joins2, where2, params2 = lookup_inner(path, clause, value, opts, opts.db_table, None)

File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/Django-0.91-py2.4.egg/django/db/models/query.py" in lookup_inner

  1. raise TypeError, "Cannot resolve keyword '%s' into field" % name

TypeError at /admin/siec/customer/add/
Cannot resolve keyword 'hwaddr' into field

sqlite ver. 3.3.4

comment:4 Changed 8 years ago by Seer

  • Summary changed from Unique fields don't work on edit_inline models to Unique fields don''t work on edit_inline models

Hi all
im fine, gl all!

comment:5 Changed 7 years ago by Simon G. <dev@…>

  • Triage Stage changed from Unreviewed to Accepted
  • Version changed from magic-removal to SVN

I've replicated this with the current SVN and this model:

from django.db import models

# Create your models here.
class Poll(models.Model):
    question = models.CharField(maxlength=200)
    pub_date = models.DateTimeField('date published')

    class Admin:
        pass

class Choice(models.Model):
    poll = models.ForeignKey(Poll, edit_inline=models.STACKED, num_in_admin=3)
    choice = models.CharField(maxlength=200, core=True, unique=True)
    votes = models.IntegerField(core=True)

    class Admin:
        pass

However, it raises an IntegrityError (column choice is not unique) and not just a warning.

comment:6 Changed 7 years ago by Simon G. <dev@…>

  • Summary changed from Unique fields don''t work on edit_inline models to Unique fields don't work on edit_inline models

comment:7 Changed 7 years ago by Emanuele Pucciarelli <ep@…>

  • Cc ep@… added

comment:8 Changed 7 years ago by kent37@…

The root of this problem is in django/db/models/fields/__init__.py. When manipulator_validator_unique() is curried with a manipulator at line 250 (in 0.96 release), the manipulator.manager is the manager for the related model (the model being edited), not the model containing the ForeignKey. So the call to self.manager.get() in manipulator_validator_unique() (line 37) looks up the unique field in the wrong table.

comment:9 Changed 7 years ago by anonymous

  • Cc christoph.rauch@… added

comment:10 Changed 7 years ago by anonymous

  • Cc frankie@… added

comment:11 Changed 7 years ago by Simon G. <dev@…>

I've marked #5302, #526, #2470, #2641, #4639, #4490 as duplicates of this.

comment:12 Changed 7 years ago by Jan Oberst <mail@…>

  • Cc mail@… added

comment:13 Changed 6 years ago by zgoda

  • Cc jarek.zgoda@… added

comment:14 Changed 6 years ago by anonymous

  • Cc avinash@… added

comment:15 Changed 6 years ago by Kent Johnson <kent37@…>

There is a similar problem using unique_together in a model that is edited inline in another model's admin interface. This causes an AttributeError, e.g. unique_together = (('person', 'blog', 'role'),) causes this error:

  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/django/db/models/fields/__init__.py" in get_manipulator_fields
  240. params['validator_list'].append(getattr(manipulator, 'isUnique%s' % '_'.join(field_name_list)))

  AttributeError at /admin/stats/blog/1262/
  'ChangeManipulator' object has no attribute 'isUniqueperson_blog_role'

comment:16 Changed 6 years ago by Jason Green <Django@…>

  • Cc Django565@… added

comment:17 Changed 6 years ago by Matias Surdi <matiassurdi@…>

  • Cc matiassurdi@… added

comment:18 Changed 6 years ago by duke@…

  • Cc duke@… added

Some comments in a couple duplicates (#526 and #2470) point out that order matters in unique_together. Apparently the related field must appear first in the list of fields. This approach works for me.

I just thought I'd repeat that information here for anyone who ends up on this bug looking for a solution.

comment:19 Changed 6 years ago by mrts

  • Keywords nfa-fixed added

comment:20 Changed 6 years ago by brosner

  • Resolution set to fixed
  • Status changed from new to closed

This is no longer a problem since the merge of newforms-admin in [7967].

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.