Correct Django URL config to read JSON - django

I'm trying to learn a bit of REST. I have added several views to an existing Django app to try and do various things using REST and JSON. I am able to get my app to send out requested data through several views, but I can't seem to get it to accept JSON as part of the URL.
I have created a view that looks like this:
def restCreateEvent(request, key, jsonString):
errors = checkKey(key)
if errors == None:
eventJson = json.loads(jsonString)
eventInfo = eventJson['event']
title = eventInfo['title']
description = eventInfo['description']
locationInfo = eventInfo['location']
place = locationInfo['place_name']
street = locationInfo['street_address']
city = locationInfo['city']
state = locationInfo['state']
zip = locationInfo['zip']
event = models.Event()
event.title = title
event.description = description
event.street_address = street
event.place_name = place
event.city = city
event.state = state
event.zip = zip
event.save()
else:
return errors
However, I can;t seem to get the URL correct, here is what I have now:
(r'^events/rest/create/(?P<key>\d+)/(?P<jsonString>.+)', 'events.views.restCreateEvent')
When I attempt to access the following url, Django debug complains that none of my urls match it.
http://127.0.0.1:8000/events/rest/33456/create/{"title":"test","description":"this is a test","location":{"place_name":"somewhere","street_address":"123 main","city":"pittsburgh","state":"pa","zip":"11111"}}
Right now the view is never called, so obviously my url is wrong. So, is my approach totally wrong here? If not how do I fix the url?

Why would you do this? The way to send JSON, like any payload, is to put it in the POST data, not the URL.

Related

Django function for views takes too long

I'm currently using a Docker & Django setup. I have to fill a database with data from API requests. I was hoping to do this everytime you went on a certain page (pretty easy: just have your views.py call the function that fills the database and voila).
But the problem is, the function takes a long time, several minutes from within django (and about half the time with Spyder).
So I usually just get a TimeOut and the page never loads (I admit I have a lot of API requests being made).
I've read some stuff on using Celery but am not quite sure how it's supposed to work.
Anyone know how I could get around this to be able to load the database?
Edit: some code
Views.py
def index(request):
fill_db()
context = {}
context['segment'] = 'index'
html_template = loader.get_template( 'index.html' )
return HttpResponse(html_template.render(context, request))
fill_db function
def fill_db():
fill_agencies()
fill_companies()
fill_contracts()
fill_orders()
fill_projects()
fill_resources()
Example of a fill function:
r = pip._vendor.requests.get(BASE_URL+EXTENSION,auth=(USER,PASS))
data0 = json.loads(r.text)
conn = sqlite3.connect('/app/database.sqlite3')
c = conn.cursor()
for client in data0['data']:
BoondID = client['id']
name = client['attributes']['name']
expertiseArea = client['attributes']['expertiseArea']
town = client['attributes']['town']
country = client['attributes']['country']
mainManager = client['relationships']['mainManager']['data']['id']
values = (BoondID, name, expertiseArea, town, country, mainManager)
c.execute("INSERT OR REPLACE INTO COMPANIES (BoondID,name,expertiseArea,town,country,mainManager) VALUES (?,?,?,?,?,?);", values)
conn.commit()
conn.close()
Solved.
I used python's threading library.
I defined
agencies_thread = threading.Thread(target=fill_agencies, name="Database Updater")
and called agencies_thread.start() inside my views function.
This works fine.

Spotipy on Django authorization without copy-paste to console

I have a Django site in which I want to use spotipy to look for statistics of the song like popularity and views. I have this code right now:
import spotipy
import spotipy.util as util #luxury
import json
import webbrowser
username = 'dgrqnco2rx8hdu58kv9if9eho'
scope = 'user-read-private user-read-playback-state user-modify-playback-state'
token = util.prompt_for_user_token(username, scope, client_id='08bb526962574a46b359bffc56048147',
client_secret='bf6d4184c8ae40aca207714e02153bad', redirect_uri='http://google.com/')
sp_obj = spotipy.Spotify(auth=token)
ss = 'name of song'
if ss.__contains__('('):
q = ss[0:ss.index('(')]
elif ss.__contains__('['):
q = ss[0:ss.index('[')]
elif ss.__contains__('['):
q = ss[0:ss.index('{')]
else:
q = ss
query = sp_obj.search(q, 1, 0, 'track')
#<<<<<<<<<<SONG>>>>>>>>>>
#FIND THE SONG URI
song_uri = query['tracks']['items'][0]['uri']
track = sp_obj.track(song_uri)
track_data = sp_obj.audio_features(song_uri)
song_popularity = track['popularity']
song_danceability = track_data[0]['danceability']
song_energy = track_data[0]['energy']
song_loudness = track_data[0]['loudness']
song_tempo = track_data[0]['tempo']
However spotipy redirects me to a page for authorization and I need to paste the url in the console. The regular user however does not have access to this console. So how can I do the authorization in an alternative way or even bypass it?
I was thinking about getting a spotify account in which every user will be getting logged in so that the user won't have to do the authorization and won't have to have a spotify account. Is this possible? If not what else can I try?
You can't use util.prompt_for_user_token because it's just a helper for local usage only.
You need to arrange your code as API endpoints so that multiple users can sign in. Here is a full working example that would allow multiple users to sign in https://github.com/plamere/spotipy/blob/master/examples/app.py.
It uses Flask but you can easily adapt it to Django.

How to perform the delete method in drf django

