Django rest framework Custom User model with token error - django

I've tried to use custom user model instead of default user.
My Django project structure is below.
Project name : project_rest
App name : app_rest
To make it happen, I refer https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#substituting-a-custom-user-model
[settings.py]
AUTH_USER_MODEL = 'app_rest.User'
[models.py]
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
from django.conf import settings
from django.contrib.auth.models import AbstractUser
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
class User(AbstractUser):
username = models.CharField(unique=True, null=False, max_length=254)
password = models.CharField(max_length=200)
[serializers.py]
from app_rest.models import User
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'password')
[views.py]
from django.shortcuts import render
from app_rest.serializers import UserSerializer
from app_rest.models import User
from rest_framework import viewsets
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
[urls.py]
from django.conf.urls import url, include
from app_rest import views
from rest_framework import routers
from django.contrib import admin
from rest_framework.authtoken import views as rest_views
router = routers.DefaultRouter()
router.register(r'user', views.UserViewSet)
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^token-auth/', rest_views.obtain_auth_token),
url(r'^admin/', admin.site.urls),
]
I seems work properly, But when I delete user, It throws error.
IntegrityError at /admin/app_rest/user/1/delete/ (1452, 'Cannot add or
update a child row: a foreign key constraint fails
('rest'.'django_admin_log', CONSTRAINT
'django_admin_log_user_id_c564eba6_fk_auth_user_id' FOREIGN KEY
('user_id') REFERENCES 'auth_user' ('id'))')
How can I solve this issue?

The error is pretty self explanatory. The record you are trying to delete is related to another one by a foreign key and it cannot be deleted as it would break referential integrity.
You need to alter that id with something like ON DELETE CASCADE or its equivalent, or allow the user to be null on the related table (if that's possible).

Related

Django create user Direct assignment to the forward side of a many-to-many set is prohibited. Use groups.set() instead

I am using the Django default User model to do user registration. When I was trying to create a user I got this error message. Direct assignment to the forward side of a many-to-many set is prohibited. Use groups.set() instead.
# views.py
from django.contrib.auth.models import User
from rest_framework import viewsets
from app.serializers import UserSerializer
# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
extra_kwargs = {'password': {'write_only': True, 'required': False}}
def create(self, validated_data):
print(validated_data)
user = User.objects.create_user(**validated_data)
return user
# urls.py
from django.urls import path, include
from rest_framework import routers
from app import views
from rest_framework.authtoken.views import obtain_auth_token
router = routers.SimpleRouter()
router.register(r'users', views.UserViewSet)
urlpatterns = [
path('auth/', obtain_auth_token),
]
urlpatterns += router.urls
I only insert the user record, there is no foreign table or many-to-many relationship. Not sure why the system throws this error.
Attached with the postman screenshot.

Relation doesn't exist in django restframework

I am creating one crud operation in django restframework and I have created project name "portfolio" and app "stock" and store in postgres database Here is my code.
stock.models.py
from django.db import models
class Stocks(models.Model):
Name = models.CharField(max_length=50)
Number_of_Share = models.IntegerField()
Unit_Price = models.IntegerField()
ShareValue=models.IntegerField()
Total_Share_Value= models.IntegerField()
stock.serializers.py
from rest_framework import serializers
from .models import Stocks
class StocksSerializer(serializers.ModelSerializer):
class Meta:
model =Stocks
fields = '__all__'
stock.viewset.py
from rest_framework import viewsets
from .models import Stocks
from . import serializers
class StockViewset(viewsets.ModelViewSet):
queryset = Stocks.objects.all()
serializer_class = serializers.StocksSerializer
portfolio.router.py
from stock.viewsets import StockViewset
from rest_framework import routers
router = routers.DefaultRouter()
router.register('Stocks',StockViewset)
portfolio.urls.py
from django.urls import path, include
from .router import router
urlpatterns = [
# path('admin/', admin.site.urls),
path('portfolio/',include(router.urls))
]
But I am facing this error.
Exception Type: ProgrammingError
Exception Value:
relation "stock_stocks" does not exist
LINE 1: ...reValue", "stock_stocks"."Total_Share_Value" FROM "stock_sto...
Please help me solve this error.

Django Rest Framework Assertion Error: Missing Meta.model attribute

I am trying to implement Rest api using Django framework. But when I click on the url on the default index page it gives me an assertion error at/languages/ Class LanguageSerializer missing meta.model attribute
I made all the migrations after changes in models.py but it did nothing
urls.py
from django.urls import path, include
from . import views
from rest_framework import routers
router = routers.DefaultRouter()
router.register('languages', views.LanguageView)
urlpatterns = [
path('', include(router.urls))
]
models.py
from django.db import models
class Language(models.Model):
name = models.CharField(max_length=50)
paradigm = models.CharField(max_length=50)
serializers.py
from rest_framework import serializers
from .models import Language
class LanguageSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'name', 'paradigm')
views.py
from django.shortcuts import render
from rest_framework import viewsets
from .models import Language
from .serializers import LanguageSerializer
class LanguageView(viewsets.ModelViewSet):
queryset = Language.objects.all()
serializer_class = LanguageSerializer
I have no clue where am I going wrong
You need to specify what model you want to serialize in the Meta class of your serializer, like:
from rest_framework import serializers
from .models import Language
class LanguageSerializer(serializers.ModelSerializer):
class Meta:
model = Language # specify the model
fields = ('id', 'name', 'paradigm')
otherwise the serializer can not determine the fields of that model, and how it will serialize the data from these fields.

Django execute custom code after user signup

I have a users app in a Django project (version 2.1 and python 3.6). After an user signup (both front end and when added in the admin dashboard ideally), I'd like to insert data in one other table. I know how to insert data, but I didn't find out how to do it right after a successfull signup.
Ideal answer would just show me how to do something like print('hello') right after an user created his account.
# users/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['email', 'username',]
admin.site.register(CustomUser, CustomUserAdmin)
# users/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ('username', 'email')
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ('username', 'email')
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
# add additional fields in here
credit = models.IntegerField(default=200) # editable=False
def __str__(self):
return self.email
# users/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('signup/', views.SignUp.as_view(), name='signup'),
]
# users/views.py
from django.urls import reverse_lazy
from django.views import generic
from .forms import CustomUserCreationForm
class SignUp(generic.CreateView):
form_class = CustomUserCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
Use a post-save signal
https://docs.djangoproject.com/en/2.1/ref/signals/
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=User)
def say_hello(sender, instance, **kwargs):
if instate._state.adding:
print('hello')
Signal is better than a method on the view because the User may be created some way other than through the view e.g , via the shell, a management command, a migration, a different view, etc.
Note the _state is not "private" so don't feel bad about using it, it's just named that way to avoid clashing with field names.
Check _state instead of more common checking instance.pk because instance.pk is always present when primary key is a natural key rather than AutoField
I think the best approach would be overriding save method of CustomUser model. For example:
class CustomUser(AbstructUser):
def save(self, *args, **kwargs):
user = super(CustomUser, self).save(*args, **kwargs)
print("Hello World")
return user
Check here in Django documentation for more details: https://docs.djangoproject.com/en/2.1/topics/db/models/#overriding-predefined-model-methods.

