How to Access Current User from Django to React? - python

I am developing a system where a user logs in and they can use the features of our service. We have used Django Authentication to make the User and Login backend.
This is the custom User model in my models.py -
class UserDef(AbstractUser):
def __str__(self):
return self.first_name + self.last_name
employeeId = models.IntegerField(unique=True)
email_address = models.EmailField()
first_name = models.CharField(max_length=256)
last_name = models.CharField(max_length=256)
USER_TYPES = [('1',"Admin"), ('2',"Director"), ('3',"Sr. Manager"), ('4',"Manager") , ('5',"Sr. Engineer"), ('6',"Assistant Regional Manager"), ('7',"Assistant to the Regional Manager")]
user_type = models.CharField(max_length=2048, choices=USER_TYPES)
created_at = models.DateTimeField(auto_now_add=True)
This in itself works really well and I was able to access all data as needed. I am writing my front-end in React though. Which means there's a certain disconnect between the templates html file and the actual React.js code. Which means I can't simply send the employeeId or some other attribute as context. Does anyone know how I can extract that User information from the Django DB (which we have connected to an RDS-MySQL server) and display it in my React app.

If the user is already logged in and a sessionID has been generated. You could just create an endpoint through where you can fetch the current user and then make a call to the endpoint in your React frontend.
#api_view(['GET'])
def current_user(request):
user = request.user
return Response({
'username' : user.username,
'firstname' : user.first_name,
'employeeID' : user.employeeId,
# and so on...
})
You could obviously, always use a serializer to ease the process.

Related

How to send an email that doesn't need triggering a specific url?

I'm trying to build an automated email system for ecommerce purposes, So, I wanna send an email if a user is not registered, with the tracking_no whenever we have assigned a tracking_no for an OrderItem, I don't understand how I would be able to put this in a view function because it'll never get triggered if no one tries to access the url connected to the view, would I need to access the admin panel url for OrderItem save function? So that whenever the admin assigns a tracking number and saves the form, a function checks up if there's an assigned number and sends out the email to the Customer. If so how would I solve this?
#Model
#Customer is someone who is not registered
class Customer(models.Model):
email = models.EmailField(max_length=100)
class Order(models.Model):
customer = models.ForeignKey(Customer)
class OrderItem(models.Model):
order = models.ForeignKey(Order)
tracking_no = models.CharField(max_length=300, null=True, blank=True)
#Email
subject = "tracking_no"
html_message = render_to_string('emails/tracking_no.html', {'tracking_no': tracking_no})
send_mail()

Authentication and Authorization with Django GraphQL JWT and Graphene Relay

I would like to ask how I can do authentication and query tags limited to a specific user (owner) using Graphen Relay and Django JWT.
Here is my Model:
class Tag(models.Model):
"""Tag to be used for a objective"""
name = models.CharField(max_length=255)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name='tag',
on_delete=models.CASCADE,
)
Here is my Schema code:
class TagNode(DjangoObjectType):
class Meta:
model = Tag
filter_fields = ['name']
interfaces = (relay.Node,)
Here is my Query:
class Query(graphene.ObjectType):
tag = relay.Node.Field(TagNode)
all_tags = DjangoFilterConnectionField(TagNode)
def resolve_all_tags(self, info):
# context will reference to the Django request
print(info.context.user)
if not info.context.user.is_authenticated:
return Tag.objects.none()
else:
return Tag.objects.filter(user=info.context.user)
Here is the document for Django JWT: https://github.com/flavors/django-graphql-jwt but I do not know how to get the user (already use info.context.user) but it does not work,
when I tried to add Authorization (JWT token) in the header or as an argument. It also does not work.
Basically you are doing everything correctly and your user should be fetched successfully.
I've just checked and it works in my case, I use JWT like a cookie but it doesn't matter.
Had you authorized your user when tried to get tags?
Because regarding JWT you need to authorize your user and receive the JWT token. Only after that the real user will be presented in the request when you call the tags query. Otherwise the user will be anonymous.

django login using class based for custom user

