Custom ModelForms with django-ajax-selects
I have a Model for URLs that contains:
[toggle code]
-
class Destination(models.Model):
- path = models.CharField(max_length=140)
- host = models.ForeignKey(Host, default=1)
- query = models.CharField(max_length=240, blank=True)
- secure = models.BooleanField(default=False)
-
class Meta:
- ordering = ['host__name', 'path']
- unique_together = (('path', 'host', 'secure', 'query'),)
-
def save(self, *args, **kwargs):
-
if self.path.startswith('/'):
- self.path = self.path.lstrip('/')
- return super(Destination, self).save(*args, **kwargs)
-
if self.path.startswith('/'):
The problem is when the stripping results in an existing URL. Model saves, whether in models.Model or admin.ModelAdmin, happen after validation, so instead of a nice “this URL already exists” I get a server error. Django thinks this isn’t a duplicate because it already passed its validation, and then I went ahead and changed it.
This is easily fixed in the Admin model, by using a custom ModelForm:
[toggle code]
-
class DestinationForm(forms.ModelForm):
-
class Meta:
- model = Destination
-
def clean_path(self):
- path = self.cleaned_data['path']
-
if path.startswith('/'):
- path = path.lstrip('/')
- return path
-
class Meta:
-
class DestinationAdmin(admin.ModelAdmin):
- form = DestinationForm
- …
Now, adding a new Destination results in the correct “Destination with this Path, Host, Secure and Query already exists.”
But it still fails in the “+add” pop-up form. I’m using django-ajax-selects, and the error is in the views.py for django-ajax-selects:
[toggle code]
- Traceback (most recent call last):
-
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py", line 111, in get_response
- response = callback(request, *callback_args, **callback_kwargs)
-
File "/Library/Python/2.7/site-packages/django_ajax_selects-1.2.5-py2.7.egg/ajax_select/views.py", line 65, in add_popup
- if 'opener.dismissAddAnotherPopup' in response.content:
-
File "/Library/Python/2.7/site-packages/django/template/response.py", line 123, in _get_content
- raise ContentNotRenderedError('The response content must be '
- ContentNotRenderedError: The response content must be rendered before it can be accessed.
A search on the ContentNotRenderedError shows a similar error on StackOverflow, with a solution that appears to work.
In add_popup in /Library/Python/2.7/site-packages/django_ajax_selects-1.2.5-py2.7.egg/ajax_select/views.py (on Red Hat Linux, ajax_select is in /usr/lib/python2.6/site-packages/django_ajax_selects-1.2.5-py2.6.egg) change it to be:
[toggle code]
-
def add_popup(request,app_label,model):
- …
- response = admin.add_view(request,request.path)
-
if request.method == 'POST':
-
if (hasattr(response,'is_rendered') and response.is_rendered or not hasattr(response,'is_rendered')) and response.content:
-
if 'opener.dismissAddAnotherPopup' in response.content:
- return HttpResponse( response.content.replace('dismissAddAnotherPopup','didAddPopup' ) )
-
if 'opener.dismissAddAnotherPopup' in response.content:
-
if (hasattr(response,'is_rendered') and response.is_rendered or not hasattr(response,'is_rendered')) and response.content:
- return response
I wouldn’t be surprised if there’s a better check to be made than response.is_rendered; probably something like admin.form.is_valid(), but that requires the ModelForm as a parameter, and I can’t see where to get it.
The developers are aware of the issue and this particular solution.
- ContentNotRenderedError after a django upgrade
- “Hacktastic solution: You can guard against this by checking if the response has an is_rendered attribute and if so, that it is true before changing the STATS string.”
- django-ajax-selects
- “Enables editing of ForeignKey, ManyToMany and CharField using jQuery UI Autocomplete.”
- Error on Pop-Up at django-ajax-selects
- “I have a ajax-select field, which has the option to add a value at it’s right. The pop-up with the form opens, and I try to save it.”