Django: TokenAuthentication and AbstractBaseUser Errors - python

I am using Django 1.8.4 and Django rest framework 3.2.3. Because I want override "username" field I had to use "AbstractBaseUser"
The used model is:
class Users(AbstractBaseUser):
username = models.EmailField(max_length=75, null=False, blank=False, unique=True)
first_name = models.CharField(max_length=50, null=True, blank=True)
last_name = models.CharField(max_length=70, null=True, blank=True)
tel_number = models.IntegerField(null=True, blank=True)
address = models.CharField(max_length=250, null=True, blank=True)
user_image = models.ImageField(upload_to='user_avatar', blank=True, null=True)
date_time = models.DateTimeField(auto_now=True, null=True, blank=True)
activated = models.BooleanField(default=False)
def __unicode__(self):
return self.username
class Meta:
ordering = ['-id']
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['tel_number']
Now I want create new user with new token:
if request.method == 'POST':
serializer = UserSerializer(data=request.data)
data = {}
if serializer.is_valid():
user = serializer.save()
token, created = Token.objects.get_or_create(user=user)
data['token'] = token
data = serializer.data
return Response(data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
and my serializer is :
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = ('id', 'username', 'password', 'first_name', 'last_name', 'tel_number', 'address', 'user_image')
But I get this error on "Create Token Lines":
Cannot query "a#gmail.com": Must be "User" instance.

You are not passing the user instance to Token.
Can you try this:
In routers.py
from rest_framework import routers
from .viewsets import UserSeralizerViewSets
router = routers.DefaultRouter()
router.register(r'users', UserSeralizerViewSets)
In urls.py
from .routers import router
urlpatterns = [
url(r'^', include(router.urls)),
]
In viewsets.py
class UserSeralizerViewSets(viewsets.ModelViewSet):
serializer_class = UserSeralizer
queryset = Users.objects.all()
def create(self, request, *args, **kwargs):
data = {}
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
token, created = Token.objects.get_or_create(user=user)
data['token'] = token.key
return Response(data, status=status.HTTP_201_CREATED)

The answer of seenu s is well but i use this line in settings.py and worked .
AUTH_USER_MODEL = 'users.Users'
Users.Users is (myappname.mymodelname)
I find this on Django doc.

Related

Django,update the same row field in model getting data from serializer

I have this model:
class AgentDetail(MethodID):
first_name = models.CharField(max_length=50, blank=True, null=True, unique=True)
last_name = models.CharField(max_length=50, unique=True, null=True)
email = models.EmailField(null=False)
authen_method = models.ForeignKey(AuthMethodID, on_delete=models.CASCADE)
country_code = models.BigIntegerField(default=1)
mobile_number = models.BigIntegerField(null=False)
sms_provider = models.CharField(max_length=50, null=True)
active_status = models.BooleanField(default=True)
created_time = models.DateTimeField(default=now, editable=False)
created_by = models.CharField(max_length=50)
updated_time = models.DateTimeField(auto_now=True)
updated_by = models.CharField(max_length=50)
and this serializer:
class AgentSerializer(serializers.ModelSerializer):
class Meta:
model = AgentDetail
fields = [
"first_name",
"last_name",
"email",
"authen_method",
"mobile_number",
"sms_provider",
]
and this views.py:
#api_view(["POST"])
def create_agent(request):
if request.method == "POST":
serializer = AgentSerializer(data=request.data, many=False)
if serializer.is_valid():
serializer.save()
request_data = serializer.data
# AgentDetail.objects.update_or_create(
# created_by=request_data["first_name"] + request_data["last_name"],
# updated_by=request_data["first_name"] + request_data["last_name"],
# )
return Response(status=status.HTTP_200_OK)
error = Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
return error
As in serializer I'm not passing created_by field and I need that field gets value of first_name+last_name which are coming from serializer data.I'm new to DRF.
as said in docs you can pass additional attributes to save method.
views.py
#api_view(["POST"])
def create_agent(request):
if request.method == "POST":
serializer = AgentSerializer(data=request.data, many=False)
if serializer.is_valid():
request_data = serializer.validated_data
serializer.save(
created_by=request_data["first_name"] + request_data["last_name"],
updated_by=request_data["first_name"] + request_data["last_name"],
)
return Response(status=status.HTTP_200_OK)
error = Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
return error
you can access the validated_data in create method, and add any extra data you want.
serializer.py
class AgentSerializer(serializers.ModelSerializer):
...
def create(self, validated_data):
first_name = validated_data.get('first_name', '')
last_name = validated_data.get('last_name', '')
validated_data.update(dict(
created_by=first_name+last_name,
updated_by=first_name+last_name
))
return super().create(validated_data)

TypeError: method() takes 1 positional argument but 2 were given if i did register api

cant do work my register_api if i have view
class RegistrationUsersApi(viewsets.ModelViewSet):
permission_classes = [AllowAny]
def get(self, request):
queryset = User.objects.all()
serializer = UserSerializerView(queryset, many=True)
return Response(serializer.data)
def post(self, request):
serializer_class = SerializerUserRegistration(data=request.data)
data={}
if serializer_class.is_valid():
new_user = serializer_class.save()
data['response'] = 'Ура ты создал нового персонажа, героя, человека, или не создал?'
data['email'] = new_user.email
data['username'] = new_user.username
else:
serializer_class.errors
return Response(data)
and i have my serilizer
class SerializerUserRegistration(serializers.ModelSerializer):
password2 = serializers.CharField(style={'input_type': 'password'}, write_only=True)
class Meta:
model = User
fields = ['username', 'email', 'password', 'password2']
extra_kwargs = {
'password': {'write_only': True}
}
def save(self):
user = User(
email=self.validated_data['email'],
username=self.validated_data['username'],
)
password = self.validated_data['password']
password2 = self.validated_data['password2']
if password != password2:
raise serializers.ValidationError({'password': 'Password must match'})
user.set_password(password)
user.save()
return user
and my usermodel
class User(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
description = models.TextField(blank=True, null=True)
location = models.CharField(max_length=30, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
is_organizer = models.BooleanField(default=False)
info_car = models.CharField(max_length=30, blank=True, null=True)
first_name = models.CharField(max_length=30, blank=True, null=True)
second_name = models.CharField(max_length=30, blank=True, null=True)
def __str__(self):
return self.user.username
urls
urlpatterns = [
path('', views.MainIndexView.as_view(), name='index'),
path('registration/', views.RegistrationUsersApi, name='registration')
]
and my root urls
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('mainapp.urls')),
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path("api/accounts/", include("mainapp.urls")),
]
why my register doesnt work. i was try to post with postman
why does Python tell me I gave it two arguments, when I only gave one? and why i have that problem i dont know
when I wrote the question, I noticed that I have the wrong view, did not add as_view () on urls. path
and
My user model was with the same name as the standard one, which caused problems, I deleted my model and started using the standard one and everything began to work for me

File uploader is not showing in Swagger Django Rest-Framwork

I have created Rest API using Django rest-framework, when I am trying to test in with Swagger, it is not supporting FileField. in place of file uploader, it is showing text field.
Here What I did -
models.py
class Document(models.Model):
IS_DELETED = (
(True, True),
(False, False),
)
project = models.ForeignKey(Project, null=False, blank=False, on_delete=models.CASCADE)
document_file = models.FileField(upload_to=PROJECT_DOC_PATH, null=False, blank=False)
is_deleted = models.BooleanField(choices=IS_DELETED, default=False)
created_by = models.CharField(max_length=500, null=True, blank=True)
created_on = models.DateTimeField(null=False, blank=False, default=timezone.now)
updated_by = models.CharField(max_length=500, null=True, blank=True)
updated_on = models.DateTimeField(null=True, blank=True)
serializers.py
class DocumentSerializer(serializers.ModelSerializer):
class Meta:
model = DocumentTbl
fields = ('project','document_file')
views.py
#method_decorator(csrf_exempt, name='dispatch')
class Document(generics.CreateAPIView):
renderer_classes = (JSONRenderer,)
parser_classes = (FormParser, MultiPartParser,)
permission_classes = (permissions.AllowAny, IsAuthenticated)
serializer_class = DocumentSerializer
def post(self, request):
try:
serializer = DocumentSerializer(data=request.data)
if serializer.is_valid():
serializer.create(serializer.validated_data)
return Response({
messages.RESULT: messages.SUCCESS,
messages.MESSAGE: messages.SUCCESSFULLY_DATA_SAVE,
}, status=status.HTTP_200_OK)
else:
return Response({
messages.RESULT: messages.FAIL,
messages.RESPONSE_DATA: serializer.errors,
messages.MESSAGE: messages.INVALID_DATA,
}, status=status.HTTP_400_BAD_REQUEST)
except Exception as ex:
return Response({
messages.RESULT: messages.FAIL,
messages.MESSAGE: messages.SERVER_ERROR + ', due to {}'.format(str(ex)),
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
urls.py
urlpatterns = [
path('document/', Document.as_view(),name='document'),
]
req.txt
Python==3.x
Django==2.2.5
django-cors-headers==3.1.0
django-rest-swagger==2.2.0
djangorestframework==3.10.3
djangorestframework-simplejwt==4.3.0
I have tried Django REST Framework + Django REST Swagger + ImageField but didn't solve my issue.
Output
This is a known issue at Django-Rest-Swagger
you can refer to below url:
https://github.com/marcgibbons/django-rest-swagger/issues/647
the rootcause is Core api doesn't have a File type yet, it is marked as # LATER: File
see https://github.com/core-api/python-coreschema/blob/master/coreschema/schemas.py#L24

Many-to-one relationship in Django

I'm new to django thus the question.
This is my Location object,
class Location(models.Model):
country = models.CharField(max_length=255)
city = models.CharField(max_length=255, unique=True)
latitude = models.CharField(max_length=255)
longitude = models.CharField(max_length=255)
And this is my modified User object
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, max_length=255)
mobile = PhoneNumberField(null=True)
username = models.CharField(max_length=255, null=True)
full_name = models.CharField(max_length=255, blank=True, null=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
is_mobile_verified = models.BooleanField(default=False)
location = models.ForeignKey(Location, on_delete=models.SET_NULL, null=True)
This is the User Registration API view
class RegisterView(views.APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
subject = "Please Activate Your Account!"
token = self._generate()
link = HOST + PREFIX + str(user.id) + SUFFIX + token
message = 'Please use the following link to activate your account.\n\n{}'.format(link)
from_email = settings.EMAIL_HOST_USER
to_list = [user.email, 'melissa#gmail.com']
send_mail(subject, message, from_email, to_list, fail_silently=True)
Token.objects.create(user=user, token=token)
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
And this is the relevant url
url(r'^register/$', RegisterView.as_view(), name='register')
Now I want to modify this endpoint to take a location id as a path param and then add the logic in my UserCreation function that the user is added to the location as described by the id.
Can someone help me do this ?
You can do this way:
url(r'^register/(?P<location_id>[\w.-]+)/$', RegisterView.as_view(), name='regist
and then,
def post(self, request, *args, **kwargs):
self.location_id = kwargs.get('location_id', "any_default")
location = Location.objects.get(id=self.location_id)
# Now assign to user
if serializer.is_valid():
user = serializer.save()
user.location = location
user.save()

Django DRF serializer on PrimaryKeyRelatedField

Question about PrimaryKeyRelatedField serialization in Django DRF version 3.4.7.
models
class UserModel(AbstractEmailUser):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.email)
class Conversation(models.Model):
admin = models.ForeignKey('UserModel', db_index=True, related_name='admin_user')
patient = models.ForeignKey('UserModel', db_index=True)
subject = models.CharField(max_length=255, db_index=True)
user_reply = models.BooleanField(default=False)
admin_seen = models.BooleanField(default=False)
expire = models.DateTimeField()
conversation_type = models.ForeignKey('ConversationType', db_index=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.admin)
class ConversationMessages(models.Model):
text = models.TextField(db_index=True)
conversation = models.ForeignKey('Conversation', db_index=True, related_name='msg_conv')
user = models.ForeignKey('UserModel', db_index=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.user)
class ConversationFiles(models.Model):
message = models.ForeignKey('ConversationMessages', db_index=True, related_name='message')
file = models.FileField(upload_to='conversations', db_index=True)
def __str__(self):
return str(self.user)
Every model has related field for Rest Framework.
Logic is create conversation, then take ID from conversation and save message model.
serialize's
class MessagesSerializer(serializers.ModelSerializer):
text = serializers.CharField(required=False)
conversation = serializers.PrimaryKeyRelatedField(queryset=Conversation.objects.all(), required=False)
user = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all(), required=False)
class Meta:
model = ConversationMessages
class ConversationSerializer(serializers.ModelSerializer):
admin = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all(), required=False)
msg_conv = MessagesSerializer()
class Meta:
model = Conversation
def create(self, validated_data):
msg_conv = validated_data.pop('msg_conv', None)
admin_user = Conversation.objects.create(**validated_data)
ConversationMessages.objects.create(conversation_id=Conversation.objects.get(id=admin_user.id).id, **msg_conv)
return admin_user
Serializer is problem on POST method. Everything works great POST object create data in database, but problem is when serializer save object i get this message: 'RelatedManager' object has no attribute 'conversation'.
View
class ConversationView(APIView):
authentication_classes = (JSONWebTokenAuthentication,)
#parser_classes((FormParser, MultiPartParser, FileUploadParser))
def post(self, request):
admin = request.user.id
data = request.data
my_time = datetime.datetime.strptime('07/05/15', '%m/%d/%y')
my_time = my_time.replace(hour=23, minute=59)
data['admin'] = admin
data['expire'] = my_time
data['msg_conv']['user'] = admin
serializer = ConversationSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(data={'success': True, 'user': serializer.data}, status=status.HTTP_200_OK)
else:
return Response(data={'success': False, 'msg': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
POST json
{
"subject":"aloha",
"conversation_type":1,
"patient":3,
"msg_conv":{
"text":"ovo je neki teks"
}
}
Can't figure out how to return data from serializer to view.
Django version : 1.10.2
Python: 3.4.3
The issue is there:
class ConversationSerializer(serializers.ModelSerializer):
msg_conv = MessagesSerializer()
By doing this, you are saying that Conversation has a FK to Message. Therefore DRF tries to do the mapping and fails because it's the oposit.
You just need to add the many=True argument to let DRF knows this is a reversed FK.

Categories

Resources