Filter TreeNode children by parent - django

How I can order my queryset, by category_views field in Treenode model?
I tried with ordering = ["category_stats__category_views"] (on settings "DEFAULT_FILTER_BACKENDS" configured with "rest_framework.filters.OrderingFilter") but it's, not working.
# category models.py
from tree_queries.models import TreeNode
class Category(TreeNode)
foo = models.CharFiled()
bar = models.CharField()
class CategoryStats(models.Model)
category = models.ForeingKey(Category, related_name="category_stats")
category_views = models.IntegerField()
# category views.py
class CategoryViews(FrontEndListView):
serializer_class = serializers.CategoryListSerializer
# ordering = ["category_stats__category_views"]
lookup_field = "id"
def get_queryset(self):
queryset = models.Category.objects.filter(parent_id=self.kwargs.get("id"))
for item in queryset:
return item.children.all()#.order_by("category_stats__category_views")

Related

Django query set to display particular field on webpage

I am trying to display the variants(field) that are related to the model RecordVariant on my webpage i have queryset on my view default how can i change my queryset or get queryset method to display variants that are related to particular record.
class RecordVariant(models.Model):
variants = models.ForeignKey(Variant_model, related_name = 'records', on_delete =
models.CASCADE)
class Variant(models.Model):
name = models.CharField(max_length = 23, blank=True, null=True)
class RecordVariantListAPIView(RecordMixin, ListAPIView):
lookup_url_kwarg = 'record_id'
serializer_class = RecordVariantSerializer
permission_classes = [IsAuthenticated]
pagination_class = StandardResultsSetPagination
filter_backends = (filters.OrderingFilter,)
queryset = RecordVariant.objects.all()
ordering = 'variants'
ordering_param = 'ordering'
ordering_fields = (
'variants',
)
def get_total_queryset(self):
queryset = (
super()
.get_queryset()
.filter(record=self.record)
)
in foreignkey relations the child should be the one with foreginkey field.
meaning your Variant model class should have this field
class Variant(models.Model):
name = models.CharField(max_length = 23, blank=True, null=True)
records = models.ForeignKey(RecordVariant, related_name = 'records',
on_delete = models.CASCADE)
class RecordVariant(models.Model):
pass
and for the serializers
class Variant(serializers.ModelSerializer):
class Meta:
model = Variant
fields = "['name']"
class RecordVariant(serializers.ModelSerializer):
records = VariantSerializer(many=True)
class Meta:
model = RecordVariant
fields = '__all__'
the view
class RecordVariantListAPIView(ListAPIView):
serializer_class = RecordVariantSerializer
permission_classes = [IsAuthenticated]
queryset = RecordVariant.objects.all()

How to use Generic View for a child

