Add attribute to admin model Django - django

I'm trying to add an attribute to my user admin model, but it doesn't work,
here is what I succeded to do (I want to add inactivity field):
from django.contrib import admin
from .models import User
class usersAdmin(admin.ModelAdmin):
list_display = ('username', 'first_name', 'last_name', 'inactivity')
admin.site.register(User, usersAdmin)
Here is my model code:
class User(models.Model):
username = models.TextField(max_length=140, default='uid', primary_key=True)
first_name = models.TextField(max_length=140, default='cn')
last_name = models.TextField(max_length=140, default='givenName')
inactivity = models.IntegerField(default=500)
def _str_(self):
return self
The error occurs when I'm trying to access to my added field from my views:
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
data = super().validate(attrs)
data['username'] = self.user.username
data['first_name'] = self.user.first_name
data['last_name'] = self.user.last_name
data['inactivity'] = self.user.inactivity
print(self.user)
return data
the error says:
Traceback (most recent call last):
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\django\views\generic\base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\rest_framework\views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
raise exc
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\rest_framework\views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\rest_framework_simplejwt\views.py", line 27, in post
serializer.is_valid(raise_exception=True)
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\rest_framework\serializers.py", line 220, in is_valid
self._validated_data = self.run_validation(self.initial_data)
File "C:\Users\oussa\.virtualenvs\SYNEIKA-v3YFud-O\lib\site-packages\rest_framework\serializers.py", line 422, in run_validation
value = self.validate(value)
File "C:\Users\oussa\OneDrive\Documents\GitHub\SYNEIKA\backend\ldapapp\views.py", line 85, in validate
data['inactivity'] = self.user.inactivity
AttributeError: 'User' object has no attribute 'inactivity'
PS: I'm using LDAP auth backend in setting.py I have:
import ldap
from django_auth_ldap.config import LDAPSearch, LDAPGroupQuery,PosixGroupType
AUTH_LDAP_SERVER_URI = 'ldap://192.0.0.1'
AUTH_LDAP_BIND_DN = 'cn=admin,dc=syneika,dc=com'
AUTH_LDAP_BIND_PASSWORD = '123'
AUTH_LDAP_USER_SEARCH = LDAPSearch('ou=users,dc=syneika,dc=com',ldap.SCOPE_SUBTREE, '(uid=%(user)s)')
AUTH_LDAP_GROUP_SEARCH = LDAPSearch('ou=groups,dc=syneika,dc=com',ldap.SCOPE_SUBTREE, '(objectClass=top)')
AUTH_LDAP_GROUP_TYPE = PosixGroupType(name_attr="cn")
AUTH_LDAP_MIRROR_GROUPS = True
# Populate the Django user from the LDAP directory.
AUTH_LDAP_REQUIRE_GROUP = (
LDAPGroupQuery("cn=Active,ou=groups,dc=syneika,dc=com")
)
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
"last_name": "sn",
"email": "mail",
"username": "uid",
"password": "userPassword"
}
AUTH_LDAP_PROFILE_ATTR_MAP = {
"home_directory": "homeDirectory"
}
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"is_active": (
LDAPGroupQuery("cn=Active,ou=groups,dc=syneika,dc=com")
),
"is_staff": (
LDAPGroupQuery("cn=Staff,ou=groups,dc=syneika,dc=com")
),
"is_superuser": (
LDAPGroupQuery("cn=Superuser,ou=groups,dc=syneika,dc=com")
)
}
AUTH_LDAP_ALWAYS_UPDATE_USER = True
AUTH_LDAP_FIND_GROUP_PERMS = True
AUTH_LDAP_CACHE_TIMEOUT = 3600
AUTH_LDAP_FIND_GROUP_PERMS = True
# Keep ModelBackend around for per-user permissions and maybe a local
# superuser.
AUTHENTICATION_BACKENDS = (
'django_auth_ldap.backend.LDAPBackend',
'django.contrib.auth.backends.ModelBackend',
)

Please go into your root directory and delete all migrations from the root directory leaving only init file then go back into your command console and apply the migrations before you sync it to your database with migrate. Your from problem seems to come from the --fake migrate as it does not actually sync it to the databased.

I figured out that in my view (TokenView) I'm referencing to the Auth user and not the User Model in my models.
So to add another attributes to the Authenticating user (provided by Django by default), I must associate the Auth user to another model and add the attributes I want, I found it here : Django Profiles
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
activity = models.IntegerField(default=500)
def _str_(self):
return self

