How to generate Email Automatically ,After Registration In Django Rest Framework? - django

I have A models.py as this
models.py
class User(AbstractUser, BaseModel):
full_name = models.CharField(max_length=64)
addresss=models.CharField(max_length=40)
phoneno=models.IntegerField(null=True, blank=True)
email=models.EmailField()
password=models.CharField(max_length=40)
re_password=models.CharField(max_length=40)
gender=models.IntegerField(choices=gender_choice,default='0')
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('full_name','id','addresss','phoneno','email','gender')
views.py
class StudentViewset(viewsets.ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
http_methods = ['get', 'post','put','delete']
def create(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
row = serializer.data
user=User.objects.get_or_create(
defaults={'full_name':row['user']['full_name'],'addresss':row['addresss'],
'phoneno':row['phoneno'],'password':row['password'] ,'re_password':row[['re_password'],
'gender':row['gender'] ,'username':username})
My Question:
After Registering Student, I want to generate an email like his/her(address#gmail.com).
How can i do This ?

Related

Updating Profile image of a UserProfile linked to a user with OneToOne Relations

I was able to automaticcaly create a userProfile everytime a user is created but I want to be able to modify somefields in the userprofile.
So my Model.py
def upload_path(instance,filename):
return 'users/avatars/{0}/{1}'.format(instance.user.username, filename)
class UserProfile(models.Model):
user= models.OneToOneField(User,on_delete=models.CASCADE, related_name='userprofile')
Profileimage= models.ImageField(upload_to=upload_path, blank=True, null=True, default='user/avatar.jpeg')
def __str__(self):
return self.user.username
# receiver(post_save,sender=User)
def create_user_profile(sender,instance,created,**kwargs):
if created:
UserProfile.objects.create(user=instance)
My Serializer.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields =['id', 'username','password','email']
extra_kwargs={'password':{'write_only':True, 'required':True}}
def create(self,validated_data):
user =User.objects.create_user(**validated_data)
Token.objects.create(user=user)
return user
class UserProfileSerializer(serializers.ModelSerializer):
user=serializers.SlugRelatedField(queryset=models.User.objects.all(), slug_field='username')
class Meta:
model =models.UserProfile
#lookup_field = 'username'
fields= '__all__'
My view.py
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_field = 'username'
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
Using postman i get the error : django.db.utils.IntegrityError: UNIQUE constraint failed: api_userprofile.user_id
So after adding
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
I was able to change the fields that I want to.

How do i get a nested field to be read_only in modelserializer?

currently when i send a get request i get what i want. But when i do a Post it throws an error saying {"user": ["This field is required."]} even though i put 'user' in read_only_fields.
heres the code:
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email']
class SaleHistorySerializier(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = SaleHistory
fields =['id', 'user', 'product', 'date_bought']
read_only_fields = ('user',)
depth = 1
models.py
class SaleHistory(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='owner')
product = models.ForeignKey(SaleItems, on_delete=models.RESTRICT, default=None)
date_bought = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f' {self.product}, {self.user}, {self.id}'
api.py create part
class SaleHistoryVS(viewsets.ViewSet):
permission_classes = [permissions.IsAuthenticated]
def create(self, request):
serializer = SaleHistorySerializier(data=request.data, many=True)
if serializer.is_valid():
serializer.save(user = request.user)
return Response(serializer.data, status= status.HTTP_201_CREATED)
return Response(serializer.errors, status= status.HTTP_400_BAD_REQUEST)
how do i make it so that i get to create post request without having to user in my post data.
Replace user = UserSerializer() with user = UserSerializer(read_only=True)

django rest framework get request in serializer create method

I'm a student studying django rest framework
I tried to upload multiple file with form-data
when i send request like this in postman
error occurs and this is error message
images_data = self.context.get('request').request.FILES
AttributeError: 'NoneType' object has no attribute 'request'
this is model
class Post(models.Model):
text = models.CharField(max_length=5000)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class Image(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
image = models.FileField(blank=True)
And views
class AddPost(APIView):
serializer_class = PostSerializer
def post(self, request, format=None):
serializer = PostSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return JsonResponse({'status':status.HTTP_200_OK, 'message':"sucess", 'data':""})
serializers
class FileSerializer(serializers.ModelSerializer):
class Meta:
model = Image
fields = '__all__'
class PostSerializer(serializers.ModelSerializer):
images = FileSerializer(source='image_set', many=True, read_only=True)
class Meta:
model = Post
fields = ('id', 'text', 'owner', 'created_at', 'images')
def create(self, validated_data):
images_data = self.context.get('request').request.FILES
images_data = self.context.get('request').request.FILES
post = Post.objects.create(text=validated_data.get('text'),owner=validated_data.get('owner'))
for image_data in images_data.values():
Image.objects.create(post=post, image=image_data)
return post
i already saw this link
https://codeday.me/en/qa/20190306/12057.html
thanks for your help
Just pass context to your serializer in views.py
PostSerializer(data=request.data, context={'request': request})
And then you will be able to get request in the context in serializers.py
self.context.get('request')

Serializers vs views to retrieve object by foreign key field

I'd like to allow users to perform POST request to create a blog post, and to use the topic name instead of the topic id as an option.
A minimal model might look as follows.
models.py
class Topic(models.Model):
name = models.CharField(max_length=30, unique=True)
description = models.CharField(max_length=100)
class Post(models.Model):
name = models.CharField(max_length=30)
topic = models.ForeignKey(Topic, on_delete=models.PROTECT)
created_on = models.DateTimeField(blank=True, auto_now_add=True, editable=False)
Now there are 2 possible approaches that I've considered:
1) Keep the views simple.
views.py
class PostList(ListCreateAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
serializers.py
class PostSerializer(serializers.ModelSerializer):
topic_name = serializers.CharField()
class Meta:
model = Topic
fields = ('name', 'topic_name', 'created_on')
read_only_fields = ('created_on',)
def validate_topic_name(self, value):
"""Verify that the topic exists."""
if not Topic.objects.filter(name=value).exists():
raise serializers.ValidationError("Specified Topic Name does not exist!")
else:
return value
def create(self, validated_data):
"""Create a Post."""
topic_name = validated_data.pop('topic_name', None)
topic = Topic.objects.get(name=topic_name)
return Post.objects.create(topic=topic, **validated_data)
2) Keep the serializers simple.
views.py
class PostList(ListCreateAPIView):
queryset = Post.objects.all()
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if not serializer.is_valid():
return Response(
serializer.errors, status=status.HTTP_400_BAD_REQUEST)
topic = get_object_or_404(Topic, name=serializer.data['topic_name'])
post = Post.objects.create(
name=serializer.data['name'],
topic=topic)
return Response({'name': serializer.data['name'], 'description': serializer.data['topic_name']},
status=status.HTTP_201_CREATED)
serializers.py
class PostSerializer(serializers.ModelSerializer):
topic_name = serializers.CharField()
class Meta:
model = Topic
fields = ('name', 'topic_name', 'created_on')
read_only_fields = ('created_on',)
My question are:
Where should I put the complexity? In the serializer on in the views?
Is there a better way to proceed?
There's no need to put this complexity into your code at all, because this function is already provided by serializers.SlugRelatedField, which allows you to refer to a related field using a string instead of an id. Here's how it looks with your model:
views.py
class PostList(ListCreateAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
serializers.py
class PostSerializer(serializers.ModelSerializer):
topic = serializers.SlugRelatedField(slug_field='name',
queryset=Topic.objects.all())
class Meta:
model = Post
fields = '__all__'

Django Rest Framework: How to associate the object with the user when posting the object

I'm new to creating REST API so I might misunderstand something.
I'm creating REST API using Django Rest Framework. And I'm trying to create an object and send it from my mobile app.
However, API returns 400. I think it still cannot associate the object with the request user and I'm wondering how to do it.
models.py
class Item(models.Model):
item_name = models.CharField()
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
serializers.py
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('item_name', 'created_by')
and views.py
class ListItems(generics.ListCreateAPIView):
queryset = Item.objects.all()
serializer_class = ItemSerializer
What I want to know is how to associate the object with the request user when posting the object like as we do like
if form.is_valid():
item = form.save(commit=False)
item.created_by = request.user
item.save()
I think the easiest approach is like this:
class ItemSerializer(serializers.ModelSerializer):
created_by = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
Reference can be found here
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('item_name',)
class ListItems(generics.ListCreateAPIView):
...
def perform_create(self, serializer):
serializer.save(created_by=self.request.user)
you can do this way
One of the possible way to overwrite serializer_create method. As user is not associated with request.data first we need to make sure, this is write_only field and also need to assign current user from modelSerializer's self.context.request.user. Following addition should solve the problem.
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('item_name', 'created_by')
extra_kwargs = {'created_by': {'write_only': True}}
def create(self, validated_data):
item = Item(
item_name=validated_data['item_name'],
created_by=self.context.request.user
)
item.save()
return item
Reference link
It works for me
models.py
class Category(models.Model):
name = models.CharField('Category', max_length=200, unique=True, help_text='Name of the category')
slug = models.SlugField('Slug', max_length=100, db_index=True, unique=True, help_text='Name of the category in format URL')
def __str__(self):
return (self.name)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
serializers.py
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = [
'id', 'name', 'slug'
]
read_only_fields = [
'slug',
]
Finally, I get the user in the view, before to save the post.
views.py
class CategoryList(APIView):te a new category instance.
permission_classes = (IsAuthenticatedOrReadOnly,)
def get(self, request, format=None):
categories = Category.objects.all()
serializer = CategorySerializer(categories, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, format=None):
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
serializer.save(created_by=self.request.user)
Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)