jQueryUI autocomplete with url as source (am using Django) - django

I am using Django web-framework for database, page generation etc.
jQueryUI / javascript side of the code
I want to use jQueryUI's autocomplete widget, as my data set will contain about 1,000 entries I wanted to query the database. On the link above it claims you can simply provide a url that returns JSON data:
Autocomplete can be customized to work
with various data sources, by just
specifying the source option. A data
source can be:
* an Array with local data
* a String, specifying a URL
* a Callback
I have taken the default example from the website, which works on my system.
However if I change the following:
$( "#tags" ).autocomplete({
source: availableTags,
});
to
$( "#tags" ).autocomplete({
source: "/search/", // url that provides JSON data
});
the autocomplete functionality doesn't work at all.
I've tried making the url actually return an error (to see if it uses it) and putting in the full url http://localhost:8000/search/, nothing works.
Django part of the code
In url.py
...
(r'^search/$', 'search'),
...
In views.py
from django.http import HttpRequest, HttpResponse
from django.utils import simplejson
...
def search(request):
HttpResponse(simplejson.dumps(["hello", "world"]))
# Will implement proper suggestions when it works.
There must be something wrong with my code and I would greatly appreciate any help you can offer :)
EDIT SOLUTION:
Thanks to #Thierry realised it didn't have a return statement before, have added that so I now looks like so:
def search(request):
output = ["hello", "world"]
return HttpResponse(simplejson.dumps(output))
And it actually works!
(It always seems to be the really small bugs that waste the most of of my time, grrr)

I return my ajax response like the following:
def search(request):
output = ["hello", "world"]
return HttpResponse(output, mimetype="application/javascript")
If you access the url http://localhost:8000/search/, you should see the output. Once you see the output, the autocomplete should work.

There are some changes in json serialization API in later versions
For django 1.6 use
import json
from django.http import HttpResponse
....
return HttpResponse(json.dumps(my_data_dictionary))
For django 1.7+ do it like here

Related

How do I authorize a specific url to load the content of my site deployed on heroku from an iframe? [duplicate]

I'm trying to enable django to allow one specific view to be embedded on external sites, preferabilly without sites restrictions.
In my views.py file, I have added the following code, where the view futurebig is the one I want to enable to be embedded:
from django.views.decorators.clickjacking import xframe_options_sameorigin
...
#xframe_options_sameorigin
def futurebig(request):
...
return render_to_response('templates/iframe/future_clock_big.html', context_dict, context)
which doesn't help as I understand because it only enables embedding in the same server.
How can I set the headers for that specific view to enable it to be embedded in any website?
For the record, I'm just a frontend developer, the backend developer who developed the site is no longer working with me and refused to document his code, so, If anyone could help me and explain carefully where and what modifications I should do, I'll apreciatte it very much.
Thanks.
As far as I know, the Django version is 1.6
You are going in the right direction, but exact decorator which you will need to achieve this is 'xframe_options_exempt'.
from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_exempt
#xframe_options_exempt
def ok_to_load_in_a_frame(request):
return HttpResponse("This page is safe to load in a frame on any site.")
PS: DJango 1.6 is no longer supported. It is good time to get an upgrade.
Apparently you can set a rule in your settings telling the following:
X_FRAME_OPTIONS = 'ALLOW-FROM https://example.com/'
Also nowadays you should consider moving to CSP
Content-Security-Policy: frame-ancestors 'self' example.com *.example.net ;
See https://stackoverflow.com/a/25617678/186202
If you want to allow the frame in specific view you can add Content-Security-Policy to your view response, so your code will be something like this
def MyView(request):
....
....
response = render(request,'MyViewHtml.html' ,{...})
response ['Content-Security-Policy'] = "frame-ancestors 'self' https://example.com"

Why does adding Regexp arguments in Django urls.py completely break HTTP response mechanism?