Related

Unable to search using elasticsearch in django with django-elasticsearch-dsl-drf (Set fielddata=true on [title.raw])

I have followed the quick start guide shown here, in order to experiment with elasticsearch searching and a sample Django app I am playing with.
Using elasticsearch 6.3.1 and latest django-elasticsearch-dsl-drf
The results is the following error.
RequestError at /search/movies/
RequestError(400, 'search_phase_execution_exception', 'Fielddata is disabled on text fields by default. Set fielddata=true on [title.raw] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead.')
I have added in the django project an extra app named search_indexes.
Here is the documents.py from this app.
# Name of the Elasticsearch index
INDEX = Index('search_movies')
# See Elasticsearch Indices API reference for available settings
INDEX.settings(
number_of_shards=1,
number_of_replicas=1
)
html_strip = analyzer(
'html_strip',
tokenizer="standard",
filter=["standard", "lowercase", "stop", "snowball"],
char_filter=["html_strip"]
)
#INDEX.doc_type
class MovieDocument(DocType):
"""Movie Elasticsearch document."""
id = fields.IntegerField(attr='id')
title = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
summary = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
Now, after running manage.py search_index --rebuild, i can visit the url http://localhost:9200/search_movies/_search?pretty where I can see that the index has been created properly and I can see the data as well.
Moving on to the next part this is my serializers.py file
from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
from .documents import MovieDocument
class MovieDocumentSerializer(DocumentSerializer):
"""Serializer for the document."""
class Meta(object):
"""Meta options."""
# Specify the correspondent document class
document = MovieDocument
# List the serializer fields. Note, that the order of the fields
# is preserved in the ViewSet.
fields = (
'id',
'title',
'summary',
'people',
'genres',
)
and then my views.py
from django_elasticsearch_dsl_drf.constants import (
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_RANGE,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
LOOKUP_QUERY_EXCLUDE,
)
from django_elasticsearch_dsl_drf.filter_backends import (
FilteringFilterBackend,
IdsFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
)
from django_elasticsearch_dsl_drf.viewsets import BaseDocumentViewSet
from django_elasticsearch_dsl_drf.pagination import PageNumberPagination
from .documents import MovieDocument
from .serializers import MovieDocumentSerializer
class MovieDocumentView(BaseDocumentViewSet):
"""The MovieDocument view."""
document = MovieDocument
serializer_class = MovieDocumentSerializer
pagination_class = PageNumberPagination
lookup_field = 'id'
filter_backends = [
FilteringFilterBackend,
IdsFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
]
# Define search fields
search_fields = (
'title',
'summary',
)
# Define filter fields
filter_fields = {
'id': {
'field': 'id',
# Note, that we limit the lookups of id field in this example,
# to `range`, `in`, `gt`, `gte`, `lt` and `lte` filters.
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
],
},
'title': 'title.raw',
'genres': {
'field': 'genres',
# Note, that we limit the lookups of `genres` field
# to `terms, `prefix`, `wildcard`, `in` and
# `exclude` filters.
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
'genres.raw': {
'field': 'genres.raw',
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
}
# Define ordering fields
ordering_fields = {
'id': 'id',
'title': 'title.raw',
}
# Specify default ordering
ordering = ('id', 'title')
Lastly my urls.py is the following
from django.conf.urls import url, include
from rest_framework import routers
from .views import MovieDocumentView
router = routers.DefaultRouter()
router.register(r'movies', MovieDocumentView, base_name='moviedocument')
urlpatterns = [
url(r'^', include(router.urls)),
]
So, when i visit a url like http://localhost:8000/search/movies/ or http://localhost:8000/search/movies/?summary__contains=photography the error I mentioned above shows up.
Here is the stacktrace
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
/usr/local/lib/python3.7/dist-packages/django_elasticsearch_dsl_drf/filter_backends/search/historical.py:231: UserWarning: SearchFilterBackend is deprecated. Switch to `CompoundSearchFilterBackend`.
self.__class__.__name__
GET http://localhost:9200/search_movies/doc/_search [status:400 request:0.013s]
Internal Server Error: /search/movies/
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/usr/local/lib/python3.7/dist-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.7/dist-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.7/dist-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/er/.local/lib/python3.7/site-packages/rest_framework/viewsets.py", line 103, in view
return self.dispatch(request, *args, **kwargs)
File "/home/er/.local/lib/python3.7/site-packages/rest_framework/views.py", line 483, in dispatch
response = self.handle_exception(exc)
File "/home/er/.local/lib/python3.7/site-packages/rest_framework/views.py", line 443, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/er/.local/lib/python3.7/site-packages/rest_framework/views.py", line 480, in dispatch
response = handler(request, *args, **kwargs)
File "/home/er/.local/lib/python3.7/site-packages/rest_framework/mixins.py", line 48, in list
return Response(serializer.data)
File "/home/er/.local/lib/python3.7/site-packages/rest_framework/serializers.py", line 765, in data
ret = super(ListSerializer, self).data
File "/home/er/.local/lib/python3.7/site-packages/rest_framework/serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "/home/er/.local/lib/python3.7/site-packages/rest_framework/serializers.py", line 683, in to_representation
self.child.to_representation(item) for item in iterable
File "/home/er/.local/lib/python3.7/site-packages/elasticsearch_dsl/search.py", line 329, in __iter__
return iter(self.execute())
File "/home/er/.local/lib/python3.7/site-packages/elasticsearch_dsl/search.py", line 706, in execute
**self._params
File "/home/er/.local/lib/python3.7/site-packages/elasticsearch/client/utils.py", line 84, in _wrapped
return func(*args, params=params, **kwargs)
File "/home/er/.local/lib/python3.7/site-packages/elasticsearch/client/__init__.py", line 844, in search
"GET", _make_path(index, doc_type, "_search"), params=params, body=body
File "/home/er/.local/lib/python3.7/site-packages/elasticsearch/transport.py", line 353, in perform_request
timeout=timeout,
File "/home/er/.local/lib/python3.7/site-packages/elasticsearch/connection/http_urllib3.py", line 236, in perform_request
self._raise_error(response.status, raw_data)
File "/home/er/.local/lib/python3.7/site-packages/elasticsearch/connection/base.py", line 162, in _raise_error
status_code, error_message, additional_info
elasticsearch.exceptions.RequestError: RequestError(400, 'search_phase_execution_exception', 'Fielddata is disabled on text fields by default. Set fielddata=true on [title.raw] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead.')
[07/Aug/2019 11:03:38] "GET /search/movies/?summary__contains=photography HTTP/1.1" 500 154541
What you're supposed to do is to use KeywordField instead of StringField with keyword analyzer:
title = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.KeywordField(), <---- change this
}
)