here is my user model.
class User (models.Model):
username = models.CharField(max_length=50)
# token = models.CharField(max_length=50)
email_id = models.EmailField(max_length=50)
password = models.CharField(max_length=50)
is_deleted = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
updated_at = models.DateTimeField(auto_now_add=True, blank=True)
and here is my views for creating user
class UserView(APIView):
def post(self,request):
try:
# RequestOverwrite().overWrite(request, {'token':'string'})
user_data = UserDetailSerializer(data=request.data)
if not(user_data.is_valid()):
return Response(user_data.errors)
user_data.save()
return Response("user created successfully",status=status.HTTP_201_CREATED)
except Exception as err:
print(err)
return Response("Error while creating user")
now what i want to do is to create a token when i post a user and that token is used later for login.
also i want to validate user if it exist in database then make user authenticate.
what should i do..?any suggestion
below is my serializers.py
class UserDetailSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id','username','email_id','password','is_deleted','created_at','updated_at')
extra_kwargs = {
'password': {
'required':True,
'error_messages':{
'required':"Please fill this field",
}
}
}
First and foremost, it seems you are defining a custom user that is not in any way connected the Django auth user. It is a very very bad idea and will be difficult to get it work with most Django features. You can check out how to customize the existing user if you really need to.
As for user authentication, using the DRF Token Authentication, the flow is this way:
Client sends request to create user
If user is created successfully, it requests for an authentication token using the user's login and password
The backend verifies user's credentials and issues a token
Client makes subsequent requests with the token
If token expires or user logs out, repeat 2-4
Check out how to do these in DRF's TokenAuthentication documentation.
Your question is not very specific so I'm not sure what sort answer you are expecting but following these steps should get you going.
Token creation should be realized in model User. You can set default value to token field.
Add parameter default to User model token field:
token = models.CharField(default=tokenGenerator, max_length=50)
tokenGenerator should be some function that returns some generated token.
Secondly UserDetailSerializer should be edited to get token if it's necessary but not required.
class UserDetailSerializer(serializers.ModelSerializer):
# You can also provide this default function like in model field
# for this token field
# default=tokenGenerator
token = serializers.CharField(max_length=50, required=False)
class Meta:
model = User
fields = (..., 'token')
extra_kwargs = ...
Now your model gets generated token for newly created User.
User should be auto logged in after registration but it's not that simple.
You need to specify how do you want to communicate with API. You want token so i guess that front should request api and token should be used from cookies.
If you send request from browser eg. jQuery you need to get response with generated token and save it in cookies. Your post response in DRF:
return Response({'token': user_data.get('token')},status=status.HTTP_201_CREATED)
And now you have some more steps:
Attach token to every browser request which requests API
Create authentication class to validate every request checks for correct token
...
Now, if you read this you realize that it needs some work. If you know that and you intentionally want to create this, you need to create mentioned view authentication class.
Else try to use libs like oauth for django. That will provide you ready classes for token management.
Also as #Ken4scholars mentioned, try to use Django User model. It have good methods for validation etc. without make this done manually.

Manipulate Request data of TastyPie and Django API

I'm writing an application with django-tastypie and following are my models.py and resource.py files.
Models.py:
import uuid
from django.db import models
class User(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=50, null=False)
email = models.EmailField(max_length=254, null=False)
password = models.CharField(max_length=100, null=False)
role = models.CharField(max_length=16, default='basic', null=False)
def __unicode__(self):
return self.name, self.email
Resources.py:
from tastypie.resources import ModelResource
from tastypie.authorization import Authorization
from api.models import User
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'user'
authorization = Authorization()
excludes = ['password']
#allowed_methods = ['get']
Now the thing is that whenever I hit an API end point from postman, the user is created directly. Now what I don't understand is that whether the request data goes into resources and then into database or directly into the database? Actually, the thing is that I need to apply some changes to the data before it is stored in the database, like hashing the password and then storing the object in the database. I'm new to django, so how can I achieve that?
Like in Flask, we can do something like:
#user.route('/users', methods=['POST'])
def create_user(user_id):
data = request.get_json(force=True)
# do all the changes we want
user = User(data)
db.session.add(user)
db.session.commit()
Now if any request comes at '/users' endpoint, we can get it's data in the 'data' variable and then whatever changes we want before storing in the database. But how to do that in django with tastypie.
Any help would be appreciated
If you have to massage data before entering into database then Tastypie has the notion of hydrate and dehydrate methods.
Check that. Here is reference hydrate and dehydrate
In every web framework the data that sent with the request passed to the api endpoint through some mechanism and the same thing happens in Tastypie (you can read about it in Tastypie documentation under Flow Through The Request/Response Cycle).
If you want to change the data that you sending/receiving read about Hydrate/Dehydrate, in your case you want to use dehydrate on user password but I recommend you to save the effort and instead use custom user model by inheriting from AbstractUser, that way you can get hashed password by default when User object is saved to your DB.

In django, how can I link a model with a user. I'd like the user to add information about their company website and name

I want the users, once they are logged in, to be able to add information about their company including website, name, logo, etc.
I already have this model
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, unique=True)
comp_name = models.CharField(max_length=120,default='', blank=True)
comp_site = models.URLField(default='', blank=True)
comp_logo = models.ImageField(default='', blank=True, upload_to='img/logos/')
in my views.py I have this:
if form1.is_valid():
saveInfo = form1.save(commit=False)
comp_name = form1.cleaned_data.get("comp_name")
comp_site = form1.cleaned_data.get("comp_site")
comp_logo = form1.cleaned_data.get("comp_logo")
saveInfo.user = form1.user
saveInfo.save()
return redirect('/profil/')
What I'd like is that the program would automatically detects which user is currently logged in, and set the user field to that user.
How could I do this?
The request attribute sent with any Django specifies the current user.
def myview(request):
current_user = request.user
You can check if the user is logged in using the request.user.is_authenticated() method. What I would do here is redirect the login view to the view with your form. This should automatically happen if you are using #login_required on the form view.
As an aside, if you are extending the User model, you should use OneToOneField instead of ForiegnKey. Use ForiegnKeyonly if each user can have multiple companies.
if form1.is_valid():
saveInfo = form1.save(commit=False)
comp_name = form1.cleaned_data.get("comp_name")
comp_site = form1.cleaned_data.get("comp_site")
comp_logo = form1.cleaned_data.get("comp_logo")
saveInfo.user = request.user #<--- the authenticated user bound to the current request
saveInfo.save()
return redirect('/profil/')
request.user is the current user who is bound to the current request. You must (probably you already do) check if user is authenticated etc..
You can associate the users to a model using one to one field as shown below
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
bio = models.TextField()
organisation = models.CharField(max_length=300, default="")
country = models.CharField(max_length=50, default="")
display_pic = models.ImageField(upload_to="authors/profile", default="")
You can then get their info of user using 'Profile' and 'User'

Categories