0
votes

I have a Profile model which has a Foreign key to the user model. I've created an 'edit profile' view which allows users to update profile information. One of those fields being an image field (Hosted with cloudinary). Since changing this field to a Cloudinary field i seem to be having issues with newly created profile objects when the profile doesn't have an image uploaded. However, if the user HAS a profile image i can load the 'edit_profile' view no problem.

I've narrowed it down to be the image field as when i remove the field it works no problems. Despite the traceback not being very helpful.

Here is my edit_profile view.

@login_required
def edit_profile(request):
    if request.method == 'POST':
        user_form = UserForm(request.POST, request.FILES, instance=request.user)
        profile_form = ProfileForm(request.POST,request.FILES, instance=request.user.profile)
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            messages.success(request, "Successfully Updated")
            return redirect('profile:edit_profile')
        else:
            messages.success(request, "Please correct the below info")
    else:
        user_form = UserForm(instance=request.user)
        profile_form = ProfileForm(instance=request.user.profile)
    return render(request, 'profile/edit.html', {
        'user_form': user_form,
        'profile_form': profile_form
})

I have two forms, one for the user model which allows the user to update first name, last name and email. Then the profile form, which allows to update the additional fields.

I think i need to add some logic to check whether the image field is set to Null!? I don't have null=True set on the set on the field so i'm a little confused.

Here is my Profile Model:

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

    image = CloudinaryField('image', default="thumbnail_mqe6ne")

    height = models.DecimalField(help_text="CM", max_digits=8, decimal_places=2, validators=[
        MinValueValidator(20),
        MaxValueValidator(600),
        ])

    gender_option = (
        ('Male', 'Male'),
        ('Female', 'Female'),
    )

    profile_status = (
        ('Public', 'Public'),
        ('Private', 'Private'),
    )

    birth_date = models.DateField(blank=True, default=datetime.date.today, verbose_name="Date of Birth")


    gender = models.CharField(choices=gender_option, blank=True, max_length=10)
    bio = models.TextField(max_length=300, blank=True)
    location = models.CharField(max_length=30, blank=True)


    status = models.CharField(default="Public", max_length=10, choices=profile_status)

    def __unicode__(self):
        return unicode(self.user.username)

    def get_absolute_url(self):
        return reverse("profile:profile_home", kwargs={"id": self.id})

// Traceback

Environment:


Request Method: GET
Request URL: http://localhost:8000/profile/edit/

Django Version: 1.10.4
Python Version: 2.7.6
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.sites',
 'stats',
 'home',
 'sorl.thumbnail',
 'storages',
 'cloudinary',
 'debug_toolbar',
 'django_cleanup',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'allauth.socialaccount.providers.facebook']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'whitenoise.middleware.WhiteNoiseMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware']


Template error:
In template /vagrant/bodymakeover/templates/profile/edit.html, error at line 27
   object of type 'NoneType' has no len()   17 : {% comment %}{{ profile.first_name }}<br>
   18 : {{ profile.last_name }}<br>
   19 : {{ profile.bio }}<br>
   20 : {{ profile.location }}<br>
   21 : {{ profile.birthdate }}<br>{% endcomment %}
   22 : 
   23 : 
   24 : <form method="post" enctype='multipart/form-data'>
   25 :   {% csrf_token %}
   26 :   {{ user_form.as_p }}
   27 :    {{ profile_form.as_p }} 
   28 :   <button class="btn btn-primary" type="submit">Save changes</button>
   29 : </form>
   30 : 
   31 : 
   32 : </div>
   33 : 
   34 : 
   35 : {% endblock %}

Traceback:

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
  39.             response = get_response(request)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  23.                 return view_func(request, *args, **kwargs)

File "/vagrant/bodymakeover/home/views.py" in edit_profile
  54.         'profile_form': profile_form

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/shortcuts.py" in render
  30.     content = loader.render_to_string(template_name, context, request, using=using)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/loader.py" in render_to_string
  68.     return template.render(context, request)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/backends/django.py" in render
  66.             return self.template.render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render
  208.                     return self._render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/test/utils.py" in instrumented_test_render
  94.     return self.nodelist.render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  174.         return compiled_parent._render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/test/utils.py" in instrumented_test_render
  94.     return self.nodelist.render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  70.                 result = block.nodelist.render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  70.                 result = block.nodelist.render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in render
  1044.             output = self.filter_expression.resolve(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in resolve
  711.                 obj = self.var.resolve(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in resolve
  852.             value = self._resolve_lookup(context)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/template/base.py" in _resolve_lookup
  915.                             current = current()

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/forms/forms.py" in as_p
  289.             errors_on_separate_row=True)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/forms/forms.py" in _html_output
  226.                     'field': six.text_type(bf),

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/utils/html.py" in <lambda>
  382.         klass.__unicode__ = lambda self: mark_safe(klass_unicode(self))

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/forms/boundfield.py" in __str__
  43.         return self.as_widget()

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/forms/boundfield.py" in as_widget
  89.         attrs = self.build_widget_attrs(attrs, widget)

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/forms/boundfield.py" in build_widget_attrs
  238.         if widget.use_required_attribute(self.initial) and self.field.required and self.form.use_required_attribute:

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/django/forms/widgets.py" in use_required_attribute
  441.         return super(ClearableFileInput, self).use_required_attribute(initial) and not initial

File "/vagrant/bodymakeover/venv/local/lib/python2.7/site-packages/cloudinary/__init__.py" in __len__
  129.         return len(self.public_id)

Exception Type: TypeError at /profile/edit/
Exception Value: object of type 'NoneType' has no len()

Any help would be much appreciated as i'm banging my head against a wall. Hopefully something obvious :)

1
can you give more detailed traceback?Rohanil
Hey Rohanil, i've added the last part of the traceback where it seems to tripping. Is that enough? Thanks for the reply.JDavies
No, that's not enough. Why can't you paste the whole thing?Daniel Roseman
Done! Sorry i didn't realise there was a copy and paste option that removed all of the cr*p, heh.JDavies
Where is self.public_id defined?ChrisFreeman

1 Answers

0
votes

The error occurs because Python is testing for Truth using len() which is defined as len(self.public_id). When public_id is None the error is raised.

Our SDK team is pushing soon a more comprehensive solution that would support None values in the CloudinaryField.

As a temporary workaround, you can check community suggested solutions for it on our GH (this one, for example).

Also, you can subscribe for the issue - here to get a notification once a fix is released.