Django rest framework-delete user but Table doesn't exist - django

Table AWSIOt.User_set_user doesn't exist
image to show error
Hello, everybody, this is my first post.
I tried to delete a user by using user.delete(). However, it didn;t find user from table auth_user.
It looked for user from project.appname_user. I didn't create model user in my app and i writed "from django.contrib.auth.models import User" in top of my view file.
here are all my code
from django.contrib.auth.models import User
from .head import *
class UserDeleteView(APIView):
def get(self, request):
try:
user_id = self.request.query_params.get('user_id')
user = User.objects.get(id=user_id)
user.delete()
return Response(Return_msg())
except User.DoesNotExist:
return Response(Return_msg(None, True, 'Failed, user does not exist!!!'))
so, how can i fix it???

Frank. Your bug is probably related to the fact you're using wildcard import from .head import *. That might be causing namespace collision with User.
I would recommend you to consider using delete method from APIView as the snippet below:
views.py
from django.contrib.auth.models import User
from rest_framework.response import Response
from rest_framework import status
from django.http import Http404
class UserDetailsView(APIView):
def get_object(self, pk):
try:
return User.objects.get(pk=pk)
except User.DoesNotExist:
raise Http404
def delete(self, request, pk, format=None):
user = self.get_object(pk)
user.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
urls.py
from django.urls import path
from . import views
urlpatterns = [
path("user/<int:pk>/", views.UserDetailsView.as_view(), name="details_user"),
]

Related

TypeError: Object of type User is not JSON serializable