How to perform the delete request in Django drf? How will I pass the params for the request?
Kindly help with the solution. I am very new in this drf-django-python programming.
class DeleteView(APIView):
def delete(self, request,format=None):
id = request.POST['book_id']
email = request.POST['email']
book = models.Book.objects.filter(book_id=id)
book_uploader = serializers.BookSerializer(book[0]).data['uploader']['email']
logged_in = request.user
print(log)
if book_uploader == logged_in :
books = models.BookUserRelationship.objects.filter(book= id, user__email=email)
books.delete()
return Response("Successfully removed", status=status.HTTP_204_NO_CONTENT)
else :
return Response("Not able to remove")
In comments you noticed that parameters will be embedded in url but you are trying to get values from POST dict.
If your url is something like
/books/id/email/
You should use request.kwargs dict like request.kwargs.get('email')
But if your url is like
/books/id/?email=someemail#google.com
id would be in request.kwargs but email in request.query_params
Notice that every url variable is in the request.query_params dict.
IMPORTANT
If you have ID url param without named group, viewset would not be able to get this from request.kwargs by name

Django backend receives one less param than sent by frontend

I have a small web app with AngularJS front-end and Django ReST in the back. There's a strange hitch going on when I make POST request to the web service: the browser console clearly shows 3 parameters being sent, but the backend logging reports only 2 params received. The result is that the server throws a code 500 error due to a bad database lookup.
Here's the code:
Client
var b = newQuesForm.username.value;
$http.post('/myapp/questions/new', {username:b,title:q.title,description:q.description}).
success(function(data, status, headers, config) {
$http.get('/myapp/questions').success(function(data){
$scope.questions = data;
q = null;
$scope.newQuesForm.$setPristine();
}).error(function(data, status, headers, config) {
console.log(headers+data);
});
}).
error(function(data, status, headers, config) {
console.log(headers+data);
});
Both my manual logging and the dev console show a string like:
{"username":"admin","description":"What's your name?","title":"question 1"}
Server
class CreateQuestionSerializer(serializers.Serializer):
author = UserSerializer(required=False)
title = serializers.CharField(max_length=150)
description = serializers.CharField(max_length=350)
def create(self, data):
q= Question()
d = data
q.title = d.get('title')
q.description = d.get("description")
q.author = User.objects.get(username=d.get('username'))
q.save()
return q
Server-side logging shows the username parameter never succeeds in making the trip, and thus I end up with code 500 and error message:
User matching query does not exist. (No user with id=none)
What's causing some of the data to get lost?
So it turns out the problem was really with the serialization of fields, as #nikhiln began to point out. I followed his lead to refactor the code, moving the create() method to api.py, rather than serializers.py, and stopped relying altogether on the client-side data for the user's identity, something that was a bit silly in the first place (passing User to a hidden input in the view, and then harvesting the username from there and passing it back to the server in the AJAX params). Here's the new code, that works perfectly:
class QuestionCreate(generics.CreateAPIView):
model = Question
serializer_class = CreateQuestionSerializer
def create(self, request,*args,**kwargs):
q= Question()
d = request.data
q.title = d.get('title')
q.description = d.get("description")
q.author = request.user
q.save()
if q.pk:
return Response({'id':q.pk,'author':q.author.username}, status=status.HTTP_201_CREATED)
return Response({'error':'record not created'}, status=status.HTTP_400_BAD_REQUEST)
So here, I do it the right way: pull the User from the request param directly in the backend.

Using FullCalendar with Django Views

I'm trying to implement the FullCalendar on my website, but am a little new to this and not quite sure how to format what I want to do. I have a view which will grab all of an individual user's events. I want to take those events and populate the calendar with them. My issue is that I don't know what to return in the view or how to handle that return value in the JavaScript function. Here's what I have right now:
View:
def calEvents(request):
user = request.user.get_profile()
eventList = user.eventList
ownedList = user.ownedEvent
events = #Part I'm having trouble with
return HttpResponse(events)
The eventList and ownedEvent keep track of all of a user's events. They have names/dates associated with them. What I don't understand is the format I need to put all that information in to return in my HttpResponse.
My JavaScript function is:
$(document).ready(function() {
$('#calendar').fullCalendar({
eventSources: [
{
url: '/calEvents/',
editable: false,
}
]
});
});
I'm telling it to go to the Django view, but am lost after that. Thanks so much in advance!
I have done this by building a list of dictionaries in my Django view, setting at minimum the required fields of 'title' and the start time, then using simplejson.dumps with cls=DjangoJSONEncoder to return json.
from django.core.serializers.json import DjangoJSONEncoder
def calEvents(request):
# as above, then:
events = []
for event in eventList:
events.append({'title': event.name, 'start': event.start})
# something similar for owned events, maybe with a different className if you like
return HttpResponse(simplejson.dumps(events, cls=DjangoJSONEncoder), mimetype='application/json')
You may also with to limit the events you return based on the starting and ending times provided by the get request:
def calEvents(request):
user = request.user.get_profile()
start_timestamp = request.GET.get('start')
end_timestamp = request.GET.get('end')
start_datetime = datetime.datetime.fromtimestamp(float(start_timestamp))
end_datetime = datetime.datetime.fromtimestamp(float(end_timestamp))
eventList = user.eventList.filter(start_time__lte=end_datetime, end_time__gte=start_datetime)
I am neglecting error handling for the timestamp conversion - fullcalendar will give you appropriate values, but it would be best to allow for the possibility of bad input. And I am making assumptions about the structure of your event models.