Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

get_absolute_update_url weird bug #172

Closed
sandroden opened this Issue · 15 comments

5 participants

@sandroden

Hi,

when using choice_label in (Multi)ChoiceWidget yout get a custom formatting of the select item but you also get that same html for the widget. I'd like to have different representation. Is there a simple/recommanded way to achieve this? i.e.: a choice_label for the select item and one for the widget item?

@jpic
Owner

Could you try a template override ?

@luzfcb

I would create a new issue, but this looks a bit like the problem I'm having

Simple autocomplete_light/widget.html template override, do not work with https://github.com/maraujop/django-crispy-forms

my widget.html override:

https://gist.github.com/luzfcb/6801013

Error: https://gist.github.com/luzfcb/6801101

Only works if I copy the entire contents of widget.html, and make the changes that I would like

official docs not explain how to perform the customization of css.

This is the best way to do this?
Suggestions??

sorry, I don't speak English

@sandroden

I think I don't follow you here. I'd like to have coloured items in the autocomplete, but have clickable ursl when they are choosen (i.e. when they are displayed after being selected). If I change the choice_label method both representation change. Which is the template used to render the selected item?

My understanding is that choice_label is used by choice_html that is used by autocomplete_html and that's just for the autocomplete as you define it in the autocomplete.js, but I need to change the way the widget represents it and I can't get where it is defined.

@sandroden

I made some (forward?) steps.

Now my Autocomplete class has an attribute widget_html that points to a template that override widget.html. I thought I needed to override block 'deck', but no modification of this block seem to influence the representation of selected values in the widget. What should I do?

Any help is grately appreciated
Thanks in advance
sandro
*:-)

@jpic
Owner

@sandroden

You probably don't need such a broad answer, but given the lack of details in your question I cannot give you the detailed answer that you need. Anyway, I hope this helps.

You say that you would like coloured items in the autocomplete: did you try to use AutocompleteTemplate ie. in AutocompleteModelTemplate ? See tutorial on AutocompleteTemplate for basic help. Then you could set choice_template and use a template for every choice item. See full documentation and see code of AutocompleteTemplate.choice_html() for details.

You say say have "clicable urls when they are choosen", I don't understand. Could you paste your code and the generated code ? It is really hard to understand what is going on so it is hard to help you.

You say that choice_label() changes only the label. You can see in AutocompleteBase.choice_html() uses choice_label(), choice_html_format attribute and choice_value(), unlike AutocompleteTemplate.choice_html() which attempts to use a template before falling back to that logic. Maybe reading the Autocomplete API docs would help.

You say that you can't find what code generates the choice representation. Well choice representation really happens at two points:

The widget template displays selected choices with this {{ choice|autocomplete_light_choice_html:autocomplete }}. This calls the autocomplete_light_choice_html filter which calls .choice_html() as you can see autocomplete_light/templatetags/autocomplete_light_tags.py.

As you can see, every choice representation is generated by choice_html(). So, this is where you should define the HTML representation of the choices if you're using AutocompleteBase or AutocompleteTemplate. If you're using your own class depending only on AutocompleteInterface then you should implement autocomplete_html().

@jpic
Owner

@luzfcb

Your problem is simple: django template engine hit a maximum recursion because of line 1. Line 1 contains {% extends 'autocomplete_light/widget.html' %}. Your template name is autocomplete_light/widget.html. So, your template is trying to extend itself. This is like if you had this python code:

class Foo(Foo):
    pass

A template must not extend itself. So your template must have another name that autocomplete_light/widget.html if you want it to extend autocomplete_light/widget.html. There are several ways to override the template name used to render the widget, as you can see in WidgetBase.render():

  • set Autocomplete.widget_template to whatever, like your_autocomplete.html, it has priority because django-autocomplete-light is Autocomplete-centric,
  • set Autocomplete.widget_template_name, you can use a shortname like red and it will use autocomplete_light/red/widget.html,
  • or directly use autocomplete_light/AutocompleteName/widget.html

So, you have several options depending on your plans with this template override.

Also, note that you have removed the class autocomplete which might be necessary for the JS to work.

For CSS I don't know how I could help you really, could you override autocomplete_light/style.css ?

@sandroden

Thanks for the prompt and very accurate reply.
My Autocomplete now looks like this::

 class ClienteAutocomplete(autocomplete_light.AutocompleteModelTemplate):
    search_fields = ['code', 'name', 'vat_number', 'organization_groups__name']
    choices = Azienda.objects.all()
    autocomplete_template = 'azienda/autocomplete_azienda.html'
    model = Azienda
    choice_template = None

    def choice_label(self, choice):
        return u'<a href="%s">%s</a>' % (reverse('admin:azienda_azienda_change', args=(choice.id,)), choice)