I am quite new to Django and I am building a simple referral system where a code is autogenerated for the user and when this code is called, the API should return the user by which this code was referred. However I am experiencing some difficulties to return the username, getting the error TypeError: Object of type User is not JSON serializable. Below I am posting my code (please ignore the unused imports, I was trying many things and I need to clean the code later)
views.py
`
from rest_framework.decorators import api_view
from rest_framework.response import Response
import json, requests
from rest_framework.views import APIView
from django.http import JsonResponse, HttpResponse
from django.core import serializers
from django.core.serializers import serialize
import ast
from rest_framework.parsers import JSONParser
class MainView(APIView):
def post(self, request):
code = request.data["ref_code"]
print(str(code))
try:
profile = ReferralSys.objects.get(code=code)
print(profile)
request.session["ref_profile"] = profile.user
username = profile.user.username
print(username)
print(type(username))
# return HttpResponse("user is here", user)
except:
pass
print(request.session.get_expiry_date())
return Response(f"{profile.user.username}")
models.py
from django.db import models
from django.contrib.auth.models import User
from .utils import generate_ref_code
class ReferralSys(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(blank=True)
code = models.CharField(max_length=12, blank=True)
recommented_by = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True, related_name="ref_by"
)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user.username}-{self.code}"
def get_recommended_profiles(self):
pass
def save(self, *args, **kwargs):
if self.code == "":
code = generate_ref_code()
self.code = code
super().save(*args, **kwargs)
utils.py
import uuid
def generate_ref_code():
code = str(uuid.uuid4()).replace("-", "")[:12]
return code
urls.py
from django.contrib import admin
from django.urls import path
from .views import MainView
urlpatterns = [
path("admin/", admin.site.urls),
path("", MainView.as_view()),
path("str:<ref_code>", MainView.as_view()),
]
Thank you in advance for the help.
PS: I am following this tutorial https://www.youtube.com/watch?v=QZfflGvRQrc&t, but instead of using templates I want to use APIView.
What happens is that Django sessions serializes data using JSON. When writing:
request.session["ref_profile"] = profile.user
You are trying to insert a model inside the session, thus the error. One basic and simple way, is to parse the desired data into a JSON:
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import ReferralSys
import json
class MainView(APIView):
def post(self, request, code=None):
if code is None:
code = request.data['code']
try:
profile = ReferralSys.objects.get(code=code)
user = {
'username': profile.user.username,
'email': profile.user.email
}
user_json = json.dumps(user)
request.session["ref_profile"] = user_json
except:
pass
print(request.session.get_expiry_date())
return Response(f"{profile.user.username}")
Of course, there are tradeoffs and I recommend you to read the documentation in order to understand them. There is also another mistake in the form of how you are passing (and retrieving) the extra keyword argument in the URL, the right syntax:
path("<str:code>/", MainView.as_view()),

Why User model has type string?

I have a view that returns data corresponded to the user, but when I try to find the User I get this error:
Type str has no object method
File views.py
from .models import Question, User
#api_view(['POST'])
#renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def answers_view(request, *args, **kwargs):
userstring = request.data["name"]
try:
user0 = User.objects.get(username=userstring)
except ObjectDoesNotExist:
user0 = "NotFound"
print("USER: ", user0, flush = True)
File models.py
from django.db import models
# Create your models here.
import random
from django.conf import settings
from django.db import models
from django.db.models import Q
User = settings.AUTH_USER_MODEL
The AUTH_USER_MODEL setting is a string, this is often used to refer to the user model, for example in a ForeignKey, the advantage of this is that at that moment, the user model does not have to be loaded (yet).
In order to get a reference to the model, you use the get_user_model() function [Django-doc]:
from .models import Question
from django.contrib.auth import get_user_model
#api_view(['POST'])
#renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def answers_view(request, *args, **kwargs):
userstring = request.data['name']
try:
user0 = get_user_model().objects.get(username=userstring)
except ObjectDoesNotExist:
user0 = 'NotFound'
print('USER: ', user0, flush=True)

How can i fetch data from django models(database) using celery(asynchronously) from previously existing data

tasks.py
import string
from django.contrib.auth.models import User
from django.utils.crypto import get_random_string
from celery import shared_task
#shared_task
def create_random_user_accounts(total):
for i in range(total):
username = 'user_{}'.format(get_random_string(10, string.ascii_letters))
email = '{}#example.com'.format(username)
password = get_random_string(50)
User.objects.create_user(username=username, email=email, password=password)
return '{} random users created with success!'.format(total)
views.py
from django.contrib.auth.models import User
from .tasks import create_random_user_accounts
from django.http import JsonResponse
def users(request):
obj = list(User.objects.values())
create_random_user_accounts.delay(20)
return JsonResponse(obj,safe=False)
here i am inserting some random datas to User model using celery
And it is working while fetching same data.
But, i want to fetch 'existing data' from database 'without inseting' them on same request.
Please share me some idea how can i do that.
Method #1 do the insert off a POST and then retrieve via a GET:
from django.contrib.auth.models import User
from .tasks import create_random_user_accounts
from django.http import JsonResponse
from django.views.generic import View
class UserView(View):
def get(self, request, *args, **kwargs):
obj = list(User.objects.values())
return JsonResponse(obj,safe=False)
def post(self, request, *args, **kwargs):
create_random_user_accounts.delay(20)
obj = list(User.objects.values())
return JsonResponse(obj,safe=False)
Method #2 is just to remove the call to create_random_user_accounts, since that is what is creating the accounts:
from django.contrib.auth.models import User
from .tasks import create_random_user_accounts
from django.http import JsonResponse
def users(request):
obj = list(User.objects.values())
# create_random_user_accounts.delay(20)
return JsonResponse(obj,safe=False)

How do you return 404 when resource is not found in Django REST Framework

When a user inputs a url that is wrong, my Django app returns an HTML error. How can I get DRF to return a json formatted error?
Currently my urls is
from django.conf.urls import url
from snippets import views
urlpatterns = [
url(r'^snippets/$', views.snippet_list),
url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]
but if a user goes to 127.0.0.1:8000/snip They get the html formatted error rather than a json formatted error.
Simply way to do it, you can use raise Http404, here is your views.py
from django.http import Http404
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from yourapp.models import Snippet
from yourapp.serializer import SnippetSerializer
class SnippetDetailView(APIView):
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data, status=status.HTTP_200_OK)
You also can handle it with Response(status=status.HTTP_404_NOT_FOUND), this answer is how to do with it: https://stackoverflow.com/a/24420524/6396981
But previously, inside your serializer.py
from rest_framework import serializers
from yourapp.models import Snippet
class SnippetSerializer(serializers.ModelSerializer):
user = serializers.CharField(
source='user.pk',
read_only=True
)
photo = serializers.ImageField(
max_length=None,
use_url=True
)
....
class Meta:
model = Snippet
fields = ('user', 'title', 'photo', 'description')
def create(self, validated_data):
return Snippet.objects.create(**validated_data)
To test it, an example using curl command;
$ curl -X GET http://localhost:8000/snippets/<pk>/
# example;
$ curl -X GET http://localhost:8000/snippets/99999/
Hope it can help..
Update
If you want to handle for all error 404 urls with DRF, DRF also provide about it with APIException, this answer may help you; https://stackoverflow.com/a/30628065/6396981
I'll give an example how do with it;
1. views.py
from rest_framework.exceptions import NotFound
def error404(request):
raise NotFound(detail="Error 404, page not found", code=404)
2. urls.py
from django.conf.urls import (
handler400, handler403, handler404, handler500)
from yourapp.views import error404
handler404 = error404
Makesure your DEBUG = False
from rest_framework import status
from rest_framework.response import Response
# return 404 status code
return Response({'status': 'details'}, status=status.HTTP_404_NOT_FOUND)
An easier way is to use get_object_or_404 method in django:
as described in this link:
get_object_or_404(klass, *args, kwargs)
- Calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.
- klass: A Model class, a Manager, or a QuerySet instance from which to get the object.
As an example, pay attention to
obj = get_object_or_404(Snippet, pk=pk)
return obj
in the following code:
from django.shortcuts import get_object_or_404
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
class SnippetDetail(APIView):
"""
Retrieve, update or delete a snippet instance.
"""
def get_object(self, pk):
obj = get_object_or_404(Snippet, pk=pk)
return obj
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
...
Or simply, you can use the same structure of DRF, without losing I18N and keep the same DRF error message:
from rest_framework import viewsets, status, exceptions
from rest_framework.decorators import action
from rest_framework.response import Response
try:
codename = get_or_bad_request(self.request.query_params, 'myparam')
return Response(self.get_serializer(MyModel.objects.get(myparam=codename), many=False).data)
except MyModel.DoesNotExist as ex:
exc = exceptions.NotFound()
data = {'detail': exc.detail}
return Response(data, exc.status_code)

django profile creation, set User profile while using multiple profile types

I am stuck at user registration, I actually intends to have different profile types. While registration I am unable to set UserProfile while creating a user. I am using UserCreationForm. code in my files are as following.
from django.contrib.auth.forms import UserCreationForm
from registration.forms import RegistrationForm
from django import forms
from django.contrib.auth.models import User
from accounts.models import UserProfile
from django.utils.translation import ugettext_lazy as _
from person.models import Person
from pprint import pprint
class UserRegistrationForm(UserCreationForm):
#email = forms.EmailField(label = "Email")
fullname = forms.CharField(label = "Full name")
class Meta:
model = User
fields = ("email","fullname","password1","password2" )
def __init__(self, *args, **kwargs):
super(UserRegistrationForm, self).__init__(*args, **kwargs)
del self.fields['username']
def clean_email(self):
"""
Validate that the supplied email address is unique for the
site.
"""
if User.objects.filter(email__iexact=self.cleaned_data['email']):
raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
return self.cleaned_data['email']
def save(self, commit=True):
user = super(UserRegistrationForm, self).save(commit=False)
#user_profile=user.set_profile(profile_type="Person")
UserProfile.profile.person.full_name = self.cleaned_data["fullname"]
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
class CompanyRegistrationForm(UserCreationForm):
email=forms.EmailField(label="Email")
class UserProfileForm(forms.ModelForm):
class Meta:
model=UserProfile
exclude=('user',)
accounts/models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user=models.OneToOneField(User)
meta_keywords=models.CharField("Meta Keywords",max_length=255,
help_text="Comma delimited set of keywords of meta tag")
meta_description=models.CharField("Meta Description",max_length=255,
help_text='Content for description meta tag')
def __unicode__(self):
return "User Profile for: "+self.username
class Meta:
ordering=['-id']
views.py
from django.contrib.auth.forms import UserCreationForm
from django.template import RequestContext
from django.shortcuts import render_to_response,get_object_or_404
from django.core import urlresolvers
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from accounts.forms import UserRegistrationForm, UserProfileForm
#from accounts.forms import UserProfile
def register(request,template_name="account/register.html"):
if request.method=='POST':
postdata=request.POST.copy()
form=UserRegistrationForm(postdata)
user_profile=UserProfileForm(postdata)
if form.is_valid():
form.save()
un=postdata.get('username','')
pw=postdata.get('password','')
from django.contrib.auth import login,authenticate
new_user=authenticate(username=un,password=pw)
if new_user and new_user.is_active:
login(request,new_user)
url=urlresolvers.reverse('dashboard')
return HttpResponseRedirect(url)
else:
form=UserRegistrationForm()
page_title="User Registration"
return render_to_response(template_name,locals(),context_instance=RequestContext(request))
#login_required
def dashboard(request):
pass
#login_required
def settings(request):
pass
As I am using multiple profiles so following is code of one of those profiles' models.py:
from django.db import models
from django.contrib.auth.models import User
from accounts.models import UserProfile
class Person(UserProfile):
skills=models.CharField(max_length=100)
fullname=models.CharField(max_length=50)
short_description=models.CharField(max_length=255)
is_online=models.BooleanField(default=False)
tags=models.CharField(max_length=50)
profile_pic=models.ImageField(upload_to="person_profile_images/")
profile_url=models.URLField()
date_of_birth=models.DateField()
is_student=models.BooleanField(default=False)
current_designation=models.CharField(max_length=50)
is_active_jobseeker=models.BooleanField(default=True)
current_education=models.BooleanField(default=True)
class Meta:
db_table='person'
My profile auth in settings.py
AUTH_PROFILE_MODULE='accounts.UserProfile'
Here is a file that also I used after looking at some other place, profile.py:
from accounts.models import UserProfile
from accounts.forms import UserProfileForm
from person.models import Person
from company.models import Company
def retrieve(request,profile_type):
try:
profile=request.user.get_profile()
except UserProfile.DoesNotExist:
if profile_type=='Person':
profile=Person.objects.create(user=request.user)
else:
profile=Company.objects.create(user=request.user)
profile.save()
return profile
def set(request,profile_type):
profile=retrieve(request,profile_type)
profile_form=UserProfileForm(request.POST,instance=profile)
profile_form.save()
I am new and confuse, have seen documentation also. Also saw other solutions at stackoverflow.com but didn't find any solution of my problem. So please tell if you find anything helpful for me. It doesn't seems to be a big problem but as I am new to it so it is a problem for me.
Multiple profile types won't work with the OneToOne relation that is required by Django profile mechanism. I suggest you keep a single profile class containing data common to all profile types and you store type-specific data in a separate set of classes that you link to your profile class using a generic relation.
EDIT:
Thanks for the clarification. Looking at your code again today it seems that you might indeed be able to accomplish what your trying to do with model inheritance. I think the problem is in the save() method of UserRegistrationForm. Try something like this:
def save(self, commit=True):
user = super(UserRegistrationForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
person = Person(user=user)
person.full_name = self.cleaned_data["fullname"]
person.save()
return user