API Root doesn't have has_permissions with JWT_Authentication

Trying to implement djangorestframework_simplejwt in accordance with DRF. After implementing everything based on: https://simpleisbetterthancomplex.com/tutorial/2018/12/19/how-to-use-jwt-authentication-with-django-rest-framework.html and when I'm logged in on localhost:8000, the API Root view is unavailable and the error is an attribute error.
'JWTAuthentication' object has no attribute 'has_permission'
When I view the ModelViewSets themselves, they appear perfectly fine. It's just the API Root itself. When I logout and try to access the API Root, the page loads perfectly fine returning HTTP 403.
Am I not supposed to access the API root when logged in or is there a loophole that I can implement (or extend) in views.py?
Edit:
Internal Server Error: /api/
Traceback (most recent call last):
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\core\handlers\exception.py", line 3
4, in inner
response = get_response(request)
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\core\handlers\base.py", line 115, i
n _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\core\handlers\base.py", line 113, i
n _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\views\decorators\csrf.py", line 54,
in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\django\views\generic\base.py", line 71, in
view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 495, in dis
patch
response = self.handle_exception(exc)
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 455, in han
dle_exception
self.raise_uncaught_exception(exc)
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 483, in dis
patch
self.initial(request, *args, **kwargs)
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 401, in ini
tial
self.check_permissions(request)
File "C:\Users\yoom\Code\test\qrveltest\venv\lib\site-packages\rest_framework\views.py", line 334, in che
ck_permissions
if not permission.has_permission(request, self):
AttributeError: 'JWTAuthentication' object has no attribute 'has_permission'
[19/Jun/2019 14:52:38] "GET /api/ HTTP/1.1" 500 95529
Here's the views.py:
from django.views.generic import ListView
from rest_framework import viewsets
from .serializers import *
from django_filters import rest_framework as filters
from rest_framework.permissions import IsAuthenticated
class HomePageView(ListView):
model = Test
template_name = 'home.html'
class UserViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated, )
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_fields = ('username', 'email')
class TestViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated, )
queryset = Test.objects.all()
serializer_class = TestSerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_fields = ('id', 'author')
def get_queryset(self):
queryset = Test.objects.all()
username = self.request.user
if username is not None:
queryset = queryset.filter(author__username=username)
return queryset
and urls.py:
from django.urls import path, include
from rest_framework import routers
from .views import *
from rest_framework_simplejwt import views as jwt_views
router = routers.DefaultRouter()
router.register('users', UserViewSet)
router.register('test', TestViewSet)
urlpatterns = [
path('', HomePageView.as_view(), name='home'),
path('api/', include(router.urls)),
path('api/token/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
]
I had the same issue and solved thanks for the comments. If anyone else is having this issue I'll write it here for you. Most likely an error in your settings be sure to add JWT under Authentication default and not Permission e.g.:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}

None type error in Django rest RegisterView

I am using Django RestFramework's RegisterView for the registration API in my project. I use a custom adapter as well, it is as follows.
class CustomAccountAdapter(DefaultAccountAdapter):
"""
Override all_auth's default adapter
"""
def send_confirmation_mail(self, request, emailconfirmation, signup):
# current_site = get_current_site(request)
promo_code = emailconfirmation.email_address.user.promo_code
activate_url = "%s/#/verifyEmail/%s/" % (
settings.FRONTEND_HOSTNAME,
emailconfirmation.key
)
if promo_code:
activate_url = "%s/#/verifyEmail/%s/?promo_code=%s" % (
settings.FRONTEND_HOSTNAME,
emailconfirmation.key,
promo_code
)
ctx = {
"user": emailconfirmation.email_address.user,
"activate_url": activate_url,
"current_site": settings.FRONTEND_HOSTNAME
}
if signup:
email_template = 'account/email/email_confirmation_signup'
else:
email_template = 'account/email/email_confirmation'
self.send_mail(email_template,
emailconfirmation.email_address.email,
ctx)
I get an error while the sending the confirmation mail to the newly registered user.The error is below:
File
"/home/ubuntu/fizprod_env/local/lib/python2.7/site-packages/django/core/mail/message.py",
line 283, in send
return self.get_connection(fail_silently).send_messages([self]) File
"/home/ubuntu/fizprod_env/local/lib/python2.7/site-packages/django/core/mail/backends/smtp.py",
line 99, in send_messages
sent = self._send(message) File "/home/ubuntu/fizprod_env/local/lib/python2.7/site-packages/django/core/mail/backends/smtp.py",
line 110, in _send
from_email = sanitize_address(email_message.from_email, email_message.encoding) File
"/home/ubuntu/fizprod_env/local/lib/python2.7/site-packages/django/core/mail/message.py",
line 105, in sanitize_address
nm, addr = addr TypeError: 'NoneType' object is not iterable
Can anyone tell me what is the error and how it's happening? I use Django 1.7, Python 2.7, Django REST 3.1.1.

Extending django User django-rest_framework gives me KeyError

I'm new to django rest_framework and have and issue, i've extended the auth_user as per the django docs, but is giving me a hard time...
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
national_id = models.CharField(max_length=10, blank=True, null=True)
mobile = models.CharField(max_length=10)
pin = models.IntegerField()
pattern = models.IntegerField(blank=True, null=True)
fingerprint = models.CharField(max_length=45, blank=True, null=True)
class Meta:
managed = False
db_table = 'user_profile'
serializers.py
class UserSerializer(serializers.ModelSerializer):
national_id = serializers.CharField(source='userprofile.national_id', allow_null=True, required=False)
mobile = serializers.CharField(source='userprofile.mobile')
pin = serializers.IntegerField(source='userprofile.pin', write_only=True)
pattern = serializers.IntegerField(source='userprofile.pattern', write_only=True)
fingerprint = serializers.CharField(source='userprofile.fingerprint', write_only=True, allow_null=True, required=False)
class Meta:
model = User
fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'national_id', 'mobile', 'pin', 'pattern', 'fingerprint')
write_only_fields = ('password',)
read_only_fields = ('last_login', 'is_superuser', 'is_staff', 'is_active', 'date_joined')
def create(self, validated_data):
user = User(
username=validated_data['username'],
first_name=validated_data['first_name'],
last_name=validated_data['last_name'],
email=validated_data['email'],
)
user.set_password(validated_data['password'])
user.save()
userprofile = UserProfile(
user=user,
national_id=validated_data['national_id'],
mobile=validated_data['mobile'],
pin=validated_data['pin'],
pattern=validated_data['pattern'],
fingerprint=validated_data['fingerprint'],
)
userprofile.save()
return user
views.py
class UserView(viewsets.ModelViewSet):
serializer_class = UserSerializer
queryset = get_user_model().objects
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from rest_framework.routers import DefaultRouter
from restful.views import *
router = DefaultRouter()
router.register(r'availability-notification', AvailabiltyNotificationView)
router.register(r'bank', BankView)
router.register(r'recipient', RecipientView)
router.register(r'user', UserView)
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^admin/', admin.site.urls),
but keeps giving me:
Environment:
Request Method: POST Request URL: http://localhost:8000/user/
Django Version: 1.10.2 Python Version: 3.5.2 Installed Applications:
['django.contrib.admin', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.staticfiles',
'rest_framework', 'restful'] Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\exception.py"
in inner
39. response = get_response(request)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py"
in _get_response
187. response = self.process_exception_by_middleware(e, request)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py"
in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\views\decorators\csrf.py"
in wrapped_view
58. return view_func(*args, **kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\viewsets.py"
in view
87. return self.dispatch(request, *args, **kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py"
in dispatch
474. response = self.handle_exception(exc)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py"
in handle_exception
434. self.raise_uncaught_exception(exc)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py"
in dispatch
471. response = handler(request, *args, **kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\mixins.py"
in create
21. self.perform_create(serializer)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\mixins.py"
in perform_create
26. serializer.save()
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\serializers.py"
in save
192. self.instance = self.create(validated_data)
File "C:\Users\echavez\Source\ws\restful\serializers.py" in create
45. national_id=validated_data['national_id'],
Exception Type: KeyError at /user/ Exception Value: 'national_id'
I know this is a newbie question, but, i really need help!
Thanks in advance.
You are getting profile data in wrong way.
validated_data is a dictionary of user and profile data which you are going to save separately.
Get it like this.
profile_data = validated_data.pop('userprofile')
Note that we poped userprofile data so now you have left only user data in validated_data. So a complete flow will look like below
profile_data = validated_data.pop('userprofile')
user = User.objects.create(**validated_data)
UserProfile.objects.create(user=user, **profile_data)
return user
Take a look here
http://www.django-rest-framework.org/api-guide/serializers/#writable-nested-representations
Thanks to LaL ZaDa who pointed me in the right direction, my code finally looks like this and works:
serializers.py
class UserSerializer(serializers.ModelSerializer):
national_id = serializers.CharField(source='userprofile.national_id', allow_null=True, required=False)
mobile = serializers.CharField(source='userprofile.mobile')
pin = serializers.IntegerField(source='userprofile.pin', write_only=True)
pattern = serializers.IntegerField(source='userprofile.pattern', write_only=True)
fingerprint = serializers.CharField(source='userprofile.fingerprint', write_only=True, allow_null=True, required=False)
bank_accounts = UserBankAccountSerializer(many=True)
class Meta:
model = User
fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'national_id', 'mobile', 'pin', 'pattern', 'fingerprint', 'bank_accounts')
write_only_fields = ('password',)
read_only_fields = ('last_login', 'is_superuser', 'is_staff', 'is_active', 'date_joined')
def create(self, validated_data):
user = User(
username=validated_data['username'],
first_name=validated_data['first_name'],
last_name=validated_data['last_name'],
email=validated_data['email'],
)
user.set_password(validated_data['password'])
user.save()
profile_data = validated_data.pop('userprofile')
userprofile = UserProfile(
user=user,
national_id=profile_data['national_id'],
mobile=profile_data['mobile'],
pin=profile_data['pin'],
pattern=profile_data['pattern'],
fingerprint=profile_data['fingerprint'],
)
userprofile.save()
return user
Cause, this is not exactly a nested model (the bank_accounts, are nested), so when i do like this:
profile_data = validated_data.pop('userprofile')
user = User.objects.create(**validated_data)
UserProfile.objects.create(user=user, **userprofile)
return user
was throwing me...
Environment:
Request Method: POST Request URL: http://localhost:8000/user/
Django Version: 1.10.2 Python Version: 3.5.2 Installed Applications:
['django.contrib.admin', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.staticfiles',
'rest_framework', 'restful'] Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\exception.py"
in inner
39. response = get_response(request)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py"
in _get_response
187. response = self.process_exception_by_middleware(e, request)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py"
in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\views\decorators\csrf.py"
in wrapped_view
58. return view_func(*args, **kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\viewsets.py"
in view
87. return self.dispatch(request, *args, **kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py"
in dispatch
474. response = self.handle_exception(exc)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py"
in handle_exception
434. self.raise_uncaught_exception(exc)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py"
in dispatch
471. response = handler(request, *args, **kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\mixins.py"
in create
21. self.perform_create(serializer)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\mixins.py"
in perform_create
26. serializer.save()
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\serializers.py"
in save
192. self.instance = self.create(validated_data)
File "C:\Users\echavez\Source\ws\restful\serializers.py" in create
49. user = User.objects.create(**validated_data)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\manager.py"
in manager_method
85. return getattr(self.get_queryset(), name)(*args, **kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\query.py"
in create
397. obj = self.model(**kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\contrib\auth\base_user.py"
in init
68. super(AbstractBaseUser, self).init(*args, **kwargs)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\base.py"
in init
550. setattr(self, prop, kwargs[prop])
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\fields\related_descriptors.py"
in set
500. manager.set(value)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\fields\related_descriptors.py"
in set
687. self.add(*objs, bulk=bulk)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\fields\related_descriptors.py"
in add
597. self.field.name: self.instance,
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\query.py"
in update
637. rows = query.get_compiler(self.db).execute_sql(CURSOR)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\sql\compiler.py"
in execute_sql
1148. cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\sql\compiler.py"
in execute_sql
824. sql, params = self.as_sql()
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\sql\compiler.py"
in as_sql
1102. val.prepare_database_save(field),
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\base.py"
in prepare_database_save
999. raise ValueError("Unsaved model instance %r cannot be used in an ORM query." % self)
Exception Type: ValueError at /user/ Exception Value: Unsaved model
instance cannot be used in an ORM query.
Now i'll finish the create to include the nested one and the update and delete...
Thanks LaL

FormWizard and saving data

im trying to use django formWizard, all is fine, but im getting an error in the last step after submit
Traceback (most recent call last):
File "/home/vacantes/webapps/django/lib/python2.6/django/core/handlers/base.py", line 100, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/home/vacantes/webapps/django/lib/python2.6/django/utils/decorators.py", line 21, in _wrapper
return decorator(bound_func)(*args, **kwargs)
File "/home/vacantes/webapps/django/lib/python2.6/django/utils/decorators.py", line 76, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/home/vacantes/webapps/django/lib/python2.6/django/utils/decorators.py", line 17, in bound_func
return func(self, *args2, **kwargs2)
File "/home/vacantes/webapps/django/lib/python2.6/django/contrib/formtools/wizard.py", line 101, in __call__
return self.done(request, final_form_list)
File "/home/vacantes/webapps/django/hay_vacantes/curriculums/forms.py", line 56, in done
website = data['website']
TypeError: __init__() got an unexpected keyword argument 'website'
i dont know where is the problem, in my Model i have a website field, but ... why the error?
model.py
class Generales(models.Model):
usuario = models.OneToOneField(User,unique=True)
.....
estado_civil = models.SmallIntegerField(max_length=1,choices=CIVIL)
website = models.URLField(verbose_name='Website', verify_exists=False,null=True,blank=True)
and in my forms:
forms.py
#others forms
.....
class ContactWizard(FormWizard):
def done(self, request, form_list):
data = {}
for form in form_list:
data.update(form.cleaned_data)
generales = Generales(
usuario = request.user.id,
documento_identidad = data['documento_identidad'],
tipo = data['tipo'],
tel_fijo = data['tel_fijo'],
celular = data['celular'],
foto = data['foto'],
sexo = data['sexo'],
direccion = data['direccion'],
codigo_postal = data['codigo_postal'],
pais = data['pais'],
ciudad = data['ciudad'],
fecha_nacimiento = data['fecha_nacimiento'],
estado_civil = data['estado_civil'],
website = data['website']
)
generales.save()
# others forms
.....
return HttpResponseRedirect('/panel/completo/')
EDIT
urls.py
from vacantes.curriculums.forms import Generales,Areas,Experiencia,Referencias,ContactWizard
urlpatterns = patterns('',
url(r'^completar/$', ContactWizard([Generales, Areas,Experiencia,Referencias])),
)
i dont know if im saving the data like formwizard need, but im trying.
any idea about the error?
thanks
As i have already used FormWizard in my app, the keys of submitted data are not 'website' or 'estado_civil',... but in the form "< form_number>-< field_name>". For example: '0-website' if the field 'website' is in the first form, '1-website' if it is in the second form and so on.
You can print out the whole submitted data dictionary to check that.