How to update modified_by field with CurrentUserDefualt - django

i get this error when i am trying to update modified_by field
Tried to update field sales.CustomersTag.modified_by with a model instance, <SimpleLazyObject: <UserProfile: Admin>>. Use a value compatible with CharField.
this is my serializer.py:
class CustomersTagSerializer(serializers.ModelSerializer):
created_by = serializers.CharField(read_only=True, default=serializers.CurrentUserDefault())
modified_by = serializers.CharField(read_only=True, default=serializers.CurrentUserDefault())
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.modified_by = validated_data.get('modified_by', instance.modified_by)
instance.save()
return instance
class Meta:
model = models.CustomersTag
fields = (
'id',
'name',
'created_date',
'modified_date',
'created_by',
'modified_by',
)
and this my view.py:
class CustomerTagGetIdPutView(generics.RetrieveAPIView,
mixins.UpdateModelMixin):
permission_classes = (AllowAny,)
queryset = models.CustomersTag.objects.all()
serializer_class = CustomersTagSerializer
def get_object(self):
id = self.kwargs['id']
obj = generics.get_object_or_404(models.CustomersTag, id=id)
return obj
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
i tried alot to solve this problem but i can't .. any one can help me for this problem

If you're using Django REST Framework generic views and no overriding the behavior of methods like get_serializer or get_serializer_context, your serializer will receive a context object. This context object is a dictionary with the request and the view object.
That said, you can do this by overriding create() and update() in your serializer. For example:
class CustomersTagSerializer(serializers.ModelSerializer):
class Meta:
model = models.CustomersTag
fields = (
'id',
'name',
'created_date',
'modified_date',
'created_by',
'modified_by',
)
def create(self, validated_data):
user = self.context['request'].user
return models.CustomersTag.objects.create(
created_by=user, **validated_data)
def update(self, instance, validated_data):
user = self.context['request'].user
instance.name = validated_data.get('name', instance.name)
instance.modified_by = user
instance.save()
return instance
But maybe if you want to maintain a log history of editions in your models you could use a package like django-auditlog.

You can do this while calling save() in your model.
For example:
class CustomersTagSerializer(serializers.ModelSerializer):
created_by = models.ForeignKey(User, null=True, editable=False)
modified_by = models.ForeignKey(User, null=True, editable=False)
def save(self, *args, **kwargs):
user = get_current_user()
if user and user.is_authenticated():
self.modified_by = user
if not self.id:
self.created_by = user
super(CustomersTagSerializer, self).save(*args, **kwargs)

Related

Call for model field validation in the serializer

