i'm trying to filter logbook report based on the logged in industry supervisor,
the supervisor should be able to see the report of students under his supervision
views.py
class LogbookEntryView(ListAPIView):
queryset = LogbookEntry.objects.all()
serializer_class = StudentLogbookEntrySerializer
def get_queryset(self, *args, **kwargs):
qs = super().get_queryset(*args, **kwargs)
request = self.request
user = request.user
if not user.is_authenticated:
LogbookEntry.objects.none()
return qs.filter(student_id__industrysupervisor = request.user.student.industry_based_supervisor)
models.py
LogbookEntry Model
class LogbookEntry(models.Model):
week = models.ForeignKey("api.WeekDates", verbose_name=_("Week Id"), null=True, on_delete=models.SET_NULL)
student = models.ForeignKey("students.Student", verbose_name=_("Student Id"), on_delete=models.CASCADE)
entry_date = models.DateTimeField()
title = models.CharField(_("Title"), max_length=50)
description = models.CharField(_("Description"), max_length=1000)
diagram = models.ImageField(_("Diagram"), upload_to=profile_picture_dir)
Student Model
class Student(models.Model):
user = models.OneToOneField(get_user_model(), null=True, on_delete=models.CASCADE)
profile_pic = models.ImageField(_("profile picture"), upload_to=profile_picture_dir)
department_id = models.ForeignKey(Department, null=True, on_delete=models.SET_NULL)
phone_no = models.CharField(max_length=11)
school_based_supervisor = models.ForeignKey("school_based_supervisor.SchoolSupervisor", verbose_name=_("School Supervisor"), null=True, on_delete=models.SET_NULL)
industry_based_supervisor = models.ForeignKey("industry_based_supervisor.IndustrySupervisor", verbose_name=_("Industry Supervisor"), null=True, on_delete=models.SET_NULL)
placement_location = models.ForeignKey("industry_based_supervisor.PlacementCentre", verbose_name=_("Placement Location"), null=True, blank=True, on_delete=models.SET_NULL)
Industry Supervisor Model
class IndustrySupervisor(models.Model):
user = models.OneToOneField(get_user_model(), null=True, on_delete=models.CASCADE)
profile_pic = models.ImageField(_("profile picture"), upload_to=profile_picture_dir)
phone_no = models.CharField(max_length=11)
placement_center = models.ForeignKey("industry_based_supervisor.PlacementCentre", verbose_name=_("Placement Centre"), null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
You can update your get_queryset method in the LogbookEntryView class
def get_queryset(self):
user = self.request.user
# If user is not authenticated, return empty queryset
if not user.is_authenticated:
return LogbookEntry.objects.none()
# If user is not a student, return empty queryset
if not hasattr(user, 'student'):
return LogbookEntry.objects.none()
# Get the industry supervisor for the student
supervisor = user.student.industry_based_supervisor
# If student does not have an industry supervisor, return empty queryset
if supervisor is None:
return LogbookEntry.objects.none()
# Filter logbook entries based on the industry supervisor
queryset = LogbookEntry.objects.filter(student__industrysupervisor=supervisor)
return queryset
Related
I am getting Issue while edit a record based on CHatquestion ID, if option is null then i need to add a record based on same chatquestion id, if chatqustion id exist in option it will work,
i am trying to multiple way to solve this issue but still can't find solution.
Models.py # thease are all 3 models
class Problem(models.Model):
Language = models.IntegerField(choices=Language_CHOICE, default=1)
type = models.CharField(max_length=500, null=True, blank=True)
def __str__(self):
return self.type
class ChatQuestion(models.Model): # Eding record based on chatquestion id
question = RichTextField(null=True, blank=True)
problem_id = models.ForeignKey(
Problem,
models.CASCADE,
verbose_name='Problem',
)
def __str__(self):
return self.question
is_first_question = models.BooleanField(default=False)
class Option(models.Model):
option_type = models.CharField(max_length=250, null=True, blank=True)
question_id = models.ForeignKey(
ChatQuestion,
models.CASCADE,
verbose_name='Question',
null=True,
blank=True
)
problem=models.ForeignKey(
Problem,
models.CASCADE,
verbose_name='Problem',
null=True,
blank=True
)
next_question_id = models.ForeignKey(ChatQuestion, on_delete=models.CASCADE, null=True, blank=True,
related_name='next_question')
def __str__(self):
return self.option_type
forms.py
class EditQuestionForm(forms.ModelForm):
class Meta:
model = ChatQuestion
fields =('question','problem_id')
class EditOptionForm(forms.ModelForm):
class Meta:
model = Option
fields =('option_type',)
views.py
def question_edit(request,id=None):
if id is not None:
queryset = get_object_or_404(ChatQuestion,pk=id)
queryset1=get_object_or_404(Option,question_id=queryset )
else:
queryset = None
queryset1 = None
if request.method=="POST":
form = EditQuestionForm(request.POST ,instance=queryset)
form1=EditOptionForm(request.POST, instance=queryset1)
if form.is_valid() and form1.is_valid():
question=form.cleaned_data['question']
option_type=form1.cleaned_data['option_type']
if id:
queryset.question=question
queryset.save()
queryset1.option_type=option_type
queryset1.save()
messages.success(request,'Sucessful')
return redirect('/fleet/list_chatbot')
else:
print(form.errors)
messages.error(request,'Please correct following',form.errors)
elif id:
form = EditQuestionForm(instance=queryset)
form1=EditOptionForm(instance=queryset1)
if not queryset1:
form1=EditOptionForm()
else:
form = EditQuestionForm()
form1=EditOptionForm()
context={
'form':form,
'form1':form1
}
return render(request,'chatbot/question_edit.html',context=context)
So many documentation for filtering in Django rest framework but all the examples are in class based view. but I am trying to do the same in DRF function based view. I wanted to do multiple filter for my items queryset.
I tried one way and it is working perfectly. Here first I am trying to search by item name or restaurant name in one request. then I take another keyword and try to filter restaurant name or item name based on restaurant city. It is working perfectly like if I hit this url
http://localhost:8000/api/items/?keyword=lasagne&keyword1=paris
then it gives me the perfect response.
But What I am asking for is that now my code looks for this specific part is messy and I want to add more fields for multiple filtering. Which procedure to follow? Should I follow this one and multiple requests and trying to filter from this.
Suppose now I want to filter the queryset based on dish_type, price, item_type, location and then search for items by name or restaurants by name
#this is my models
class Restaurant(models.Model):
user = models.OneToOneField(CustomUser, related_name='restaurant', on_delete=models.CASCADE, null=False)
name = models.CharField(max_length=200, blank=True, null=True)
profile_picture = models.ImageField(null=True, blank=True)
address = models.TextField(max_length=2000, blank=True, null=True)
city = models.CharField(max_length=200)
latitude = models.DecimalField(max_digits = 13, decimal_places = 7, blank=True, null=True)
longitude = models.DecimalField(max_digits = 13, decimal_places = 7, blank=True, null=True)
is_verified = models.BooleanField(default=False)
createdAt = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.name)
class Item(models.Model):
user = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
name = models.CharField(max_length=220)
image = models.ImageField(null=True, blank=True)
dish_type = models.ForeignKey(Dishtype, on_delete=models.CASCADE)
item_type = models.ForeignKey(Itemtype, on_delete=models.CASCADE)
description = models.TextField(max_length=10000)
rating = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)
numReviews = models.IntegerField(null=True, blank=True, default=0)
old_price = models.DecimalField(max_digits=11, decimal_places=2)
discount = models.IntegerField(blank=True, null=True)
price = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True)
countInStock = models.IntegerField(blank=True, null=True, default=0)
createdAt = models.DateTimeField(auto_now_add=True)
_id = models.AutoField(primary_key=True, editable=False)
def save(self, *args, **kwargs):
self.price = Decimal(self.old_price * (100 - self.discount) / 100)
return super(Item, self).save(*args, **kwargs)
class Meta:
ordering = ['-createdAt']
def __str__(self):
return self.name
#serializer
class RestaurantSerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Restaurant
fields = '__all__'
def get_user(self, obj):
user = obj.user
serializer = UserSerializer(user, many=False)
return serializer.data
class ItemSerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField(read_only=True)
dish_type = serializers.SerializerMethodField(read_only=True)
item_type = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Item
fields = '__all__'
def get_user(self, obj):
user = obj.user
serializer = RestaurantSerializer(user, many=False)
return serializer.data
def get_dish_type(self, obj):
dish_type = obj.dish_type
serializer = DishtypeSerializer(dish_type, many=False)
return serializer.data
def get_item_type(self, obj):
item_type = obj.item_type
serializer = ItemtypeSerializer(item_type, many=False)
return serializer.data
#views.py
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def getItems(request):
user = request.user
query = request.query_params.get('keyword')
if query == None:
query = ''
cuery = request.query_params.get('keyword1')
if cuery == None:
cuery = ''
items = Item.objects.select_related('user').select_related('dish_type').select_related('item_type').all().filter(
Q(name__icontains = query) | Q(user__name__icontains = query))
else:
restaurant_city = Item.objects.select_related('user').select_related('dish_type').select_related('item_type').all(
).filter(Q(user__city__iexact = cuery))
items = restaurant_city.filter(Q(name__icontains = query) | Q(user__name__icontains = query))
serializer = ItemSerializer(items, many=True)
return Response(serializer.data)
######Updated solved the problem
#filters.py
class ItemFilter(django_filters.FilterSet):
numReviews = django_filters.NumberFilter()
numReviews__gt = django_filters.NumberFilter(field_name='numReviews', lookup_expr='gt')
numReviews__lt = django_filters.NumberFilter(field_name='numReviews', lookup_expr='lt')
name = django_filters.CharFilter(lookup_expr='icontains')
class Meta:
model = Item
fields = ['_id', 'dish_type__id']
#views
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def getItems(request):
user = request.user
queryset = Item.objects.all()
filterset = ItemFilter(request.GET, queryset=queryset)
if filterset.is_valid():
queryset = filterset.qs
serializer = ItemSerializer(queryset, many=True)
return Response(serializer.data)
now data are passing like this
http://localhost:8000/api/items/?numReviews__gt=20&numReviews__lt=22
You can use queryset and override get_queryset function.
class FooViewSet(GenericViewSet, mixins.ListModelMixin):
authentication_classes = [JSONWebTokenAuthentication]
permission_classes = [IsAuthenticated]
serializer_class = ItemSerializer
def get_queryset(self):
query = self.request.query_params.get('keyword', '')
if not self.request.query_params.get('keyword1'):
items = Item.objects.select_related('user').select_related('dish_type').select_related(
'item_type').all().filter(
Q(name__icontains=query) | Q(user__name__icontains=query))
else:
restaurant_city = Item.objects.select_related('user').select_related('dish_type').select_related(
'item_type').all(
).filter(Q(user__city__iexact=self.request.query_params.get('keyword1', '')))
items = restaurant_city.filter(Q(name__icontains=query) | Q(user__name__icontains=query))
return items
the issue is that i have 3 users levels
1-superuser
2-jihawi
3-mahali,
I would like to separate the veiw from the "Quantite" function by request.user
models.py
class typestock(models.Model):
Type = models.CharField(max_length=50, blank=True, null=True)
def __str__(self):
return self.Type
class stock(models.Model):
Jihawi = models.ForeignKey(User, on_delete=models.CASCADE, related_name="stockjihawi", editable=True, blank=True, null=True)
Mahali = models.ForeignKey(User, on_delete=models.CASCADE, related_name="stockmahali", editable=True, blank=True, null=True)
Date = models.DateField(blank=True, null=True)
TypeStock = models.ForeignKey(typestock, on_delete=models.CASCADE, editable=True, blank=True, null=True)
Quantite = models.IntegerField()
def save(self, *args, **kwargs):
super(stock, self).save(*args, **kwargs)
return self.TypeStock
admin.py
class TypeStockAdmin(nested_admin.NestedModelAdmin, ImportExportModelAdmin):
inlines = [InlineStock]
list_display = ('Type', 'Quantite')
list_display_links = ('Type',)
list_filter = ('Type',)
search_fields = ('Type',)
def Quantite(self, obj):
result = stock.objects.filter(TypeStock_id=obj).aggregate(Sum("Quantite"))
return result["Quantite__sum"]
Quantite.short_description = "Quantité"
how to add this code in the Quantite function:
if request.user.is_superuser:
stock.objects.filter(StockType_id=obj).aggregate(Sum("Quantity"))
###must view all quantity from stock models###
elif request.user.is_jihawi:
stock.objects.filter(TypeStock_id=obj).aggregate(Sum("Quantity"))
###how to add filter Jihawi=request.user (Jihawi from stock models)###
elif request.user.is_mahali:
stock.objects.filter(StockType_id=obj).aggregate(Sum("Quantity"))
###how to add filter Mahali=request.user (Mahali from stock models)###
So I have three models:
class Session(models.Model):
id = models.UUIDField('ID', default=uuid.uuid4, primary_key=True, editable=False)
start_time = models.TimeField('Start Time', default=None)
end_time = models.TimeField('End Time', default=None)
def __str__(self):
return "{}-{}".format(str(self.start_time), str(self.end_time))
class Slot(models.Model):
id = models.UUIDField('ID', default=uuid.uuid4, primary_key=True, editable=False)
timings = models.ForeignKey('Session', on_delete=models.DO_NOTHING, related_name='slot_timings')
available_counsellors = models.ManyToManyField(User, limit_choices_to={'role': 'COUNSELLOR'}, related_name='available_counsellors')
def __str__(self):
return str(self.timings)
class ChatSession(models.Model):
def get_access_code():
while True:
access_code = get_random_string(length=6, allowed_chars=('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'))
if not ChatSession.objects.filter(access_code=access_code).exists():
return access_code
id = models.UUIDField('ID', default=uuid.uuid4, primary_key=True, editable=False)
client = models.ForeignKey(User, limit_choices_to={'role': 'CLIENT'}, on_delete=models.DO_NOTHING, related_name='client_user')
counsellor = models.ForeignKey(User, limit_choices_to={'role': 'COUNSELLOR'}, on_delete=models.DO_NOTHING, related_name='counsellor_user')
access_code = models.CharField('Access Code', default=get_access_code, max_length=6)
topic = models.CharField('Topic', default=None, blank=True, null=True, max_length=255)
slot = models.ForeignKey(Slot, on_delete=models.DO_NOTHING, default=None)
def __str__(self):
return str(self.topic)
In the chat session model, I want to limit the options for counsellor field to the available_counsellors list in slot model.
How can I do this??
I want the same to reflect in my admin view also.
You need to update the queryset on the counsellor form field.
Assuming you are using a ModelForm, you can do this in your view:
chat_session = ChatSession.objects.get(pk=1)
form = ChatSessionForm(instance=chat_session)
form.fields["counsellor"].queryset = chat_session.slot.available_counsellors
You can alternatively do it in your ModelForm:
class ChatSessionForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super (ChatSessionForm, self).__init__(*args, **kwargs)
if self.instance and self.instance.slot:
options = self.instance.slot.available_counsellors
else
options = User.objects.none()
self.fields['counsellor'].queryset = options
For Django admin, something like this should work:
class ChatSessionAdmin(admin.ModelAdmin):
def render_change_form(self, request, context, *args, **kwargs):
if kwargs['obj'].slot:
options = kwargs['obj'].slot.available_counsellors
else:
options = User.objects.none()
context['adminform'].form.fields['counsellor'].queryset = options
return super(ChatSessionAdmin, self).render_change_form(request, context, args, kwargs)
I've two type of users: Students and Institutions.
Both can login in the website and they have different profiles views.
I'd like to use "http://example.com/accounts/" for both types of users but running different logics and displaying different templates for each one.
For example, Students when they go to their profile they can view/modify their attributes as what are they studying, interested courses.. etc. On the other side, the institution users can view/modify attributes of their own model as institution information.
Institution User Type:
class InstitutionProfile(models.Model):
user = models.OneToOneField(User, related_name='client')
gender = models.CharField(max_length=40, choices=GENDERS_TYPES, blank=True)
#Contact Information
location = models.ManyToManyField(Location)
address = models.CharField(max_length=254, blank=True)
zipcode = models.CharField(max_length=56, blank=True)
phone = models.CharField(max_length=56, blank=True)
def __unicode__(self):
return '%s' % format(self.user)
Student User Type:
class StudentProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
about_me = models.TextField(null=True, blank=True)
gender = models.CharField(max_length=40, choices=GENDERS_TYPES, blank=True)
birth = models.DateTimeField(blank=True, null=True)
#Contact Information
location = models.ManyToManyField(Location, related_name='homecountry')
address = models.CharField(max_length=254, blank=True)
zipcode = models.CharField(max_length=56, blank=True)
phone = models.CharField(max_length=56, blank=True)
#Interested
countries_interested = models.ManyToManyField(Location, blank=True, related_name='countries interested')
areas_interested = models.ManyToManyField(StudyArea, blank=True)
levels_interested = models.ManyToManyField(StudyLevel, blank=True)
languages_interested= models.ManyToManyField(LanguageCourse, blank=True)
def __unicode__(self):
return '%s' % format(self.user)
view.py
class InstitutionProfileDetailView(DetailView):
model = get_user_model()
slug_field = "username"
template_name = "account/institution_profile.html"
def get_object(self, queryset=None):
user = super(InstitutionProfileDetailView, self).get_object(queryset)
InstitutionProfile.objects.get_or_create(user=user)
return user
class StudentProfileDetailView(DetailView):
model = get_user_model()
slug_field = "username"
template_name = "account/student_profile.html"
def get_object(self, queryset=None):
user = super(StudentProfileDetailView, self).get_object(queryset)
StudentProfile.objects.get_or_create(user=user)
return user
What is the best solution for having different views with 2 different type of users?
You can use an unified view and return different views from that according to your logic -
def accounts_view(request):
if request.user.is_student(): # <-- check with your logic, is_student() is a stub
return StudentProfileDetailView.as_view()
elif request.user.is_institute():
return InstitutionProfileDetailView.as_view()
And point accounts/ to accounts_view.