AttributeError: 'str' object has no attribute 'fields' Using Django non rel on GAE
Asked Answered
G

2

6

I'm doing an app with Django non rel on Google App Engine, and im using Bootstrap...to use Bootstrap on Django Forms i installed django_forms_bootstrap (https://github.com/pinax/django-forms-bootstrap)

The thing is...when i deploy on GAE and trying to create a new user (registration) i get the Server Error (500), but the new user is created...the log of GAE show this:

> Exception in request: Traceback (most recent call last):   File
> "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/core/handlers/base.py",
> line 113, in get_response
>     response = callback(request, *callback_args, **callback_kwargs)   File
> "/base/data/home/apps/s~softsystemanager/1.378394621720949564/myapp/modulos/presentacion/views.py",
> line 32, in signup_view
>     return render_to_response('presentacion/login.html', context_instance=RequestContext(request))   File
> "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/shortcuts/__init__.py",
> line 29, in render_to_response
>     return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/loader.py",
> line 177, in render_to_string
>     return t.render(context_instance)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 140, in render
>     return self._render(context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 134, in _render
>     return self.nodelist.render(context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 830, in render
>     bit = self.render_node(node, context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 844, in render_node
>     return node.render(context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/loader_tags.py",
> line 124, in render
>     return compiled_parent._render(context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 134, in _render
>     return self.nodelist.render(context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 830, in render
>     bit = self.render_node(node, context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 844, in render_node
>     return node.render(context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/loader_tags.py",
> line 63, in render
>     result = block.nodelist.render(context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 830, in render
>     bit = self.render_node(node, context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 844, in render_node
>     return node.render(context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 881, in render
>     output = self.filter_expression.resolve(context)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django/template/base.py",
> line 606, in resolve
>     new_obj = func(obj, *arg_vals)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django_forms_bootstrap/templatetags/bootstrap_tags.py",
> line 20, in as_bootstrap
>     form = _preprocess_fields(form)   File "/base/data/home/apps/s~softsystemanager/1.378394621720949564/django_forms_bootstrap/templatetags/bootstrap_tags.py",
> **line 10, in _preprocess_fields
>     for field in form.fields: AttributeError: 'str' object has no attribute 'fields'**

Then i go to the file bootstrap_tags.py and i see no error

> def _preprocess_fields(form):
>     for field in form.fields:
>         name = form.fields[field].widget.__class__.__name__.lower()
>         if not name.startswith("radio") and not name.startswith("checkbox"):
>             form.fields[field].widget.attrs["class"] = " form-control"
>     return form
> 
> 
> @register.filter def as_bootstrap(form):
>     template = get_template("bootstrap/form.html")
>     form = _preprocess_fields(form)
> 
>     c = Context({
>         "form": form,
>     })
>     return template.render(c)

In the HTML file of my app i got this

<div class="col-md-4 ">
            <form action="." method="POST">
                {%csrf_token%}
                {{ form|as_bootstrap}}
                <button type="submit" class="btn btn-default">Sign UP</button>
            </form>     
        </div>
    </div>

and i don't know if this is useful but here is the form

class RegisterForm(forms.Form):
    username = forms.CharField(label="Nombre de Usuario",widget=forms.TextInput())
    name = forms.CharField(label="Nombre",widget=forms.TextInput())
    last_name = forms.CharField(label="Apellido",widget=forms.TextInput())
    email = forms.EmailField(label="Correo Electronico", widget=forms.TextInput())
    password_one = forms.CharField(label="Password", widget=forms.PasswordInput(render_value=False))
    password_two = forms.CharField(label="Confirmar Password", widget=forms.PasswordInput(render_value=False))

In fact, the error is with this particular form, because i have another one, the login form, and it works perfectly and im using the same procedure to use the django_forms_bootstrap

The source code of my singup_view is:

def signup_view(request):
    form = RegisterForm()
    if request.method == "POST":
        form = RegisterForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            name = form.cleaned_data['name']
            last_name = form.cleaned_data['last_name']
            email = form.cleaned_data['email']
            password_one = form.cleaned_data['password_one']
            password_two = form.cleaned_data['password_two']
            newUser = User.objects.create_user(username=username, first_name=name, last_name=last_name, email=email, password=password_one)
            newUser.save()
            return render_to_response('presentacion/login.html', context_instance=RequestContext(request))
        else:
            ctx = {'form':form}
            return render_to_response('presentacion/sign_up.html',ctx, context_instance=RequestContext(request))
    ctx = {'form':form}
    return render_to_response('presentacion/sign_up.html',ctx, context_instance=RequestContext(request))

Please Help!!!

Guddle answered 2/9, 2014 at 4:14 Comment(4)
Please post the code for your signup_view method.Remember
The problem is with your login.html file, not your sign_up.html file. In your login.html file, do you have a {{ form|as_bootstrap }}?Remember
Yes, what should i do??Guddle
@BurhanKhalid i think i solved it i changed: return render_to_response('presentacion/login.html', context_instance=RequestContext(request)) for: return HttpResponseRedirect('/login') it works!!!Guddle
R
5

In your login.html template, you have {{ form|as_bootstrap }}, but in your code for signing up, you are rendering the template for login, but you are not passing in the form value:

return render_to_response('presentacion/login.html',
                          context_instance=RequestContext(request))

There is no context here.

You need to fix this by redirecting the user to the login view, instead of rendering the login template from your sign up view.

In addition, you should use the render shortcut which will automatically send RequestContext.

Your are also not checking for duplicate users.

To fix these issues in your code:

from django.shortcuts import render, redirect

def signup_view(request):
    form = RegisterForm(request.POST or None)
    ctx = {'form': form}
    if request.method == "POST":
        if form.is_valid():
            username = form.cleaned_data['username']
            name = form.cleaned_data['name']
            last_name = form.cleaned_data['last_name']
            email = form.cleaned_data['email']
            password_one = form.cleaned_data['password_one']
            password_two = form.cleaned_data['password_two']
            if not User.objects.filter(email=email).exists():
                 newUser = User.objects.create_user(username=username,
                                                    first_name=name,
                                                    last_name=last_name,
                                                    email=email,
                                                    password=password_one)
                 newUser.save()
            else:
                 # Do something, because a user
                 # with this email already exists
                 pass
            return redirect('login')

    return render(request, 'presentacion/sign_up.html', ctx)
Remember answered 2/9, 2014 at 4:43 Comment(0)
F
7

If you ended up here like me with a similar error, in Django 2.2.4, using as_table|crispy doesn't seem to work at all. The solution was to remove as_table:

Before

<div class="col-md-4 ">
   <form action="." method="POST">
         {%csrf_token%}
         {{ form.as_table|as_bootstrap}}
         <button type="submit" class="btn btn-default">Sign UP</button>
    </form>     
</div>

After

<div class="col-md-4 ">
   <form action="." method="POST">
         {%csrf_token%}
         {{ form|as_bootstrap}}
         <button type="submit" class="btn btn-default">Sign UP</button>
    </form>     
</div>

This may not answer the OP's question, but if you ended up here like me, hope this helps you.

Fulguration answered 18/8, 2019 at 19:46 Comment(1)
My issue was with {form.as_p|crispy}} - removing as_p similarly got rid of the errorAssam
R
5

In your login.html template, you have {{ form|as_bootstrap }}, but in your code for signing up, you are rendering the template for login, but you are not passing in the form value:

return render_to_response('presentacion/login.html',
                          context_instance=RequestContext(request))

There is no context here.

You need to fix this by redirecting the user to the login view, instead of rendering the login template from your sign up view.

In addition, you should use the render shortcut which will automatically send RequestContext.

Your are also not checking for duplicate users.

To fix these issues in your code:

from django.shortcuts import render, redirect

def signup_view(request):
    form = RegisterForm(request.POST or None)
    ctx = {'form': form}
    if request.method == "POST":
        if form.is_valid():
            username = form.cleaned_data['username']
            name = form.cleaned_data['name']
            last_name = form.cleaned_data['last_name']
            email = form.cleaned_data['email']
            password_one = form.cleaned_data['password_one']
            password_two = form.cleaned_data['password_two']
            if not User.objects.filter(email=email).exists():
                 newUser = User.objects.create_user(username=username,
                                                    first_name=name,
                                                    last_name=last_name,
                                                    email=email,
                                                    password=password_one)
                 newUser.save()
            else:
                 # Do something, because a user
                 # with this email already exists
                 pass
            return redirect('login')

    return render(request, 'presentacion/sign_up.html', ctx)
Remember answered 2/9, 2014 at 4:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.