django - different inlines for different users - django

I have these models
class Office(models.Model):
name = models.CharField(max_length=255)
class User(models.Model):
name = models.CharField(max_length=255)
status = models.SmallIntegerField()
office = models.ForeignKey(Office, on_delete=models.SET_NULL, null=True)
class Inspection(models.Model):
place = models.CharField(max_length=255, null=True, blank=True)
class Jobs(models.Model):
inspection = models.ForeignKey(Inspection, on_delete=models.CASCADE)
inspector = models.ForeignKey(User, on_delete=models.SET_NULL)
cost = models.DecimalField(max_digits=20, decimal_places=2)
I have different users: common users(status=1) and admins(status=2).
Common users can make and see Jobs only with Inspectors from the same office.
Admins can put any user into Inspectors and see all Jobs.
I can filter job list for users in the same office:
class JobAdmin(admin.StackedInline):
model = Job
extra = 0
def get_queryset(self, request):
qs = super(JobAdmin, self).get_queryset(request)
if request.user.status in [1]:
qs = qs.filter(inspector__office=request.user.office)
return qs
class InspectionAdmin(ModelAdmin):
list_display = ['place']
inlines = [JobAdmin]
But how can I add additional filters for editing?
If it was not an inline form I would do it this way:
class JobAdminForm(ModelForm):
def __init__(self, *args, **kwargs):
super(JobAdminForm, self).__init__(*args, **kwargs)
if self.user.status == 1: #common user
self.fields['inspector'].queryset = Inspector.objects.filter(office=self.user.office)
class Meta:
model = Jobs
fields = '__all__'
class JobAdmin(ModelAdmin):
form = JobAdminForm
def get_form(self, request, obj=None, **kwargs):
form = super(JobAdmin, self).get_form(request, **kwargs)
form.user = request.user
return form

Maybe this code will be helpfull:
class JobAdmin(admin.StackedInline):
model = Job
extra = 0
def get_queryset(self, request):
qs = super(JobAdmin, self).get_queryset(request)
if request.user.status in [1]:
qs = qs.filter(inspector__office=request.user.office)
return qs
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
if db_field.name == "inspector" and request.user.status == 1:
kwargs['queryset'] = Inspector.objects.filter(office=request.user.office)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
P.S. Link to Django documentation: formfield_for_foreignkey

Related

DRF: django rest framework case insensitive lookup in detail view

How to make urls case insensitive with certain parameters passed
For example, assuming Stock model has a ticker. All links below should find the same ticker content, right now they are case sensitive and try to search for different values:
/stocks/AAPL
/stocks/aapl
/stocks/AaPl
views.py
class StockViewSet(viewsets.ModelViewSet):
queryset = Stock.objects.all()
serializer_class = StockSerializer
lookup_field = "ticker"
#action(detail=True, methods=["get"], url_path="is", url_name="is")
def get_income_statement(self, request, *args, **kwargs):
is_qs = IncomeStatement.objects.filter(ticker=self.get_object())
serializer = IncomeStatementSerializer(is_qs, many=True)
return Response(serializer.data)
#action(detail=True, methods=["get"], url_path="bs", url_name="bs")
def get_balance_sheet(self, requests, *args, **kwargs):
bs_qs = BalanceSheet.objects.filter(ticker=self.get_object())
serializer = BalanceSheetSerializer(bs_qs, many=True)
return Response(serializer.data)
#action(detail=True, methods=["get"], url_path="cf", url_name="cf")
def get_cashflows_statement(self, requests, *args, **kwargs):
cf_qs = CashflowsStatement.objects.filter(self.get_object())
serializer = CashflowsStatementSerializer(cf_qs, many=True)
return Response(serializer.data)
class IncomeStatementDetail(viewsets.ModelViewSet):
queryset = IncomeStatement.objects.all()
serializer_field = IncomeStatementSerializer
class BalanceSheetDetail(viewsets.ModelViewSet):
queryset = BalanceSheet.objects.all()
serializer_field = BalanceSheetSerializer
class CashflowsStatementDetail(viewsets.ModelViewSet):
queryset = CashflowsStatement.objects.all()
serializer_field = CashflowsStatementSerializer
urls.py
router = DefaultRouter()
router.register(r"stocks", views.StockViewSet)
urlpatterns = router.urls
models.py
class Stock(models.Model):
id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
ticker = models.CharField(max_length=10, unique=True, primary_key=True)
slug = models.SlugField(default="", editable=False)
def save(self, *args, **kwargs):
value = self.ticker
self.slug = slugify(value, allow_unicode=True)
super().save(*args, **kwargs)
def __str__(self):
return self.ticker
class Meta:
verbose_name = "stock"
verbose_name_plural = "stocks"
ordering = ["ticker"]
Use lookup_url_kwarg and lookup_field as
from rest_framework import viewsets
class StockViewSet(viewsets.ModelViewSet):
lookup_url_kwarg = 'ticker'
lookup_field = 'ticker__iexact'
# rest of your code
You can refer the source code of get_object(self) to see how DRF fetching the model object in the detail view.

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

How to update modified_by field with CurrentUserDefualt

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)