and a simple template:

{% for choice in choices %}
   <span class="div" data-value="{{ choice.pk }}">{{ choice }}</span>
{% endfor %}

This produces a nice url when widget renders but not when I select a choice from the autocomplete, it's just reported 'as is' in the widget (you said "naively fetched by javascript") so that it's not formatted as it would if choice_label would be used.

What I would like is to produce a different representation when transfered from the autocomplete to the widget.

sandro
*:-)

@jpic
Owner

Thanks for the details, I see.

What happens here is that you have overridden autocomplete_template, and your version of autocomplete_template does not use choice_html() nor choice_label(). So, when JS naively clones the choice, this ends up in your deck <span class="div" data-value="123">YourChoice</span>. But the other, pre-selected choices, are generated by choice_html() (which uses choice_label()).

Your problem is that you broke a DRY system with the template. The DRY system was that choice_html() is used in the widget rendering (for pre-selected choices) and used in the autocomplete rendering (for choices who can be selected and copied into the deck).

You have two solutions instead of overriding autocomplete_template:

  • you could override choice_template,
  • you could use AutocompleteModelBase again and override choice_html_format

But your override of autocomplete_template is not good. If you really want to override autocomplete_template, you should use autocomplete_light_choice_html template filter to let choice_html() do the rendering and keep it all DRY.

I just noted that AutocompleteModelTemplate uses a nice choice template by default, so you could use that for inspiration.

Anyway, your solutions are:

  • set autocomplete_template to None for the moment and override choice_template,
  • or use AutocompleteModelBase and override choice_html_format (see AutocompleteBase.choice_html() for details).
@jpic
Owner

Hi, any feedback ?

@francisalfanta

Newbie here Sir.

This issue is what I'm also looking for that I ask in http://stackoverflow.com/questions/19947690/how-to-add-a-link-to-django-autocomplete-light-selected-items.

I managed to follow jpic instruction above and used this code with sandroden idea how to add url after item is selected.

#autocomplete_light_registry.py

import autocomplete_light
from ccad.models import Carrier
from django.core.urlresolvers import reverse

class CarrierAutocomplete(autocomplete_light.AutocompleteModelBase):
search_fields = ['companyname']
autocomplete_js_attributes = {'placeholder': 'Name or Initial', }

def choice_label(self, choice):
    return u'<a href="%s">%s</a>' % (reverse('admin:ccad_carrier_change', args=(choice.id,)), choice)

autocomplete_light.register(Carrier, CarrierAutocomplete)

The problem now is once I select an item with this url attached the click trigger me to redirect to the specified url.
The purpose for such links is to help user edit the record if needed not to automatically redirect them.

Is there a work around for this purpose?

Thanks,
fma

@juanjosepimentel

Add this to your url:

?_popup=1" target="_blank" onclick="return showAddAnotherPopup(this);

A post a complete solution in StackOverflow http://stackoverflow.com/questions/19947690/how-to-add-a-link-to-django-autocomplete-light-selected-items/19978641#19978641

@francisalfanta

When I follow this You have to add this '?_popup=1" target="_blank" onclick="return showAddAnotherPopup(this);' to your url. the code works when added like this.

def choice_label(self, choice):
return u'<a href="%s"?_popup=1" target="_blank" onclick="return showAddAnotherPopup(this);">%s</a>' % (reverse('admin:ccad_carrier_change', args=(choice.id,)), choice,)

But when I tried your subclass i received this error

'Exception Type: AttributeError
Exception Value: 'Carrier' object has no attribute 'get_absolute_update_url'

@juanjosepimentel

You should implement this method in your model:

def get_absolute_update_url(self):
    url = reverse('admin:ccad_carrier_change', args=(self.id,))
    url = '%s?_popup=1" target="_blank" onclick="return showAddAnotherPopup(this);' % url
    return url
@jpic
Owner

That's a funny hack, and fixing it in django-autocomplete-light will break backward compatibility on this. I'll fix it in v2 then.

@jpic jpic closed this
@jpic jpic reopened this
@jpic jpic added the bug label
@jpic jpic changed the title from choice_label to get_absolute_update_url weird bug
@jpic
Owner

Couldn't reproduce, you're probably doing something wrong.

Would love to have a demo: http://django-autocomplete-light.readthedocs.org/en/stable-2.x.x/faq.html#how-to-ask-for-help

@jpic jpic closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.