I have Post model:
class Post(models.Model):
title = models.CharField(max_length=50)
text = models.CharField(max_length=1000)
published_date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
And a view:
#api_view(['GET', 'POST'])
def posts(request):
if request.method == 'GET':
post_list = Post.objects.all()
serializer = PostSerializer(post_list, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors)
And serializer:
class PostSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
author = UserSerializer(read_only=True)
category = CategorySerializer(read_only=True)
author_id = serializers.IntegerField(write_only=True)
category_id = serializers.IntegerField(write_only=True)
class Meta:
model = Post
fields = ('id', 'title', 'text', 'published_date', 'author', 'category', 'category_id', 'author_id')
I want to send POST request like {"title":"some title", "text":"some text", "category_id"=1}, so that author_id will be automatically current user id. How can I do this?
In the view, pass the current user to serializer.save() during the POST.
def posts(request):
if request.method == 'GET':
post_list = Post.objects.all()
serializer = PostSerializer(post_list, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
serializer.save(author=request.user)
^^^
return Response(serializer.data)
return Response(serializer.errors)
Related
In Model.py
class Item(models.Model):
item_id = models.AutoField(primary_key=True)
item_description = models.CharField(max_length=500)
quantity = models.IntegerField(default=0)
avg_rate = models.IntegerField(default=0)
category_id = models.ForeignKey(category, on_delete=models.CASCADE)
last_purchase_rate = models.IntegerField(default=0)
added_date = models.DateTimeField(auto_now=True)
custom_id = models.CharField(max_length=11, unique=True, blank=True)
def save(self, *args, **kwargs):
self.custom_id = f"ITM-{str(self.item_id).zfill(5)}"
super().save(*args, **kwargs)
In Serializer.py
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = '__all__'
def create(self, validated_data):
item = Item.objects.create(**validated_data)
item.custom_id = f"ITM-{str(item.item_id).zfill(5)}"
item.save()
return item
In view.py
#api_view(['GET', 'POST'])
def ItemsViewSet(request, format=None):
# GET.
if request.method == 'GET':
itemsdata = Item.objects.all()
serializer = ItemsSerializer(itemsdata, many=True)
return Response(serializer.data)
# POST.
if request.method == 'POST':
serializer = ItemsSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
SELECTED ITEM GET, PUT(UPDATE) & DELETE.
#api_view(['GET', 'PUT', 'DELETE'])
def items_detail(request, id):
# ID PICK POINT.
try:
itms = Item.objects.get(pk=id)
except itms.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
GET.
if request.method == 'GET':
serializer = ItemsSerializer(itms)
return Response(serializer.data)
# PUT.
elif request.method == 'PUT':
serializer = ItemsSerializer(itms, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# DELETE.
` elif request.method == 'DELETE':
itms.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
I want to set the Custom_ID in the format of 'ITM-00001', but currently, I am getting a Custom_ID of 'ITM-00None'. Additionally, this code also performs CRUD operations. I need the category_name to be displayed on the frontend instead of the category_ID.
NOTE: Using Python and Django rest framework current version. Database: MySQL
The concept is that I try to post or update a Case. The fields "title", "customer", "assigned_to"
and "created_by" is required. Also the "assigned_to" and "created_by", are foreign keys of model Employees with email field as unique.I get the validation error for "title" if it's null but for the others I get the "Duplicate entry" error. The rest of the requests for Employees and Customers are working great.Thanks everybody in advance.
Below you'll find the necessary code:
-----------MODELS------------------------------
class Employees(models.Model):
#auto increment id
email = models.EmailField(unique=True)
class Customers(models.Model):
#auto increment id
email = models.EmailField(unique=True, null=True, blank=True)
class Cases(models.Model):
#auto increment id
title = models.CharField(max_length=100)
assigned_to = models.ForeignKey(
Employees, on_delete=models.PROTECT, related_name='assignee')
created_by = models.ForeignKey(
Employees, on_delete=models.PROTECT, related_name='creator')
customer = models.ForeignKey(
Customers, on_delete=models.PROTECT, related_name='cases',null=True, blank=True)
-----------Serializers------------------------------
class SimpleEmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employees
fields = ['id', 'full_name', ]
read_only_fields=('full_name',)
full_name = serializers.SerializerMethodField(method_name='get_full_name')
def get_full_name(self, obj):
return '{} {}'.format(obj.first_name, obj.last_name)
class SimpleCustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customers
fields = ['id', 'full_name',]
read_only_fields=('full_name',)
full_name = serializers.SerializerMethodField( method_name='get_full_name')
def get_full_name(self, obj):
return '{} {}'.format(obj.first_name, obj.last_name)
class ViewUpdateCaseSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
class Meta:
model = Cases
fields = ['id', 'category', 'title', 'description', 'customer', 'assigned_to',
'created_by', 'priority', 'status', 'creation_date', 'start_date', 'resolved_date',
'due_date', 'comments', 'cost', 'earning_fixed','earning_percent', 'clear_earning',
'price_without_vat','price_with_vat']
customer = SimpleCustomerSerializer()
assigned_to = SimpleEmployeeSerializer()
created_by = SimpleEmployeeSerializer()
-----------Views------------------------------
#api_view(['GET', 'POST'])
def cases_list(request):
if request.method == 'GET':
queryset = Cases.objects.select_related('customer', 'assigned_to', 'created_by').all()
serializer = ViewUpdateCaseSerializer(queryset, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ViewUpdateCaseSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
#api_view(['GET', 'PUT', 'PATCH', 'DELETE'])
def case_detail(request, id):
case = get_object_or_404(Cases, pk=id)
if request.method == 'GET':
serializer = ViewUpdateCaseSerializer(case)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = ViewUpdateCaseSerializer(case, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
elif request.method == 'PATCH':
serializer = ViewUpdateCaseSerializer(case, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
print("patch serializer: ", serializer.data)
return Response(serializer.data)
elif request.method == 'DELETE':
case.delete()
return Response( status=status.HTTP_204_NO_CONTENT)
Finally except for the "Duplicate entry", I got 1 empty row to the Employee table on Mysql db and 1 empty row to the Customer table. How do I solve this kind of excemption?
How I can add data to form that user submitted ? I want the user to fill in the "name" and "done" in the form and automatically add "user" (creator) and "board"
code:
#views.py
#login_required(login_url='loginPage')
def taskAdd(request, pk):
board = Board.objects.filter(user=request.user).get(pk=pk)
form = AddTaskForm()
if request.method == "POST":
form = AddTaskForm(request.POST)
if form.is_valid():
form.initial['user'] = request.user
form.initial['board'] = board
# that doesn't seem to work....
form.save()
return redirect('insideBoard', pk)
context = {'form': form}
return render(request, 'tasks/taskAdd.html', context)
#forms.py
class AddTaskForm(ModelForm):
class Meta:
model = Task
fields = "__all__"
exclude = ('user', 'board',)
#models.py
class Board(models.Model):
title = models.CharField(max_length=50, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Task(models.Model):
title = models.CharField(max_length=200, null=True)
done = models.BooleanField(default=False, null=True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
board = models.ForeignKey(Board, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
You can edit the instance wrapped in the form:
from django.shortcuts import get_object_or_404
#login_required(login_url='loginPage')
def taskAdd(request, pk):
board = get_object_or_404(Board, user=request.user, pk=pk)
form = AddTaskForm()
if request.method == 'POST':
form = AddTaskForm(request.POST)
if form.is_valid():
form.instance.user = request.user
form.instance.board_id = pk
form.save()
return redirect('insideBoard', pk)
context = {'form': form}
return render(request, 'tasks/taskAdd.html', context)
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.
I have created an api where one can upload pic for profile along with rest of the details. My problem is that if one wants to change the pic, how can it be done.
At present, I am able to save pic for the first time.
models.py
class Profile(models.Model):
User = get_user_model()
branch = models.CharField(max_length=20, null=True)
year = models.IntegerField(null=True)
image = models.ImageField(upload_to="accounts/images/", null=True, blank=True)
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
primary_key=False,
null=True
)
views.py
class ProfileView(APIView):
permission_classes = (IsAuthenticated,)
serializer_class = ProfileSerializer
queryset = Profile.objects.all()
def post(self, request, format=None):
current_user = request.user
param = request.data
profile = Profile.objects.filter(user=current_user.pk)
if profile:
serializer = ProfileSerializer(profile, many=True)
return Response(serializer.data)
else:
serializer = ProfileSerializer(data=param)
if serializer.is_valid(raise_exception=True):
serializer.save(user=current_user)
new_data = serializer.data
return Response(new_data)
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
class ProfileView(APIView):
permission_classes = (IsAuthenticated,)
def post(self, request, format=None):
try:
# exist then update
profile = Profile.objects.get(user=request.user)
serializer = ProfileSerializer(profile, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
except Profile.DoesNotExist:
# not exist then create
serializer = ProfileSerializer(data=param)
if serializer.is_valid():
serializer.save(user=request.user)
return Response(serializer.data)
else:
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
or just use UpdateAPIView:
class ProfileView(UpdateAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = ProfileSerializer
queryset = Profile.objects.all()
Using:
class PostSerializer(serializers.ModelSerializer):
author = ExtUserSerializer(required=False, allow_null=True)
class Meta:
model = Post
field = ('title','description','rating','author')
def create(self, validated_data):
return Post.objects.create(**validated_data)
and
#api_view(['GET'])
def post_list(request, format=None):
if request.method == 'GET':
posts = Post.objects.all()
serializer = PostSerializer(posts, many=True)
return Response(serializer.data)
How to modify Serializer and view to fill field author automatically