How to add django-reversion to an app developed using django and django-rest framework

I have an app developed using Django and Django Rest framework. I would like to add the django-reversion feature to my app.
I have already tried http://django-reversion.readthedocs.org/en/latest/api.html#low-level-api but I have failed to make specific changes to my app.
Below are the modules of the app where I would like to include the Django-reversion to restore objects if they get deleted. How to set the django-reversion configuration for the below modules
admin.py:-
from django.contrib import admin
from.models import Category
admin.site.register(Category)
models.py:-
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=64, unique=True)
def __unicode__(self):
return self.name
serializers.py:-
from rest_framework import serializers
from .models import Category
class CategorySerializer(serializers.ModelSerializer):
courses = serializers.HyperlinkedRelatedField(
many=True
read_only=True
view_name='course-detail'
)
class Meta:
model = Category
fields = ('pk', 'name', 'courses',)
urls.py :-
from django.conf.urls import patterns, url
from rest_framework.urlpatterns import format_suffix_patterns
from .import views
from django.conf.urls import include
category_list = views.CategoryViewSet.as_view({
'get': 'list',
'post': 'create'
})
category_detail = views.CategoryViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy',
})
urlpatterns = format_suffix_patterns([
url(r'^categories/$',
category_list,
name='category-list'),
url(r'^categories/(?P<pk>[0-9]+)/$',
category_detail,
name='category-detail'),
])
urlpatterns += [
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
]
views.py :-
from rest_framework import permissions
from rest_framework import viewsets
from .models import Category
from .serializers import CategorySerializer
class CategoryViewSet(viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
permission_classes = (permissions.IsAuthenticatedorReadOnly,)
The simplest way to create revisions is to use reversion.middleware.RevisionMiddleware. This will automatically wrap every request in a revision, ensuring that all changes to your models will be added to their version history.
To enable the revision middleware, simply add it to your MIDDLEWARE_CLASSES setting as follows:
MIDDLEWARE_CLASSES = (
'reversion.middleware.RevisionMiddleware',
# Other middleware goes here...
)
Any thing more complex with this will require adding API calls through your code in away that wraps specific save calls in ways that you decide.
admin.py
from django.contrib import admin
from.models import Category
import reversion
class BaseReversionAdmin(reversion.VersionAdmin):
pass
admin.site.register(Category, BaseReversionAdmin)
also added reversion to installed_apps and middlewareclasses.
Finally i could see the "recover deleted objects button".
I discovered that since rest_framework.viewsets.ModelViewSet inherits from django.views.generic.View so you can also use the reversion.views.RevisionMixin to create revisions instead of having to use the middleware if you want.
From the question above this would look like the following:
from rest_framework import permissions
from rest_framework import viewsets
from .models import Category
from .serializers import CategorySerializer
from reversion.views import RevisionMixin
class CategoryViewSet(RevisionMixin, viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
permission_classes = (permissions.IsAuthenticatedorReadOnly,)
You can read more about the specifics of how you can use RevisionMixin here: https://django-reversion.readthedocs.io/en/stable/views.html#reversion-views-revisionmixin