I have changed the way URLS are handled in my Django app.
Previously I was posting my model IDs as named variables in the URLs. But now, I am instead embedding my model IDs in the URL itself which looks more elegant to me. However, doing so is seemingly giving me a problem TypeError: <myObject: Object #4> is not JSON serializable
My Django Application used to be structured like this:
Old urls.py:
url(r'^doSomethingStep1/?$', views.doSomethingStep1View, name='doSomethingStep1'),
url(r'^doSomethingStep2/?$', views.doSomethingStep2View, name='doSomethingStep2'),
Old views.py doSomethingStep1() function:
#login_required
def doSomethingStep1View(request):
myObjectObj = Prediction.objects.get(pk=int(request.GET["p"]))
...
return HttpResponseRedirect(reverse("doSomethingStep2"))
This used to work fine. But now I have changed it to the code shown below:
New urls.py:
url(r'^doSomethingStep1/(?P<myObjectID>\d+)/(?P<myObjectSlug>[a-z0-9\-_]+)/?$', views.doSomethingStep1View, name='doSomethingStep1'),
url(r'^doSomethingStep2/(?P<myObjectID>\d+)/(?P<myObjectSlug>[a-z0-9\-_]+)/?$', views.doSomethingStep2View, name='doSomethingStep2')
New views.py doSomethingStep1() function:
#login_required
def doSomethingStep1View(request, myObjectID, myObjectSlug=None):
...
return HttpResponseRedirect(reverse(
"doSomethingStep2",
kwargs={
'myObjectID': myObjectObj.id,
'myObjectSlug': myObjectObj.slug,
}
)
)
Running this view now (by visiting /doSomethingStep1/4/myobject-4-slug) yields the following error in the Browser:
TypeError at /doSomethingStep1/4/myobject-4-slug <MyObject: myObject 4 Slug> is not JSON serializable
It's really confounding. Why is this happening and how to fix it? I have printed out the value of reverse and there is no problem with it. I have no clue why and where it is trying to serialize MyObject4. As far as I know, it shouldn't be trying to serialize this object.
Are you using Django 1.6? The default session serializer was switched to JSON, which can cause problems if you put something in the session that is not serializable. You can switch back to the old pickle serializer using the SESSION_SERIALIZER setting. See the 1.6 release notes for details:
https://docs.djangoproject.com/en/dev/releases/1.6/#default-session-serialization-switched-to-json
You didn't include all of your view code, but I'm betting you are putting a MyObject instance in the user's session, which wouldn't get serialized and throw the error until the redirect happens.

Django running wrong view method

I have to view files stored in mysite folder. one is named as views.py and other is named as request_view.py. In urls.py, I have used 'answer' method for views.py and 'display_meta' method for request_view.py.
(django version: 1.5 and python version: 2.7.3)
this is the url pattern:
url(r'^twitter/$', answer), url(r'request/$', display_meta)
when I call http:/127.0.0.1:8000/request/, then also first view(i.e. /twitter/) is called!
any help?
one more thing. In my view.py, I have some unbounded code (i.e. the code which is neither present in a method or class). can this be the cause of the problem?
l = StdOutListener()
auth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
stream = Stream(auth, l)
keyword = input('enter the keyword you want to search for?')
stream.filter(track = [keyword])
apart from this code, evry code is either in the class or method.
One thing that I noticed is that first the code of the view.py runs, then display_meta runs.
Thanks in advance.
SOLVED
The problem was with the import function that I was using. since my code was unbounded in one of the views, the import function always import that regardless of the url that I choose.
Suggestion
Always use the nomenclature mentioned in the this example. In many books it has been suggested that we should import the views, but it might cause an error if you have unbounded code like I had.
I don't know exactly why /twitter/ view is called, but I can see two things to change:
You should use a string as the second parameter for url(), as you can see in this example [1]. You can use 'myapp.views.my_method' nomenclature.
You forgot to start the request URL with ^ that indicates the start of the URL.
About the unbounded code, I don't know if that could be causing the problem. But I can't see why are you putting that code unbounded. I am not sure when that code would be executed, I guess the first time you call a view in that file and Django loads the file (I'm guessing, I don't know exactly), but I don't think that would be a good way to do that. Think when do you want to execute that code, put it in a method, and call it.
[1] https://docs.djangoproject.com/en/1.5/topics/http/urls/#example
HI hemant i am wondering why you have written request_view.py.
Please see the django docs.
what you can do is .
Create two function in your views.py like
def answer(request):
do some stuffs.
render_to_response(template.html)
and on the same page write another
def display_meta(request):
# do your studd
render_to_response(some.html)
YOU NEED NOT TO CREATE TWO SEPERATE VIEWS.PY
I dont know what this code does
l = StdOutListener()
auth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
stream = Stream(auth, l)
keyword = input('enter the keyword you want to search for?')
stream.filter(track = [keyword])
But if you want to use StdOutListener inside your function you can call in your view
like
def display_meta(request):
stobject = StdOutListener() # use parameters if you have here
# do your studd
render_to_response(some.html)
Organizing views into a python package could solve this problem. So if you have a structure like this...
# views.py
def SomeView(request):
return HttpResponse('SomeView')
# another_view.py
def AnotherView(request):
return HttpResponse('AnotherView')
Your can reorganize these separate view files into a views package. That is...
# views
# __init__.py
from views import SomeView
from another_view import AnotherView
# views.py
def SomeView(request):
return HttpResponse('SomeView')
# another_view.py
def AnotherView(request):
return HttpResponse('AnotherView')
And now, everything can be called in a django-standard way:
url(r'^url-to-some-view/$', 'views.SomeView'),
url(r'^url-to-another-view/$', 'views.AnotherView'),
UPDATED:
To make a 'python package'...
Create a views directory at the same level as the view.py file [mkdir views]
Create a __init.py__ file inside the views directory # this is what makes a directory a 'python package'
Move views.py into the views directory.
Move your request_view.py into the views directory.
Edit the __init__.py file with the necessary import statements. In this case:
from views import answer
from request_view import display_meta
What this does is replace a file with a directory. By importing everything into the __init__.py file, this directory looks like a large file to your code, rather than another module.