I am starting to learn how to use the generic view. Considering that we`ve got a foreign key to parent. How can I create a child view using Generic View?
Would that be the same way we are creating the parentview?
views?.py
class ChildCreateView(generic.CreateView):
template_name = "app/create_child.html"
model = Child
form_class = ChildForm
success_url = reverse_lazy("app:index_child")
models.py
class Parent(models.Model):
pass
class Child(models.Model):
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
views1.py
class ParentCreateView(generic.CreateView):
template_name = "app/create_parent.html"
model = Parent
form_class = ParentForm
success_url = reverse_lazy("app:index_parent")
You need to communicate to the child view what the parent is. The common solution is to use nested urls:
urlpatterns = [
path("/app/parents/", ParentListView.as_view()),
path("/app/parents/<int:parent_id>/", ParentDetailView.as_view()),
path("/app/parents/<int:parent_id>/children/", ChildListView.as_view()),
path("/app/parents/<int:parent_id>/children/<int:child_id>/", ChildDetailView.as_view()),
]
Now you can restrict the child to specific a parent in the ChildDetailView:
class ChildDetailView(generic.DetailView):
model = Child
pk_url_kwarg = 'child_id'
def get_queryset(self, queryset):
qs = super().get_queryset(queryset)
return qs.filter(parent__pk=self.kwargs['parent_id'])
class ChildCreateView(generic.CreateView):
model = Child
pk_url_kwarg = 'child_id'
def get_queryset(self, queryset):
qs = super().get_queryset(queryset)
return qs.filter(parent__pk=self.kwargs['parent_id'])
class ChildUpdate...
Wait, this gets repetitive:
class NestedParentMixin(generic.base.SingleObjectMixin):
parent_lookup = 'parent__pk'
parent_url_kwarg = 'parent_id'
def get_queryset(self, queryset):
qs = super().get_queryset(queryset)
filter_kwargs = {self.parent_lookup: self.kwargs[self.parent_url_kwarg]}
return qs.filter(**filter_kwargs)
class ChildDetailView(NestedParentMixin, generic.DetailView):
model = Child
pk_url_kwarg = 'child_id'
class ChildUpdateView(NestedParentMixin, generic.UpdateView):
model = Child
pk_url_kwarg = 'child_id'
class SiblingDetailView(NestedParentMixin, generic.DetailView):
model = Sibling
pk_url_kwarg = 'sibling_id'

Django REST framework: how to combine the same type of model

How to combine many models in one query set so that it would be possible to use HyperlinkedModelSerializer using pagination?
I need to connect many models with the same fields.
That's what I did, but it doesn’t suit me.:
#models.py
class Merketing(models.Model):
question = models.CharField(max_length=500, unique=True)
answer = models.CharField(max_length=500)
class Management(models.Model):
question = models.CharField(max_length=500, unique=True)
answer = models.CharField(max_length=500)
#serializers.py
class MerketingSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Merketing
fields = ['id','question', 'answer']
class ManagementSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Management
fields = ['id','question', 'answer']
class FiltersSerializers(serializers.Serializer):
model_1 = MerketingSerializer(read_only=True,many=True)
model_2 = ManagementSerializer(read_only=True,many=True)
#viesw.py
class MerketingViewSet(viewsets.ModelViewSet):
queryset = Merketing.objects.all().order_by('question')
serializer_class = MerketingSerializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [filters.SearchFilter]
search_fields = ['question']
class ManagementViewSet(viewsets.ModelViewSet):
queryset = Management.objects.all().order_by('question')
serializer_class = ManagementSerializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [filters.SearchFilter]
search_fields = ['question']
class FiltersView(APIView):
def get(self, request, *args, **kwargs):
filters = {}
filters['model_1'] = Merketing.objects.all().order_by('question')
filters['model_2'] = Management.objects.all().order_by('question')
serializer = FiltersSerializers(filters)
return Response (serializer.data, status=HTTP_200_OK)
Here is the solution to my problem !!!
class Fi2ViewSet(viewsets.ModelViewSet):
qs1 = Merketing.objects.all()
qs2 = Management.objects.all()
qs3= Macroeconom.objects.all()
qs4 = Kse.objects.all()
queryset = qs1.union(qs2,qs3,qs4).order_by('question')
serializer_class = Fi2Serializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [filters.SearchFilter]
search_fields = ['question']
serializers.py
class Fi2Serializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Merketing
fields = ['id','question', 'answer']

Insertions of same row is happening and how to reject an insertion if iti is already present in DB Django-rest-framework,PostgreSQL

I am trying to create a backend for social app. While inserting friend relation in database, It is also inserting relations already present in DB.
Example:
User 1 and User 2 are already friends
So,The row in DB: 1,2,3,date
Now the DB shouldn't accept the same row anymore but it is accepting !!!
How to reject or restrict multiple insertions of same rows.
My View:
class Friendship(viewsets.ModelViewSet):
"""Handles Creating Friendship"""
authentication_classes = (TokenAuthentication,)
serializer_class = UserFriendSerializer
permission_classes = (permissions.FriendCreate,IsAuthenticated)
queryset = Friends.objects.all()
def perform_create(self, serializer):
"""Sets the friendship status to user"""
serializer.save(username = self.request.user)
My serializer:
class UserFriendSerializer(serializers.ModelSerializer):
"""A serializer for adding and removing Friends"""
class Meta:
model = Friends
fields = ('user_id_1','user_id_2','status',)
def create(self, validated_data):
"""Create user friendship with lesser id in first column"""
friend_1 = validated_data['user_id_1']
friend_2 = validated_data['user_id_2']
if friend_1.pk > friend_2.pk:
temp = friend_1
friend_1 = friend_2
friend_2 = temp
friend = Friends(
user_id_1 = friend_1,
user_id_2 = friend_2,
status = validated_data['status'],
)
friend.save()
return friend
My Model:
class Friends(models.Model):
'''Friend's or Relationship between user's and their relation status'''
user_id_1 = models.ForeignKey(User,on_delete=models.CASCADE,related_name='user_a')
user_id_2 = models.ForeignKey(User,on_delete=models.CASCADE,related_name='user_b')
status = models.PositiveSmallIntegerField()
friends_on = models.DateTimeField(auto_now_add=True,auto_now=False)
def __str__(self):
"""Returns model as a String"""
return str(self.user_id_1)
class Meta:
verbose_name_plural = "Friends"
if i understand you correct, you need the unique-together
class Friends(models.Model):
"""Friend's or Relationship between user's and their relation status"""
user_id_1 = models.ForeignKey(User,on_delete=models.CASCADE,related_name='user_a')
user_id_2 = models.ForeignKey(User,on_delete=models.CASCADE,related_name='user_b')
status = models.PositiveSmallIntegerField()
friends_on = models.DateTimeField(auto_now_add=True,auto_now=False)
def __str__(self):
"""Returns model as a String"""
return str(self.user_id_1)
class Meta:
verbose_name_plural = "Friends"
unique_together = ("user_id_1", "user_id_2")

How to change the choices of the ChoiceField of django-rest-framework from a model class?

Th models.py is:
from django.db import models
class Type(models.Model):
letter = models.CharField(max_length = 1)
name = models.CharField(max_length = 10)
class Code(models.Model):
type = models.ForeignKey(Type, related_name = 'code', blank = True, default = None)
the serializers.py is:
import collections
from rest_framework import serializers
from code.models import Type, Code
class TypeSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Type
fields = ('letter','name')
class TypeField(serializers.HyperlinkedModelSerializer):
class Meta:
model = Type
fields = ('letter',)
class CodeSerializer(serializers.HyperlinkedModelSerializer):
type = TypeField() #serializers.ChoiceField(???)
def create(self, validated_data):
c = Code()
c.type = Type.objects.get(letter = validated_data['type']['letter'])
c.save()
return c
class Meta:
model = Code
fields = ('type',)
the views.py is:
from rest_framework import viewsets
from code.models import Code, Type
from code.serializers import CodeSerializer, TypeSerializer
class CodeViewSet(viewsets.ModelViewSet):
queryset = Code.objects.all()
serializer_class = CodeSerializer
class TypeViewSet(viewsets.ModelViewSet):
queryset = Type.objects.all()
serializer_class = TypeSerializer
Is possible use a ChoiseField for choose the type inside the Code, When I create an istance of the Code object instead a CharField?
Possible Solution
I find a possible solution, I derived class ChoiseField to DynamicChoiceField
class DynamicChoiceField(serializers.ChoiceField):
def __init__(self, **kwargs):
super(DynamicChoiceField, self).__init__([],**kwargs)
def set_choices(self, choices):
pairs = [
isinstance(item, (list, tuple)) and len(item) == 2
for item in choices
]
if all(pairs):
self.choices = OrderedDict([(key, display_value) for key, display_value in choices])
else:
self.choices = OrderedDict([(item, item) for item in choices])
self.choice_strings_to_values = dict([
(six.text_type(key), key) for key in self.choices.keys()
])
and change the CodeSerializer in:
class CodeSerializer(serializers.HyperlinkedModelSerializer):
type = TypeField(read_only=True)
choise_of_type = DynamicChoiceField(allow_blank=False, write_only=True)
def __init__(self, *args, **kwargs):
types = Type.objects.all()
choices = [(t.letter,t.name) for t in types]
self.fields['choise_of_type'].set_choices(choices)
super(CodeSerializer, self).__init__(*args, **kwargs)
def create(self, validated_data):
c = Code()
c.type = Type.objects.get(letter = validated_data['choise_of_type'])
c.save()
return c
class Meta:
model = Code
fields = ('type', 'choise_of_type',)
the only flaw of this solution is that I need of two fields insted only one (type,choise_of_type)