FileField not processed on form POST - python

When trying to upload a file using a FileField, the form doesn't post the file data to the server.
It works perfectly if you use a text field, but for some reason it doesn't recognize the file, as it doesn't
show up on request.FILES, or request.POSTS.
MEDIA_ROOT and MEDIA_URL configuration:
MEDIA_ROOT = '/home/grove/pootleImages/'
MEDIA_URL = '/pootleImages/'
get_unit_context decorator in decorators.py:
def get_unit_context(permission_codes):
def wrap_f(f):
#wraps(f)
def decorated_f(request, uid, *args, **kwargs):
unit = get_object_or_404(
Unit.objects.select_related("store__translation_project",
"store__parent"),
id=uid,
)
_common_context(request, unit.store.translation_project,
permission_codes)
request.unit = unit
request.store = unit.store
request.directory = unit.store.parent
return f(request, unit, *args, **kwargs)
return decorated_f
return wrap_f
My forms.py method:
def unit_image_form_factory(language):
image_attrs = {
'lang': language.code,
'dir': language.direction,
'class': 'images expanding focusthis',
'rows': 2,
'tabindex': 15,
}
class UnitImageForm(forms.ModelForm):
class Meta:
fields = ('image',)
model = Unit
# It works if using a CharField!
#image = forms.CharField(required=True,
# label=_("Image"),
# widget=forms.Textarea(
# attrs=image_attrs))
image= forms.FileField(required=True, label=_('Image'),
widget=forms.FileInput(
attrs=image_attrs))
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(UnitImageForm, self).__init__(*args, **kwargs)
def save(self):
super(UnitImageForm, self).save()
return UnitImageForm
My models.py snippet:
class Unit(models.Model, base.TranslationUnit):
# ...
# ...
# It works if using a TextField!
#image = models.TextField(null=True, blank=True)
image = models.FileField(upload_to=".", blank=True, null=True)
# ...
# ...
My urls.py snippet:
url(r'^xhr/units/(?P<uid>[0-9]+)/image/?$',
'image',
name='pootle-xhr-units-image'),
My views.py method:
#require_POST
#ajax_required
#get_unit_context('translate')
def image(request, unit):
"""Stores a new image for the given ``unit``.
:return: If the form validates, the cleaned image is returned.
An error message is returned otherwise.
"""
# Update current unit instance's attributes
unit.uploaded_by = request.profile
unit.uploaded_on = timezone.now()
language = request.translation_project.language
form = unit_image_form_factory(language)(request.POST, request.FILES, instance=unit,
request=request)
if form.is_valid():
form.save()
context = {
'unit': unit,
'language': language,
}
t = loader.get_template('unit/image.html')
c = RequestContext(request, context)
json = {'image': t.render(c)}
rcode = 200
else:
json = {'msg': _("Image submission failed.")}
rcode = 400
response = simplejson.dumps(json)
return HttpResponse(response, status=rcode, mimetype="application/json")
My HTML template for the image upload:
<div id="upload-image">
<form enctype="multipart/form-data" method="post" action="{% url 'pootle-xhr-units-image' unit.id %}" id="image-form">
{% csrf_token %}
<input type="file" name="image" id="id_image" />
<p><input type="submit" value="{% trans 'Upload' %}" /></p>
</form>
</div>
When the form is instantiated, request.POST does not return the file browsed by the user, neither request.FILES.
form.errors just returns "This field is required"
The form object returns the following:
<tr><th><label for="id_image">Image:</label></th><td><ul class="errorlist"><li>This field is required.</li>
</ul><input lang="pl" rows="2" name="image" id="id_image" type="file" class="images expanding focusthis" dir="ltr" tabindex="15" /></td></tr>
And when the user clicks the submit button, the following POST error occurs:
"POST /xhr/units/74923/image HTTP/1.1" 400 35
I could bypass it by including required=False to the image property, but the file is not posted anyway.
More output debug information:
POST when fileField is required=True:
Status Code: 400 BAD REQUEST
Form Data:
csrfmiddlewaretoken: yoTqPAAjy74GH
form.errors:
"msg": "imageThis field is required."}
If change required=True to required=False:
Status Code: 200 OK
Form Data:
csrfmiddlewaretoken: yoTqPAAjy74GH
But the imagefield still doesn't show up in the form data.
Thank you,
Alex
I added a gist hub containing all files related to this problem, to ease visualization:
https://gist.github.com/alex-silva/40313734b9f1cd37f204