Django: simulate HTTP requests in shell

I just learnt that with Rails is possible to simulate HTTP requests in the console with few lines of code.
Check out: http://37signals.com/svn/posts/3176-three-quick-rails-console-tips (section "Dive into your app").
Is there a similar way to do that with Django? Would be handy.
You can use RequestFactory, which allows
inserting a user into the request
inserting an uploaded file into the request
sending specific parameters to the view
and does not require the additional dependency of using requests.
Note that you have to specify both the URL and the view class, so it takes an extra line of code than using requests.
from django.test import RequestFactory
request_factory = RequestFactory()
my_url = '/my_full/url/here' # Replace with your URL -- or use reverse
my_request = request_factory.get(my_url)
response = MyClasBasedView.as_view()(my_request) # Replace with your view
response.render()
print(response)
To set the user of the request, do something like my_request.user = User.objects.get(id=123) before getting the response.
To send parameters to a class-based view, do something like response = MyClasBasedView.as_view()(my_request, parameter_1, parameter_2)
Extended Example
Here's an example of using RequestFactory with these things in combination
HTTP POST (to url url, functional view view, and a data dictionary post_data)
uploading a single file (path file_path, name file_name, and form field value file_key)
assigning a user to the request (user)
passing on kwargs dictionary from the url (url_kwargs)
SimpleUploadedFile helps format the file in a way that is valid for forms.
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import RequestFactory
request = RequestFactory().post(url, post_data)
with open(file_path, 'rb') as file_ptr:
request.FILES[file_key] = SimpleUploadedFile(file_name, file_ptr.read())
file_ptr.seek(0) # resets the file pointer after the read
if user:
request.user = user
response = view(request, **url_kwargs)
Using RequestFactory from a Python shell
RequestFactory names your server "testserver" by default, which can cause a problem if you're not using it inside test code. You'll see an error like:
DisallowedHost: Invalid HTTP_HOST header: 'testserver'. You may need to add 'testserver' to ALLOWED_HOSTS.
This workaround from #boatcoder's comment shows how to override the default server name to "localhost":
request_factory = RequestFactory(**{"SERVER_NAME": "localhost", "wsgi.url_scheme":"https"}).
How I simulate requests from the python command line is:
Use the excellent requests library
Use the django reverse function
A simple way of simulating requests is:
>>> from django.urls import reverse
>>> import requests
>>> r = requests.get(reverse('app.views.your_view'))
>>> r.text
(prints output)
>>> r.status_code
200
Update: be sure to launch the django shell (via manage.py shell), not a classic python shell.
Update 2: For Django <1.10, change the first line to
from django.core.urlresolvers import reverse
(See tldr; down)
Its an old question,
but just adding an answer, in case someone maybe interested.
Though this might not be the best(or lets say Django) way of doing things.
but you can try doing this way.
Inside your django shell
>>> import requests
>>> r = requests.get('your_full_url_here')
Explanation:
I omitted the reverse(),
explanation being, since reverse() more or less,
finds the url associated to a views.py function,
you may omit the reverse() if you wish to, and put the whole url instead.
For example, if you have a friends app in your django project,
and you want to see the list_all() (in views.py) function in the friends app,
then you may do this.
TLDR;
>>> import requests
>>> url = 'http://localhost:8000/friends/list_all'
>>> r = requests.get(url)

What is the best (=easiest) way to populate django-textfield with values from other models in the admin-interface?

I am working on a small newsletter-app for a custom-Blog-Django-project (just for me). One main feature of the project is the defined set of Article-Types. All Article-types are children of the abstract base class "Article". Two examples of article-types are "event-article" and "video-article". In the newsletter-app I have a "content"-Field (=email-message). Now I want to choose several articles (of any type) to be included in the newsletter. It may be easier if I just create a function that searches all articles which are not featured in a newsletter yet. Then I would collect all needed information, combine them into a text and set the function as default for the field. But I rather choose the articles by myself. I thought about a m2m-field, but how can I choose some articles (inline in the edit-form of the object) and have the content-field filled with the needed information (like absolute_url or headline) immediately? Thanks for your help in advance.
Only option is AJAX. Setup a view that returns an article as JSON. Make the AJAX call to that view when user selects an article. Then, parse the returned JSON with and populate the text field with JavaScript.
views.py
from django.core import serializers
from django.http import HttpResponse
def json_get_article(request, article_id):
article = get_object_or_404(MyModel, id=article_id)
data = serializers.serialize("json", article)
return HttpResponse(data, mimetype='application/json')
script.js (using jQuery for simplicity)
$.getJSON('/my/ajax/url/', function (data, textStatus, jqXHR) {
$('#id_my_text_field').val(data[0]['field_containing_text'])
});
You'll obviously have to tweak that somewhat, but that's the basic process.