I will try to make a check for the uniqueness of the field at the validation level in the serializer and can not understand why the validator is not called at all.
models.py
class Vendor(models.Model):
active = models.BooleanField(default=False)
...
class VendorContacts(models.Model):
vendor = models.ForeignKey('Vendors', related_name='contacts', on_delete=models.CASCADE)
email = models.CharField(max_length=80, blank=True, null=True)
.....
serializer.py
class VendorContactCreateSerializer(serializers.ModelSerializer):
email = serializers.CharField(validators=[RegexValidator(regex=r'[^#]+#[^\.]+\..+',
message='Enter valid email address')])
vendor = serializers.PrimaryKeyRelatedField(queryset=Vendors.objects.all(), required=False, allow_null=True)
class Meta:
model = VendorContacts
fields = (.....
)
def create(self, validated_data):
.....
#some logic
def validate_email(self, value):
print('Start validation')
exist_contact = VendorContacts.objects.filter(email=value)
if exist_contact:
vc = get_object_or_404(VendorContacts, email=value)
v = vc.vendor
if v.active:
raise serializers.ValidationError('Email {} already exists'.format(value))
return value
In the above serializer, I perform a check at the def validate_email() model field level.
print('Start validation') is not called.
I tried the same at the object level through def validate(): but it is not called either.
UPD
views.py
class VendorContactsCreateView(APIView):
permission_classes = [permissions.AllowAny, ]
serializer_class = VendorContactCreateSerializer
def post(self, request, *args, **kwargs):
data = request.data
serializer = VendorContactCreateSerializer(data=data)
try:
serializer.is_valid(raise_exception=True)
serializer.save()
except ValidationError:
return Response({"errors": (serializer.errors,)},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response(request.data, status=status.HTTP_200_OK)

I want to get the list of all the employees that are registered with the company along with their designation

I am working on a model and I want to get the details of the employees in an organization along with their designations. I cannot think of anything at this point of time. This is my first time asking a question here so any help would mean a lot and if I havent provided the exact details please tell me. I think these should be sufficient enough for the answe.
Here is my organization and userorgdetail models:
class Organization(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=256)
employees = models.ManyToManyField(InSocialUser, related_name='organizations', blank=True,
through="UserOrgDetail")
description=models.TextField(blank=True)
class UserOrgDetail(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(InSocialUser, related_name='org_details', on_delete=models.CASCADE)
org = models.ForeignKey(Organization, related_name='employee_details', on_delete=models.CASCADE)
designation = models.CharField(max_length=256)
REQUIRED_FIELDS = ['user','org']
Here is my serializers file:
class OrgSerializer(serializers.ModelSerializer):
class Meta:
model = Organization
fields = ('id','name','employees')
class UserOrgDetailSerializer(serializers.ModelSerializer):
class Meta:
model = UserOrgDetail
fields = '__all__'
class UserOrgDetailReadSerializer(UserOrgDetailSerializer):
user = serializers.PrimaryKeyRelatedField(read_only=True)
org = OrgSerializer(read_only=True)
views.py
class OrganizationAPIView(
mixins.CreateModelMixin,
generics.ListAPIView):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
serializer_class = OrgSerializer
filter_backends = [filters.OrderingFilter,filters.SearchFilter]
search_fields = ['name']
ordering_fields = ['name']
ordering = ['name']
queryset = Organization.objects.all()
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
def perform_create(self, serializer):
serializer.save()
class UserOrgDetailAPIView(
mixins.CreateModelMixin,
generics.ListAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = UserOrgDetailReadSerializer
filter_backends = [filters.OrderingFilter,filters.SearchFilter]
search_fields = ['designation']
ordering_fields = ['name']
ordering = ['name']
def get_queryset(self, *args, **kwargs):
id = self.kwargs.get("id",None)
"""
This view should return a list of all the Organization Details of the logged in user
"""
queryset = UserOrgDetail.objects.filter(user__id=id)
return queryset
def post(self, request, *args, **kwargs):
id = self.kwargs.get("id",None)
#user = get_object_or_404(User, id=id)
user = User.objects.get(id=id)
orgId = request.data.get('org_id')
org = Organization.objects.get(pk=orgId)
designation = request.data.get('designation')
org_detail = UserOrgDetail.objects.create(user=user,org=org,designation=designation)
user.save()
return Response({"status": "Success","result":UserOrgDetailReadSerializer(org_detail).data})
class UserOrgDetailDetailAPIView(
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.RetrieveAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = UserOrgDetailReadSerializer
queryset = UserOrgDetail.objects.all()
lookup_field = 'id'
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
def get_serializer_class(self):
if self.request.method == 'GET':
return UserOrgDetailReadSerializer
else:
return self.serializer_class
I want that when I fire the get request for userorgdetail I get the employees working in the company along with their designation. Any help would be very useful, Thank you

I want to dynamically change the form of django according to user information

Although it is in the title, I want to change the form dynamically with django.
But now I get an error.
I can't deal with it.
I was able to get user information, but if I filter it, it will be “cannot unpack non-iterable UPRM object”.
#forms.py
class RecordCreateForm(BaseModelForm):
class Meta:
model = URC
fields = ('UPRC','URN','UET','URT',)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(RecordCreateForm,self).__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
self.fields['URN'].choices = UPRM.objects.filter(user=user)
#views.py
class RecordCreate(CreateView):
model = URC
form_class = RecordCreateForm
template_name = 'records/urcform.html'
success_url = reverse_lazy('person:home')
def get_form_kwargs(self):
kwargs = super(RecordCreate, self).get_form_kwargs()
# get users, note: you can access request using: self.request
kwargs['user'] = self.request.user
return kwargs
#models
class UPRM(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
URN = models.CharField( max_length=30,editable=True)
def __str__(self):
return self.URN
class URC(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
UPRC = models.CharField(max_length=300)
URN = models.ForeignKey(UPRM, on_delete=models.CASCADE)
def __str__(self):
return self.UPRC
cannot unpack non-iterable UPRM object
You should use queryset instead of choices here:
class RecordCreateForm(BaseModelForm):
class Meta:
model = URC
fields = ('UPRC','URN','UET','URT',)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(RecordCreateForm,self).__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
self.fields['URN'].queryset = UPRM.objects.filter(user=user)

Redirected by django updateview but not updated

I created an update screen for django. However, although it redirects to successURL, the data has not been updated. I don't know why.
I need your help.
I will post it if necessary.
#view
class RecordDetailEdit(UpdateView,LoginRequiredMixin):
template_name = 'records/detail_edit.html'
model = URC
form_class = RecordDetailEditForm
pk_url_kwarg = 'id'
success_url = reverse_lazy('person:home')
def get_object(self):
return get_object_or_404(User, pk=self.request.user.user_id)
def get_form_kwargs(self):
kwargs = super(RecordDetailEdit, self).get_form_kwargs()
# get users, note: you can access request using: self.request
kwargs['user'] = self.request.user
return kwargs
#form
class RecordDetailEditForm(forms.ModelForm):
class Meta:
model = URC
fields = ('UPRC','URN','UET','URT')
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(RecordDetailEditForm, self).__init__(*args, **kwargs)
self.fields['URN'].queryset = UPRM.objects.filter(user=user)
#model
class URC(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
UPRC = models.CharField(max_length=300)
URN = models.ForeignKey(UPRM, on_delete=models.CASCADE)
UET = models.DurationField(editable=True)
URT = models.DateTimeField(default=timezone.now,editable=True)
group = models.ForeignKey(group, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.UPRC
#url
path('<id>/edit/', views.RecordDetailEdit.as_view(), name='record_detail_edit'),
I changed it to the following.
def get_object(self, queryset=None):
obj = URC.objects.get(id=self.kwargs['id'])
return obj

POST requests error for Django many-to-many models

I'm receiving the following error when trying to make a POST request to create a particular model within the sqlite3 database:
"<Article>" needs to have a value for field "article" before this many-to-many relationship can be used.
I'm building a REST API using the Django REST Framework and I have two models with a many-to-many relationship as follows:
class Publication(models.Model):
title = models.CharField(max_length=30)
class Article(models.Model):
headline = models.CharField(max_length=100)
publications = models.ManyToManyField(Publication)
The corresponding extract in views.py for an Article is as follows:
class ArticleList(mixins.ListModelMixin, mixins.CreateModelMixin):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
I'm assuming the issue is that the article doesn't get saved before the POST request is finished as I'm able to perform all CRUD operations fine using Django's database API.
The PublicationSerializer is as follows:
class PublicationSerializer(serializers.Serializer):
pk = serializers.IntegerField(read_only=True)
title = serializers.CharField(required=True, max_length=120, allow_blank=False)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.save()
return instance
def create(self, validated_data):
return Publication.objects.create(**validated_data)
The ArticleSerializer is as follows:
class ArticleSerializer(serializers.Serializer):
pk = serializers.IntegerField(read_only=True)
headline = serializers.CharField(required=True, max_length=120, allow_blank=False)
publications = serializers.StringRelatedField(many=True)
def update(self, instance, validated_data):
instance.headline = validated_data.get('headline', instance.headline)
instance.publications = validated_data.get('publications', instance.publications)
instance.save()
return instance
def create(self, validated_data):
return Article.objects.create(**validated_data)
A sample of the data I attempted to post:
{
"headline": "Trending Topics",
"publications": []
}
What's the best approach to solving this issue?