It looks like you've forgotten to add the {% csrf_token %} in your form. Add that between the tag.
OR...
You can add the csrf_exempt decorator to your processing view:
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
#csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
More info: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/

Finally managed to get it to work in some way. The form wasn't working at all when using it in the main page, so I created a link to a blank page containing just the upload image form. When separate from the main page, the upload works fine. Then I just redirect to the main page after uploading. Why the form doesn't work in the main page, that's a mystery.

Related

Django redirect URL into another URL with form

I wouldlike to redirect in another URL when I submit my form.
After submit, I wouldike to have another page with something like "Hello (SummonerName) and Welcome" with URL like this : interface/main/SummonerName=(SummonerName)
Here my code :
forms.py
from django import forms
class SummonerForm(forms.Form):
summoner_name = form.CharField(label='SummonerName:', max_length=100)
views.py
from django.http import HttpresponseRedirect
from django.shortcuts import render
from .forms import NameForm
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/interface/name.html')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'interface/main.html', {'form': form})
and my main.html
<form action="/SummonerName={{ current_name }}" method="post">
<label for="summoner_name">SummonerName: </label>
<input id="summoner_name" type="text" name="summoner_name" value="{{ current_name }}">
<input type="submit" value="Rechercher">
</form>
EDIT :
urls.py
from django.urls import path
from . import views
urlpatterns = {
path('main', view.get_summoner_name)
}
Thank you !
That is what return HttpResponseRedirect does your views.py. You only need to pass your desired url as the first parameter instead of `'/interface/name.html'.
See:
https://docs.djangoproject.com/en/2.2/ref/request-response/#httpresponse-subclasses
For passing on the name, you have many options depending on what you want to do with the inputted data.
A simple solution:
Your example is rather simple and so if you only want to redirect to some url and show the name the user has inputed the easiest would be to pass the name (and any other parameters) via the url as a querystring:
import urllib.parse
# ... omitted code
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# get parameters from the form
params = {
"summoner_name" : form.validated_data["summoner_name"],
# multiple parameters can be passed in this dict e.g.
# "some_other param" : param_value
}
# encode the dictionary into a querystring
q_string = urllib.parse.urlencode(params)
# construct the new URL:
redirect_url = "/interface/success/?summoner_name={}".format(q_string)
return HttpResponseRedirect(redirect_url)
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'interface/main.html', {'form': form})
You can then access these parameters in your views/templates by the request object.
Then, in your urls.py you should match this url pattern by adding to your patterns something like:
path('interface/success/', views.success_view),
and you should of course define that view:
# views.py
def success_view(request):
return render(request, "success.html")
Finally you should add a template success.html. There you could do <h1> Hello {{ request.GET.summoner_name }}! </h1>
A more common usecase
The method above only shows data the user has inputted which is usually not very usefull... More commonly in a form we ask data that we need to save to the db, and thats why I proposed a ModelForm in my comment. It is off the scope of this answer to explain exactly how that would work but in a nutshell: you should define a model in your models.py (i.e. a db table) where you can store data (summoner_name would be a field in such a model).
class SimpleModel(models.Model):
summoner_name=models.CharField(max_length=256)
# other fields you may need
Then you can use a django's generic class based views e.g.
class SimpleFormView(CreateView):
model = SimpleModel
success_url = "interface/success"
urls.py will also need some editing and your tempaltes should comply with django naming conentions too. Do read this if you want to go down that way:
https://docs.djangoproject.com/en/2.2/topics/class-based-views/generic-editing/#form-handling-with-class-based-views

Calling a Django-Rest API from a Django Form

I built a Django-Rest API with an APIView that uploads a file to a folder of a web server.
This API is working with Postman as shown in the pictures below:
Now, I am working on calling this API from the below HTML form:
Issue I am facing: the file sent via the form returns the following error:
"file": [
"No file was submitted."
]
Probably something related with the binding of the file as the file is uploaded in the form but not sent to the API.
Below the code of my application:
index.html
<form action="/file/upload/" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input id="audio_file" type="file"/>
<input type="submit" value="Upload File" name="submit"/>
</form>
views.py
class IndexView(TemplateView):
template_name = "index.html"
log = logging.getLogger(__name__)
log.debug("Debug testing")
def post(self, request): # TODO: fix, empty file error returned after calling post method
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
# https://docs.djangoproject.com/en/2.2/ref/forms/api/#binding-uploaded-files
form = FileForm(request.POST, request.FILES)
# check whether it's valid:
if form.is_valid():
instance = form.save(commit=False)
instance.save()
# redirect to the same URL:
return HttpResponseRedirect('/App/index/')
# if a GET (or any other method) we'll create a blank form
else:
form = FileForm()
return render(request, 'index.html', {'form': form})
class FileView(views.APIView):
parser_classes = (MultiPartParser, FormParser)
def post(self, request):
'''This method is used to Make POST requests to save a file in the media folder'''
file_serializer = FileSerializer(data=request.data)
if file_serializer.is_valid():
file_serializer.save()
return Response(file_serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
models.py
from django.db import models
class FileModel(models.Model):
file = models.FileField()
timestamp = models.DateTimeField(auto_now_add=True)
forms.py
from django.forms import ModelForm
from App.models import FileModel
class FileForm(ModelForm):
# Creating a form that maps to the model: https://docs.djangoproject.com/en/2.2/topics/forms/modelforms/
class Meta:
model = FileModel
fields = ['file']
Below the documentation I have already consulted without success:
https://docs.djangoproject.com/en/2.2/topics/http/file-uploads/
https://docs.djangoproject.com/en/2.2/topics/forms/
These are the stackoverflow questions I already read without finding a solution to the issue:
Django Contact Form Attachment showing 'This field is required.' What am I doing Wrong?
Django calling REST API from models or views?
Django HTML Form Send Attachment Emails
Post to django rest framework
Complete code repository: https://github.com/marcogdepinto/Django-Emotion-Classification-Ravdess-API .
EDIT: I changed the if statement inside IndexView.post as follows
if form.is_valid():
instance = form.save(commit=False)
instance.save()
Now the request is OK but the file passed is empty
HTTP 201 Created
Allow: POST, DELETE, OPTIONS
Content-Type: application/json
Vary: Accept
{
"file": null,
"timestamp": "2019-08-16T06:15:58.882905Z"
}

How to include a search form in an existing page in django?

I have a function called search in views.py which I use to process search parameters and display results on a different page. My search form is on the home page template so that I can search from there and be redirected to the page specified by my search function. Currently my views.py looks like this:
from django.shortcuts import render
from django.views.generic import ListView
from django.core.paginator import Paginator
from core.models import Movie
from core.documents import MovieDocument
class MovieList(ListView):
model = Movie
template_name='movie_list.html'
paginate_by = 10
queryset = Movie.objects.all()
def search(request):
q = request.GET.get('q')
if q:
movies = MovieDocument.search().query("match", title=q)
else:
movies = ''
return render(request, 'search.html', {'movies': movies})
The home page is being served by the MovieList class and I have the following html snippet for the search field in the home page movie_list.html:
<form method="get" action="{{ views.search}}">
<input id="q" name="q" type="text" placeholder="Search...">
</form>
The url path for MovieList looks like this:
path('movies',views.MovieList.as_view(),name='MovieList')
When,for example I type 'terminator' in the search box, the url in the browser changes to http://127.0.0.1:8000/movies?q=terminator but the search function is not called and nothing happens. How can I get this working properly, preferably without having to define a new url to capture the search query string but by specifying the search function in the form's action attribute, unless that's not possible? Having the search box on its own page and creating its own url path actually works but that's not what I need.
You can't add views.search directly in form action.
Update your view like this:
class MovieList(ListView):
model = Movie
template_name='movie_list.html'
paginate_by = 10
queryset = Movie.objects.all()
show_search = False
def get(self, request, *args, **kwargs):
if self.show_search == True:
template_name='search.html'
else:
template_name='movie_list.html'
context = self.get_context_data()
return self.render_to_response(context)
def get_queryset(self):
try:
q = self.kwargs['q']
except:
q = ''
if (q != ''):
object_list = self.model.search().query("match", title=q)
self.show_search = True
else:
self.show_search = False
object_list = self.model.objects.all()
return object_list
Ok so I finally figured this out, quite simple. All I had to do was add a path for redirecting the search to a new page:
path('search',views.search,name='search')
Then I updated the form tag:
<form method="get" action="{% url 'search' %}">
It doesn't matter what the names are in the path arguments as long as you are pointing to the correct view function and the form's action is matched to the correct url name.

How to validate Google reCAPTCHA v2 in django

I have been trying to use the Google reCAPTCHA on a website that I've been making. The captcha loads on the webpage but I've been unable to validate it using several methods. I've tried the recaptcha validation using the method given at
How to use Python plugin reCaptcha client for validation? but I think it's outdated as it no longer works and it is referring to challenges whereas the one I'm trying to use is the new 'checkbox' reCAPTCHA v2 by Google or maybe I need to make changes in my settings after installing recaptcha-client or django-recaptcha.
Please help!
Here is a simple example to verify Google reCAPTCHA v2 within Django view using requests library (http://docs.python-requests.org/en/latest/):
import requests
from django.conf import settings
def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip
def grecaptcha_verify(request):
if request.method == 'POST':
response = {}
data = request.POST
captcha_rs = data.get('g-recaptcha-response')
url = "https://www.google.com/recaptcha/api/siteverify"
params = {
'secret': settings.RECAPTCHA_SECRET_KEY,
'response': captcha_rs,
'remoteip': get_client_ip(request)
}
verify_rs = requests.get(url, params=params, verify=True)
verify_rs = verify_rs.json()
response["status"] = verify_rs.get("success", False)
response['message'] = verify_rs.get('error-codes', None) or "Unspecified error."
return HttpResponse(response)
There is a third-party Django app to implement the new reCAPTCHA v2 here:
https://github.com/ImaginaryLandscape/django-nocaptcha-recaptcha
After installing it, add the following lines to the following files:
# settings.py
NORECAPTCHA_SITE_KEY = <the Google provided site_key>
NORECAPTCHA_SECRET_KEY = <the Google provided secret_key>
INSTALLED_APPS = (
....
'nocaptcha_recaptcha'
)
#forms.py
from nocaptcha_recaptcha.fields import NoReCaptchaField
class YourForm(forms.Form):
.....
captcha = NoReCaptchaField()
# In your template, add the following script tag:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
Google has changed the API around, we need to use a POST request now. Here a re-usable solution in case you need to do the validation in more than one django view:
utils.py
# django imports
from django.conf import settings
from django.views.generic.base import View
from django.http import HttpResponseForbidden
# 3rd-party imports
import requests
from ipware import get_client_ip
def is_recaptcha_valid(request):
"""
Verify if the response for the Google recaptcha is valid.
"""
return requests.post(
settings.GOOGLE_VERIFY_RECAPTCHA_URL,
data={
'secret': settings.RECAPTCHA_SECRET_KEY,
'response': request.POST.get('g-recaptcha-response'),
'remoteip': get_client_ip(request)
},
verify=True
).json().get("success", False)
def human_required(view_func):
"""
This decorator is aimed to verify Google recaptcha in the backend side.
"""
def wrapped(request, *args, **kwargs):
if is_recaptcha_valid(request):
return view_func(request, *args, **kwargs)
else:
return HttpResponseForbidden()
return wrapped
then:
views.py
from utils import human_required
class MyView(View):
#human_required
def post(request, *args, **args):
pass
Note we are using django-ipware in this solution to get the ip address, but this is up to you. Also, don't forget to add GOOGLE_VERIFY_RECAPTCHA_URL and RECAPTCHA_SECRET_KEY to the django settings file!
views.py
def login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(request, username=username, password=password)
if user is not None:
if user.is_active:
auth.login(request, user)
''' Begin reCAPTCHA validation '''
recaptcha_response = request.POST.get('g-recaptcha-response')
url = 'https://www.google.com/recaptcha/api/siteverify'
values = {
'secret' : settings.GOOGLE_RECAPTCHA_SECRET_KEY,
'response' : recaptcha_response
}
data = urllib.parse.urlencode(values).encode("utf-8")
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
result = json.load(response)
''' End reCAPTCHA validation '''
if result['success']:
return redirect('index')
else:
messages.error(request, 'Invalid reCAPTCHA. Please try again.')
return redirect('login')
else:
messages.info(request, 'Wrong Credentials!!! enter right username or password')
return redirect('login')
else:
return render(request, 'login.html')
login.html
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
<div class="body bg-gray">
<div class="form-group">
<input type="text" name="username" class="form-control" placeholder="Username"/>
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" placeholder="Password"/>
</div>
<div class="form-group">
<input type="checkbox" name="remember_me"/> Remember me
</div>
</div>
<div class="footer">
<button type="submit" class="btn bg-olive btn-block">Sign me in</button>
<p>I forgot my password</p>
Register a new membership
</div>
<br><br>
<script src='https://www.google.com/recaptcha/api.js'></script>
<div class="g-recaptcha" data-sitekey="(enter your key here that is private or authenticated on google recapthcha)"></div>
</form>
settings.py
INSTALLED_APPS = [
....
....
'captcha'
]
GOOGLE_RECAPTCHA_SECRET_KEY ='6LdXBLAUAMlGYqqyDESeHKI7-'
RECAPTCHA_PUBLIC_KEY = '6LdXBLAUAAAAAP3oI1VPJgA-VHXoj'
RECAPTCHA_PRIVATE_KEY = '6LdXBLAUAAAAAGYqqyDESeHKI7-'
''' you have to register your domain to get the access of these keys. or you can
register your localhost also to test this after uploading on the server you can
register with real domain and change the keys.
don't forget to like if you find it helpful.'''
'https://www.google.com/recaptcha/intro/v3.html' -> 'admin console' where you can
register your domain or localhost and get your key.
Expanding on the answer given by #trinchet, here is a simple modification of the FormView Django class to automatically handle Google's reCAPTCHA v2.
class RecaptchaFormView(FormView):
""" This class handles Google's reCAPTCHA v2. """
recaptcha_ok = None
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['grecaptcha_site_key'] = settings.RECAPTCHA_SITE_KEY
return context
def get_form(self):
form = super().get_form()
if self.recaptcha_ok == False:
form.add_error(None, "Invalid reCAPTCHA, please try again.")
return form
def post(self, request, *args, **kwargs):
self.recaptcha_ok = is_recaptcha_valid(request)
return super().post(self, request, *args, **kwargs)
Don't forget to include the is_recaptcha_valid function provided by #trinchet (see his answer), reCAPTCHA keys in settings.py and the reCAPTCHA code in the template (use {{ grecaptcha_site_key }} as the site key).
This is how I handle the proposed question:
views.py
from django.contrib.auth.views import LoginView, LogoutView
from django.conf import settings
from authentication.forms import MyAuthenticationForm
class MyLoginView(LoginView):
template_name = 'authentication/login.html'
form_class = MyAuthenticationForm
def get_client_ip(self):
x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = self.request.META.get('REMOTE_ADDR')
return ip
def get_form_kwargs(self):
kwargs = super(MyLoginView, self).get_form_kwargs()
if self.request.method in 'POST':
kwargs['g-recaptcha-response'] = self.request.POST.get('g-recaptcha-response')
kwargs['remote_ip'] = self.get_client_ip()
return kwargs
def get_context_data(self, **kwargs):
context = super(MyLoginView, self).get_context_data(**kwargs)
# To use in the template
context['recaptcha_challenge_secret'] = settings.G_RECAPTCHA_CHALLENGE_SECRET
return context
forms.py
import requests
from django.contrib.auth.forms import AuthenticationForm
from django.conf import settings
from django.forms import ValidationError
from django.utils.translation import ugettext_lazy as _
class MyAuthenticationForm(AuthenticationForm):
def __init__(self, *args, **kwargs):
self.g_recaptcha_response = kwargs.pop('g-recaptcha-response', None)
self.remote_ip = kwargs.pop('remote_ip', None)
super(MyAuthenticationForm, self).__init__(*args, **kwargs)
def clean(self):
cleaned_data = super(MyAuthenticationForm, self).clean()
self.verify_captcha()
return cleaned_data
def verify_captcha(self):
if self.g_recaptcha_response:
data = {
'secret': settings.G_RECAPTCHA_VERIFY_SECRET,
'response': self.g_recaptcha_response,
'remoteip': self.remote_ip
}
response = requests.post(settings.G_RECAPTCHA_VERIFICATION_URL, data=data)
result = response.json()
if result['success']:
return
raise ValidationError(
_('Invalid reCAPTCHA challenge.'),
code='invalid_recaptcha_challenge'
)

How to get data from form using POST in django (Horizon Dashboard)?

i'm new in development using django, and i'm trying modify an Openstack Horizon Dashboard aplication (based on django aplication).
I implements one function and now, i'm trying to do a form, but i'm having some problems with the request.
In my code i'm using the method POST
Firstly, i'm want to show in the same view what is on the form, and i'm doing like this.
from django import http
from django.utils.translation import ugettext_lazy as _
from django.views.generic import TemplateView
from django import forms
class TesteForm(forms.Form):
name = forms.CharField()
class IndexView(TemplateView):
template_name = 'visualizations/validar/index.html'
def get_context_data(request):
if request.POST:
form = TesteForm(request.POST)
if form.is_valid():
instance = form.save()
else :
form = TesteForm()
return {'form':form}
class IndexView2(TemplateView):
template_name = 'visualizations/validar/index.html'
def get_context_data(request):
text = None
if request.POST:
form = TesteForm(request.POST)
if form.is_valid():
text = form.cleaned_data['name']
else:
form = TesteForm()
return {'text':text,'form':form}
My urls.py file is like this
from django.conf.urls.defaults import patterns, url
from .views import IndexView
from .views import IndexView2
urlpatterns = patterns('',
url(r'^$',IndexView.as_view(), name='index'),
url(r'teste/',IndexView2.as_view()),
)
and my template is like this
{% block main %}
<form action="teste/" method="POST">{% csrf_token %}{{ form.as_p }}
<input type="submit" name="OK"/>
</form>
<p>{{ texto }}</p>
{% endblock %}
I search about this on django's docs, but the django's examples aren't clear and the django's aplication just use methods, the Horizon Dashboard use class (how is in my code above)
When i execute this, an error message appears.
this message says:
AttributeError at /visualizations/validar/
'IndexView' object has no attribute 'POST'
Request Method: GET
Request URL: http://127.0.0.1:8000/visualizations/validar/
Django Version: 1.4.5
Exception Type: AttributeError
Exception Value:'IndexView' object has no attribute 'POST'
Exception Location:
/home/labsc/Documentos/horizon/openstack_dashboard/dashboards/visualizations/validar/views.py in get_context_data, line 14
Python Executable: /home/labsc/Documentos/horizon/.venv/bin/python
Python Version: 2.7.3
i search about this error, but not found nothing.
if someone can help me, i'm thankful
Your signature is wrong:
def get_context_data(request)
should be
def get_context_data(self, **kwargs):
request = self.request
Check the for get_context_data and the word on dynamic filtering
Since your first argument is the self object, which in this case is request, you are getting the error.
If you read more carefully the error message, it appears that the URL was retrieved using a GET method. Not POST:
AttributeError at /visualizations/validar/
'IndexView' object has no attribute 'POST'
Request Method: GET
Request URL: http://127.0.0.1:8000/visualizations/validar/
See the following link for an in deep explanation of GET vs POST
TemplateView by default will return a method not allowed 405 when you try to post to it. You can write your own post method for it:
class IndexView(TemplateView):
template_name = 'visualizations/validar/index.html'
def get_context_data(request):
#define your context and return
context = super(ContactView, self).get_context_data(**kwargs)
#context["testing_out"] = "this is a new context var"
return context
def post(self, request, *args, **kwargs):
context = self.get_context_data()
if context["form"].is_valid:
print 'yes done'
#save your model
#redirect
return super(TemplateView, self).render_to_response(context)
If you're going to post from a form, use FormView instead, and you can still define context as you wish by overwriting get_context_data:
from django.views.generic import TemplateView, FormView
from forms import ContactUsEmailForm
class ContactView(FormView):
template_name = 'contact_us/contact_us.html'
form_class = ContactUsEmailForm
success_url = '.'
def get_context_data(self, **kwargs):
context = super(ContactView, self).get_context_data(**kwargs)
#context["testing_out"] = "this is a new context var"
return context
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
#form.send_email()
#print "form is valid"
return super(ContactView, self).form_valid(form)
contact_us = ContactView.as_view()
And urls.py:
from django.conf.urls import patterns, url
urlpatterns = patterns('contact_us.views',
url(r'^$', 'contact_us', name='contact_us'),
)
Hope this helps :) More on FormsView.

Categories

Resources