Im doing a simple script to update a playlist but I have an error even if everything looks good: `
The script start, I URI works and give me a token, spotify open to asked me the access but after it fail :
HTTP Error for PUT to https://api.spotify.com/v1/playlists/6rkyVmrfPEeWkJm01mbhO1 with
Params: {} returned 401 due to Invalid access token
Traceback (most recent call last):
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\spotipy\client.py", line 269, in _internal_call
response.raise_for_status()
File "C:\Users\xxxx\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url:
https://api.spotify.com/v1/playlists/6rkyVmrfPEeWkJm01mbhO1
Python code:
def func():
scope = 'playlist-modify-public'
username = 'myusername'
SPOTIPY_CLIENT_ID = 'xxxxxxxxxxxx'
SPOTIPY_CLIENT_SECRET = 'xxxxxxxxx'
token = util.prompt_for_user_token(username,scope,SPOTIPY_CLIENT_ID,SPOTIPY_CLIENT_SECRET,redirect_uri='https://www.dev.com')
print(token)
sp = spotipy.Spotify(auth="token")
id = 'https://open.spotify.com/playlist/6rkyVmrfPEeWkJm01mbhO1'
playlist_name = 'it works'
playlist_description = 'updated by script'
sp.user_playlist_change_details(username, id, name=playlist_name, description=playlist_description)
func()
here another try :
I get :
py spotify_bot.py
HTTP Error for PUT to https://api.spotify.com/v1/playlists/6rkyVmrfPEeWkJm01mbhO1 with Params: {} returned 403 due to Not allowed
An exception occurred
Here the code
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import json
def func():
SCOPE = 'playlist-modify-public'
USER_ID = 'xifeat'
REDIRECT_URI = 'http://localhost:3000/callback'
CLIENT_ID = '6cff431d1dea40f4812460b4721032b0'
CLIENT_SECRET = 'fb0bcffd4b2b41ac84b9b1d7501dbb80'
PLAYLIST_ID = '6rkyVmrfPEeWkJm01mbhO1'
PLAYLIST_NAME = 'test'
DESCRIPTION = 'Updated !'
try:
auth_manager = SpotifyOAuth(
scope=SCOPE,
username=USER_ID,
redirect_uri=REDIRECT_URI,
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET)
spotify = spotipy.Spotify(auth_manager=auth_manager)
spotify.user_playlist_change_details(
user=USER_ID,
playlist_id=PLAYLIST_ID,
name=PLAYLIST_NAME,
description=DESCRIPTION)
except:
print("An exception occurred")
func()
`
Yes, it is a Scope problem.
The playlist you are trying to change, is private/not public*. That requires the playlist-modify-private scope.
* On Spotify, all playlists that are not displayed on your profile, are considered private/not public.
You needs to pass correct parameters in here
The playlist_id just id of playlist, it is not full URL.
def user_playlist_change_details(
self,
user,
playlist_id,
name=None,
public=None,
collaborative=None,
description=None,
):
Parameters:
- user - the id of the user
- playlist_id - the id of the playlist
- name - optional name of the playlist
- public - optional is the playlist public
- collaborative - optional is the playlist collaborative
- description - optional description of the playlist
This code will works
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import json
def func():
SCOPE = ['playlist-modify-private','playlist-modify-public']
USER_ID = 'your-user-id'
REDIRECT_URI = 'your-redirect-uri'
CLIENT_ID = 'your-client-id'
CLIENT_SECRET = 'your-client-secret'
PLAYLIST_ID = 'your-play-list'
PLAYLIST_NAME = 'Oh my new playlist name!'
DESCRIPTION = 'This is new description'
try:
auth_manager = SpotifyOAuth(
scope=SCOPE,
username=USER_ID,
redirect_uri=REDIRECT_URI,
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET)
spotify = spotipy.Spotify(auth_manager=auth_manager)
spotify.user_playlist_change_details(
user=USER_ID,
playlist_id=PLAYLIST_ID,
name=PLAYLIST_NAME,
description=DESCRIPTION)
except:
print("An exception occurred")
func()
Before change
After change
The scope is ['playlist-modify-private','playlist-modify-public']
Related
I am trying to connect my react frontend to my flask api backend. Note that flask-cors is already installed.
I initiated CORS as CORS(app) . the login passes but I keep getting this error when I go to project route:
Access to fetch at 'http://192.168.101.4:5000/project' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
My init.py file:
from flask import Flask, request, make_response
from .extensions import db, migrate, jwt, mail, CORS
from .models import TokenBlocklist
from .routes.base import base
from .routes.auth import auth
from .routes.core import core
from .routes.admin import admin
from .routes.user import user
from .routes.project import project
def create_app(config_file='config.py'):
app = Flask(__name__)
app.config.from_pyfile(config_file)
#jwt.token_in_blocklist_loader
def check_if_token_revoked(jtw_header, jwt_payload: dict)->bool:
jti = jwt_payload['jti']
token = db.session.query(TokenBlocklist.id).filter_by(jti=jti).scalar()
return token is not None
# initiate
db.init_app(app)
migrate.init_app(app, db)
jwt.init_app(app)
mail.init_app(app)
CORS(app)
app.register_blueprint(base)
app.register_blueprint(auth, url_prefix='/auth')
app.register_blueprint(core, url_prefix='/core')
app.register_blueprint(admin, url_prefix='/admin')
app.register_blueprint(user, url_prefix='/user')
app.register_blueprint(project, url_prefix='/project')
return app
my auth.py:
"""
Route: endpoints for authentication
"""
from flask import Blueprint, jsonify, request, current_app, url_for, make_response
import datetime
import uuid
import validators
from itsdangerous import URLSafeTimedSerializer
from flask_jwt_extended import create_access_token, create_refresh_token, get_jwt_identity, jwt_required, unset_jwt_cookies, get_jwt, set_access_cookies, set_refresh_cookies
from werkzeug.security import generate_password_hash
from flask_cors import CORS
from ..utils import send_mail
from ..extensions import db, status, jwt
from ..models import User, TokenBlocklist
auth = Blueprint('auth', __name__)
CORS(auth)
#auth.route('/confirm-email/<token>')
def confirm_email(token):
s = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
try:
email = s.loads(token, salt='email-confirm', max_age=200)
# mark user mail as confirmed
user = User.query.filter_by(email=email).first()
if not user.is_confirmed:
user.is_confirmed = True
db.session.commit()
return jsonify(msg='email confirmed'), status.ok
except:
return jsonify(msg = False), status.bad
#auth.route('/register', methods=['POST'])
def register():
"""
recieve request->username, email, password
check username & email exists or not, if not hash password and store.
send email with confirmation link
"""
data = request.get_json()
username = data['username']
email = data['email']
password = data['password']
# check existance of requirements in request json
if not username or not email or not password:
return jsonify(msg='missing json data'), status.bad
# email validations
if not validators.email(email):
return jsonify(msg='invalid email address'),
# check if username and email is taken
user = User.query.filter_by(username=username).first()
if user:
return jsonify(msg='username already taken')
user = User.query.filter_by(email=email).first()
if user:
return jsonify(msg='email already taken')
# save new user in db
new_user = User(
username = username,
email = email,
password = generate_password_hash(password, 'sha256'), # probably not a good practice to use User
public_id = uuid.uuid4()
)
try:
db.session.add(new_user)
db.session.commit()
except:
return jsonify(msg='could not save')
# create email confirmation link
token = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
token = token.dumps(email, salt='email-confirm')
link = url_for('auth.confirm_email', token=token, _external=True)
# send mail
body = f'confirmation link: {link}'
mail_sent = send_mail(recipient=email, body=body, subject='Linkage Email Confirmation')
if not mail_sent:
return jsonify(msg= 'email could not be sent')
return jsonify(msg= 'mail sent' ,email=email, token=token), 201
#auth.route('/login', methods=['POST'])
def login():
"""
recieve json data->email, password
check if email exists,
check user's hashed password and if email is confirmed.
generate refresh and access token and return
"""
data = request.get_json()
email = data['email']
password = data['password']
user = User.query.filter_by(email=email).first()
# email not found
if not user:
return make_response(
'User not found',
401,
{'WWW-Authenticate' : 'Basic realm ="could not verify"'}
)
# email found
verified = user.verify_password(password)
if verified is False:
return make_response(
'password mismatch',
401,
{'WWW-Authenticate' : 'Basic realm ="could not verify"'}
)
# authenticated, now generate tokens
user_public_id = user.public_id
refresh_token = create_refresh_token(identity=user_public_id)
access_token = create_access_token(identity=user_public_id)
# i am totally not sure about the following, but the fe dev *insists*
response = jsonify({"x-access-token": access_token})
response.set_cookie("refresh_token_cookie", refresh_token)
return response, 200
And Finally my project.py:
from datetime import datetime
from flask import Blueprint, jsonify, request, make_response
from flask_jwt_extended import get_jwt_identity, jwt_required
from ..extensions import db
from ..models import Project
project = Blueprint('project', __name__)
# this route must be deleted before production
#project.route('/', methods=['GET'])
#jwt_required()
def all_projects():
user_public_id = get_jwt_identity()
projects = Project.query.filter_by(user_public_id=user_public_id).all()
projects_data = []
for project in projects:
project_data = {}
project_data['id'] = project.id
project_data['domain'] = project.domain
project_data['name'] = project.name
project_data['user_public_id'] = project.user_public_id
project_data['wp_password'] = project.wp_password
project_data['wp_username'] = project.wp_username
project_data['date_added'] = project.date_added
projects_data.append(project_data)
return jsonify(projects = projects_data), 20
CORS related configs in my config.py file:
#CORS
CORS_ALLOW_HEADERS = ['Content-Type', 'Authorization']
CORS_SUPPORTS_CREDENTIALS = True
CORS_HEADERS = ['Content-Type', 'Authorization']
I am totally lost here. I don't know where is the redirect is happening.
Thank you for your time.
I am trying to query a model to check if an object exists or not using the following APIview function. Unfortunately i am not able to receive any response object in react native apisauce get function as shown below
apisauce function
const checkIfUserExists = (email) =>
client.get("/account/user-exists/?email=" + email);
APIView class
class UserExistsView(APIView):
"""Checks if user exists or not"""
def get(self, request, *args, **kwargs):
username = self.request.GET['email']
try:
user = models.UserProfile.objects.get(email=username)
except models.UserProfile.DoesNotExist:
return Response(data={'message': False})
else:
return Response(data={'message': True})
Results from the browser
What am i doing wrong here?
Print result on shell <Response status_code=200, "text/html; charset=utf-8">
You can do it simplier:
class UserExistsView(APIView):
"""Checks if user exists or not"""
def get(self, request, *args, **kwargs):
email = self.request.GET['email']
user_exists = models.UserProfile.objects.filter(email=email).exists()
return Response(
data={'message': user_exists}
)
If you create a QuerySet and then call .exists(), Django will call the SQL function checking only if the object is in the database, but it will not query it, which is much faster and desired in your call from JS.
Assuming you have a class base component, You could modify your function like below, track the user existence in state. I don't see any errors in your server-side code. but in your javascript code you didn't handle the promise.
checkUserExists= (email) => {
client.get("/account/user-exists/?email=" + email)
.then(response=>{
this.setState({isUserExists : response.data.messgae})
)
}
I am using flask-mail. But when i call the rest api in front end(react.js) of flask mail i am getting this error
'Blueprint' object has no attribute 'config'
Here is my code for flask mail
from flask import Flask,Blueprint
from flask_mail import Mail, Message
app = Blueprint('app', __name__)
app.register_blueprint(url_prefix='/api/v1/SalesLead')
mail=Mail(app)
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'myvar30#gmail.com'
app.config['MAIL_PASSWORD'] = '*****'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
mail = Mail(leadHistoryController)
#app.route("/")
def index():
msg = Message('Sheraspace', sender = 'myvar30#gmail.com', recipients = ['jobaer.jhs#gmail.com'])
msg.body = "Hello jh"
mail.send(msg)
return "Sent again"
if __name__ == '__main__':
app.run(debug = True)
Is there any solution for blueprint config? Or can i use the rest api in front end without using blueprint?
Must use flask.current_app instead.
from flask import current_app
def gen_file_name(filename):
"""
If file was exist already, rename it and return a new name
"""
fielname = current_app.config['UPLOAD_FOLDER']
return filename
There is similar question here
blueprint-config
I have created an endpoints api in Google Apps Engine with python. The api requires oAuth2 authentication. The method works perfectly from the api explorer, however I can't seem to figure out why I get an HttpError 403 "Client_id is not allowed" at runtime. I know that the client id is valid because I have been able to use it successfully in api explorer. I know I am exposing my client secret in this post, but I need the help. Once I get it working I will request a new secret and client id.
The code that is calling the API:
from apiclient.discovery import build
from oauth2client.appengine import OAuth2Decorator
import logging
import pprint
import webapp2
decorator = OAuth2Decorator(
client_id='968442935974-happ8rfg8eq059v1p8364bv5mj8tjd4l.apps.googleusercontent.com',
client_secret='q31TNSbsc70xfEwaTjXuVAPI',
scope='https://www.googleapis.com/auth/userinfo.email')
# For for production
api_root = 'https://jamesste-school-app.appspot.com/_ah/api'
api = 'knowledge'
version = 'v1'
discovery_url = '%s/discovery/v1/apis/%s/%s/rest' % (api_root, api, version)
class TestHandler(webapp2.RequestHandler):
#decorator.oauth_required
def get(self):
service = build(api,version,discoveryServiceUrl=discovery_url)
self.response.headers['Content-Type'] = 'application/json'
knowledge_list = service.knowledge_message().list()
knowledge_list.execute(http=decorator.http())
self.response.out.write(pprint.pformat(knowledge_list))
app = webapp2.WSGIApplication([
('/test', TestHandler),
(decorator.callback_path, decorator.callback_handler())],
debug=True)
The API code:
from google.appengine.ext import ndb
from models import Knowledge
from models import KnowledgeType
from models import Resource
from protorpc import message_types
from protorpc import messages
from protorpc import remote
from apiuser import ApiUser
import endpoints
import logging
def get_endpoints_current_user(raise_unauthorized=True):
"""Returns a current user and (optionally) causes an HTTP 401 if no user.
Args:
raise_unauthorized: Boolean; defaults to True. If True, this method
raises an exception which causes an HTTP 401 Unauthorized to be
returned with the request.
Returns:
The signed in user if there is one, else None if there is no signed in
user and raise_unauthorized is False.
"""
current_user = endpoints.get_current_user()
if raise_unauthorized and current_user is None:
raise endpoints.UnauthorizedException('Invalid token.')
return current_user
class KnowledgeMessage(messages.Message):
knowledge_key = messages.StringField(1)
knowledge = messages.StringField(2)
resource_key = messages.StringField(3)
resource_name = messages.StringField(4)
resource_section_key = messages.StringField(5)
resource_section_name = messages.StringField(6)
types = messages.StringField(7, repeated=True)
page = messages.IntegerField(8)
keywords = messages.StringField(9, repeated=True)
user_email = messages.StringField(10)
user_org_key = messages.StringField(11)
class KnowledgeMessageList(messages.Message):
items = messages.MessageField(KnowledgeMessage, 1, repeated=True)
#endpoints.api(name="knowledge", version="v1", description="API for Knowledge management",
auth_level=endpoints.AUTH_LEVEL.REQUIRED,
allowed_client_ids=['1-web-apps.apps.googleusercontent.com',
'2-android-apps.apps.googleusercontent.com',
endpoints.API_EXPLORER_CLIENT_ID])
class KnowledgeMessageApi(remote.Service):
#endpoints.method(KnowledgeMessage, KnowledgeMessage, name="knowledge_message.insert", path="knowledge", http_method="POST")
def insert_knowledge(self, request):
authenticated_user = ApiUser()
logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - authenticated_user.email = " + authenticated_user.email)
PARENT_KEY = authenticated_user.get_org_key()
logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - authenticated_user.get_org_key()")
logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.knowledge = " + request.knowledge)
logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.resource_key = " + request.resource_key)
logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.resource_section_key = " + request.resource_section_key)
types_string = ""
for item in request.types:
types_string += item.strip()
logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.types = " + types_string)
logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.page = " + str(request.page))
keywords_string = ""
for item in request.keywords:
keywords_string += item.strip()
logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.keywords = " + keywords_string)
if request.knowledge_key:
logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.knowledge_key = " + request.knowledge_key)
# If no key exists, then we can assume it needs to be inserted
# into the datastore. Overwrite any exiting values with what
# is passed into the method
kno=ndb.Key(urlsafe=request.knowledge_key).get()
kno.knowledge = request.knowledge
kno.resource = ndb.Key(urlsafe=request.resource_key)
kno.resource_section = ndb.Key(urlsafe=request.resource_section_key)
kno.types = request.types
kno.page = request.page
kno.keywords = request.keywords
kno.put()
else:
#get resource key and name
Knowledge(parent=PARENT_KEY,
knowledge=request.knowledge,
resource = ndb.Key(urlsafe=request.resource_key),
resource_section = ndb.Key(urlsafe=request.resource_section_key),
types = request.types,
page = request.page,
keywords = request.keywords
).put()
return request
#endpoints.method(message_types.VoidMessage, KnowledgeMessageList, name='knowledge_message.list', path='knowledge_messages', http_method='GET')
def list_knowledge(self, unused_request):
authenticated_user = ApiUser()
if not authenticated_user.is_authenticated:
logging.info("Logging: KnowledgeMessageApi.list_knowledge - user was not authenticated")
raise endpoints.ForbiddenException()
logging.info("finding current user info : " + authenticated_user.email)
PARENT_KEY = authenticated_user.get_org_key()
knos = []
for kno in Knowledge.query(ancestor=PARENT_KEY):
knos.append(KnowledgeMessage(knowledge_key=kno.key.urlsafe(),
knowledge=kno.knowledge,
resource_key=kno.resource.urlsafe(),
resource_name=kno.resource.get().name,
resource_section_key=kno.resource_section.urlsafe(),
resource_section_name=kno.resource_section.get().name,
types=kno.types,
page=kno.page,
keywords=kno.keywords,
user_email=authenticated_user.email,
user_org_key=PARENT_KEY.urlsafe())
)
return KnowledgeMessageList(items=knos)
app = endpoints.api_server([KnowledgeMessageApi])
I'll also include a few images of proofs that I explored prior to sending the question.
enter image description here
I will greatly appreciate any help I receive.
I discovered my mistake after much work:
In my api, I never specified which client_ids were permitted.
#endpoints.api(name="knowledge", version="v1", description="API for Knowledge management",
auth_level=endpoints.AUTH_LEVEL.REQUIRED,
allowed_client_ids=['1-web-apps.apps.googleusercontent.com',
'2-android-apps.apps.googleusercontent.com',
endpoints.API_EXPLORER_CLIENT_ID])
class KnowledgeMessageApi(remote.Service):
Apparently the code '1-web-apps.apps.googleusercontent.com' was a placeholder, and I never replaced it with my own. That has been corrected.
Django REST Framework is reporting an error that a value is null even though I am sending the value when I POST the data.
The error Django reports is:
django.db.utils.IntegrityError: (1048, "Column 'owner_id' cannot be null")
[04/Apr/2016 18:40:58] "POST /api/items/ HTTP/1.1" 500 226814
The Angular 2 code that POSTs to Django REST Framework API is:
let body = JSON.stringify({ url: 'fred', item_type: 'P', owner_id: 2 });
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post('http://127.0.0.1:8000/api/items/',
body, {
headers: headers
})
.subscribe(
data => {
alert(JSON.stringify(data));
},
err => alert('POST ERROR: '+err.json().message),
() => alert('POST Complete')
);
My Django API view looks like this:
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all().order_by('-date_added')
serializer_class = ItemSerializer
"""
Use the API call query params to determing what to return
API params can be:
?user=<users_id>&num=<num_of_items_to_return>&from=<user_id_of_items_to_show>
"""
def get_queryset(self):
this_user = self.request.query_params.get('user', None)
restrict_to_items_from_user_id = self.request.query_params.get('from', None)
quantity = self.request.query_params.get('num', 20)
if restrict_to_items_from_user_id is not None:
queryset = Item.objects.filter(owner=restrict_to_items_from_user_id, active=True).order_by('-date_added')[0:int(quantity)]
elif this_user is not None:
queryset = Item.objects.filter(active=True, credits_left__gt=0).exclude(pk__in=Seen.objects.filter(user_id=this_user).values_list('item_id', flat=True))[0:int(quantity)]
else:
queryset = Item.objects.filter(active=True, credits_left__gt=0)[0:int(quantity)]
print("User id param is %s and quantity is %s" % (user_id,quantity))
return queryset
The associated model is:
class Item(models.Model):
ITEM_TYPES = (
('V', 'Vine'),
('Y', 'YouTube'),
('P', 'Photo'), # Photo is stored by us on a CDN somewhere
('F', 'Flickr'),
('I', 'Instagram'),
('D', 'DeviantArt'),
('5', '500px'),
)
owner = models.ForeignKey(User, on_delete=models.CASCADE) # Id of user who owns the item
title = models.CharField(max_length=60, default='') # URL of where item resides (e.g. Vine or YouTube url)
url = models.CharField(max_length=250, default='') # URL of where item resides (e.g. Vine or YouTube url)
item_type = models.CharField(max_length=1, choices=ITEM_TYPES) # Type of item (e.g. Vine|YoutTube|Instagram|etc.)
keywords = models.ManyToManyField(Keyword, related_name='keywords')
# E.g. Art, Travel, Food, etc.
credits_applied = models.IntegerField(default=10, help_text='Total number of credits applied to this item including any given by VeeU admin')
# Records the total number of credits applied to the Item
credits_left = models.IntegerField(default=10, help_text='The number of credits still remaining to show the item')
# Number of credits left (goes down each time item is viewed
credits_gifted = models.IntegerField(default=0, help_text='The number of credits this item has been gifted by other users')
# Number of credits users have gifted to this item
date_added = models.DateTimeField(auto_now_add=True) # When item was added
liked = models.IntegerField(default=0) # Number of times this item has been liked
disliked = models.IntegerField(default=0) # Number of times this item has been disliked
active = models.BooleanField(default=True, help_text='If you mark this item inactive please say why in the comment field. E.g. "Inapproriate content"')
# True if item is available for showing
comment = models.CharField(max_length=100, blank=True) # Comment to be applied if item is inactive to say why
# Add defs here for model related functions
# This to allow url to be a clickable link
def item_url(self):
return u'%s' % (self.url, self.url)
item_url.allow_tags = True
def __str__(self):
return '%s: Title: %s, URL: %s' % (self.owner, self.title, self.url)
I can't see what is wrong with my POST call, or the Django code.
EDIT: Added serializer code
Here is the associated serializer
class ItemSerializer(serializers.HyperlinkedModelSerializer):
username = serializers.SerializerMethodField()
def get_username(self, obj):
value = str(obj.owner)
return value
def get_keywords(self, obj):
value = str(obj.keywords)
return value
class Meta:
model = Item
fields = ('url', 'item_type', 'title', 'credits_applied', 'credits_left', 'credits_gifted', 'username', 'liked', 'disliked')
Your serializer doesn't have an owner field and your view doesn't provide one. As it's non null in your model the DB will complain about this.
You should override the view's perform_update and add the owner as extra argument to the serializer
You need to pass the Resource URI for the field which is foreign key,
here owner is the FK, so the
ownerIns = User.objects.get(id=2)
let body = JSON.stringify({ url: 'fred', item_type: 'P', owner: ownerIns, owner_id: ownerIns.id });
I ran into a similar issue using Angular and Flask. This may because your CORS headers are not set correctly for your Django app which makes your Angular app not allowed to post to the backend. In Flask, I fixed it using this code:
#app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
return response
I'm not sure how to do this in Django, but this may be a great first stop for you since this is likely your issue.
Is your ItemSerializer code correct? The rest looks fine to me.
You should be having 'owner_id' in your serializer fields i think.
Take a look at this answer, add the related fields in this manner.
https://stackoverflow.com/a/20636415/5762482