Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception when using models having primary key names different from 'id' #413

Closed
kouete opened this issue May 11, 2015 · 6 comments
Closed
Milestone

Comments

@kouete
Copy link

kouete commented May 11, 2015

To reproduce the issue, add a custom primary_key field to the FkModel test model
FkModelId = models.AutoField('ID', primary_key=True, editable=False)

@python_2_unicode_compatible
class FkModel(models.Model):
    FkModelId = models.AutoField('ID', primary_key=True, editable=False)
    name = models.CharField(max_length=200)
    relation = models.ForeignKey('self', null=True, blank=True)
    noise = models.ForeignKey('OtoModel', null=True, blank=True)
    taxpayeraccount = models.ForeignKey(iTaxPayerAccount, null=True, blank=True)

    for_inline = models.ForeignKey('self', null=True, blank=True,
                                   related_name='reverse_for_inline')
    def __str__(self):
        return self.name

Following exception is thrown when adding new values to this model

OperationalError at /admin/basic/fkmodel/2/
no such column: id
Request Method: GET
Request URL:    http://eternity:8000/admin/basic/fkmodel/2/
Django Version: 1.7.3
Exception Type: OperationalError
Exception Value:    
no such column: id

The problem is the statement

            clauses = ' '.join(['WHEN id=%s THEN %s' % (pk, i) for i, pk in
                    enumerate(self.values)])

in the method order_choices of autocomplete_light/autocomplete/model.py

It is assumed the primary key name is id

    def order_choices(self, choices):
        """
        Order choices using :py:attr:`order_by` option if it is set.
        """
        if self.values:
            # Order in the user selection order when self.values is set.
            clauses = ' '.join(['WHEN id=%s THEN %s' % (pk, i) for i, pk in
                    enumerate(self.values)])
            ordering = 'CASE %s END' % clauses
            return choices.extra(
                select={'ordering': ordering}, order_by=('ordering',))

        if self.order_by is None:
            return choices

        if isinstance(self.order_by, six.string_types):
            return choices.order_by(self.order_by)

        return choices.order_by(*self.order_by)

To fix the issue, change the above statement in:

            clauses = ' '.join(['WHEN "%s"=%s THEN %s' % (self.model._meta.pk.name, pk, i) for i, pk in
                    enumerate(self.values)])
            ordering = 'CASE %s END' % clauses

Now use the model primary_key name, which is "id" by default

@rhunwicks
Copy link
Contributor

Even with the fix suggested above the SQL query will fail if the primary key is not an integer, because the value isn't quoted.

@rhunwicks
Copy link
Contributor

The change to order_values() also seems to overwrite any default ordering on the queryset. Is there a situation where self.values will be set, but the conditions on the queryset will allow it to include other values from the database? If so, then the values will be ordered first, but everything else will be random because you are ignoring self.order_by.

@kouete
Copy link
Author

kouete commented May 12, 2015

Basically in the fix, the only change is replacing "id" with the actual primary_key name of the model. which should fix the reported bug. Any other issues such as reported by rhunwicks is from my opinion not related to this reported bug.

@jpic
Copy link
Member

jpic commented May 17, 2015

Closing in favor of PR #417, please join the discussion there.

It tests non-id non-numeric id.

@rhunwicks
The purpose of this feature is to keep the order the user selected it in.

@jpic
Copy link
Member

jpic commented May 26, 2015

Could you try with 2.2.0rc1 which was released yesterday ?

Thanks.

@davmlaw
Copy link

davmlaw commented May 28, 2015

Hi, I had the non-id primary key issue with 2.1.1 (was using CharField(16)) and it is fixed after "sudo pip install -U --pre django-autocomplete-light" upgrading to 2.2.0rc2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants