Django rest methodfield if condition working issue? - django-rest-framework

i want to pass completely and partially paid users in my serializer,but its not shows
,
payment_status = serializers.SerializerMethodField()
def get_payment_status(self, obj):
if int(obj.total_due) > 0:
paid_status ={'payment_status':'Partially paid'}
else:
paid_status={'payment_status':'Completely paid'}
return paid_status

Try to return String, not dict
payment_status = serializers.SerializerMethodField()
def get_payment_status(self, obj):
if int(obj.total_due) > 0:
return 'Partially paid'
return 'Completely paid'

Related

Qt6: how to disable selection for empty cells in QTableView?

I'm trying to display some data from a database in a grid view, similar to how a file manager works. I thought of using a QTableView as the grid view since it did what I wanted out of the box. However, as shown with the below given MRE, even if just a single cell has value, you can still select the other empty cells, how can I prevent this? Basically, I want to make it so that only cells with a value can be selected.
MRE:
from PySide6 import QtWidgets as qtw
from PySide6 import QtGui as qtg
from PySide6 import QtCore as qtc
ROW_COUNT = 5
COL_COUNT = 5
class Model(qtc.QAbstractTableModel):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._data = [[None for _ in range(COL_COUNT)] for _ in range(ROW_COUNT)]
def data(self, index: qtc.QModelIndex, role: qtc.Qt.ItemDataRole):
if not index.isValid():
return None
if role == qtc.Qt.ItemDataRole.DisplayRole:
return self._data[index.row()][index.column()]
return None
def setData(self, index: qtc.QModelIndex, value, role: qtc.Qt.ItemDataRole=qtc.Qt.ItemDataRole.DisplayRole):
if not index.isValid():
return False
if role == qtc.Qt.ItemDataRole.DisplayRole:
self._data[index.row()][index.column()] = value
return False
def rowCount(self, _):
return ROW_COUNT
def columnCount(self, _):
return COL_COUNT
app = qtw.QApplication()
view = qtw.QTableView()
view.setModel(Model())
view.setShowGrid(False)
view.verticalHeader().setVisible(False)
view.horizontalHeader().setVisible(False)
view.model().setData(view.model().createIndex(0, 0), "this is a test")
view.show()
app.exec()
You need to override the flags() and ensure that it doesn't return the ItemIsSelectable flag.
class Model(qtc.QAbstractTableModel):
# ...
def flags(self, index):
flags = super().flags(index)
if index.data() is None:
flags &= ~qtc.Qt.ItemIsSelectable
return flags
In your case, you also probably want to avoid the ItemIsEnabled, and since these two flags are the default one, you can just return NoItemFlags
def flags(self, index):
if index.data() is None:
return qtc.Qt.NoItemFlags
return super().flags(index)
If you also need to clear the selection, then you could subclass the view and do it in the mousePressEvent():
class TableView(qtw.QTableView):
def mousePressEvent(self, event):
index = self.indexAt(event.pos())
if index.isValid() and not index.flags() & qtc.Qt.ItemIsSelectable:
self.clearSelection()
else:
super().mousePressEvent(event)

how can store the number 100 only when 1 to 99 numbers are must have inside the db

suppose i am adding matchround_5, round 1,2,3,4 must have inside the db ,check each round are present in the database , How can i solve this issue?
Modelserializer
class MatchScoreSerializer(serializers.ModelSerializer):
def create(self, validated_data):
gameevent = validated_data.get('gameevent')
match_round =validated_data.get('match_round')
match = Matchscore.objects.filter(gameevent=gameevent,match_round=match_round).first()
if match :
validated_data = Matchscore.objects.filter(gameevent=gameevent,match_round=match_round).update(**validated_data)
match.refresh_from_db()
return validated_data
else:
return Matchscore.objects.create(**validated_data)
def validate(self, validated_data):
gameevent = validated_data.get('gameevent')
match_round =validated_data.get('match_round')
if not match_round :
raise serializers.ValidationError("Enter value more than 0")
if match_round == 1:
return validated_data
round = range(1,match_round)
match = Matchscore.objects.filter(gameevent=gameevent,match_round__in=round).values_list('match_round',flat=True)
match = set(match)
if match :
return validated_data
if len(match)== match_round-1:
return validated_data
else:
raise serializers.ValidationError("Enter a valid match_round")
Here my model
class Matchscore(TimeStampedModel):
gameevent = models.ForeignKey(GameEvent, null=True, related_name='game_event',on_delete=models.DO_NOTHING)
match_round = models.IntegerField(null=True,blank=True)
team_a = models.ForeignKey(Team,null=True,related_name='team_one',on_delete=models.DO_NOTHING)
team_a_score = models.PositiveIntegerField(null=True,blank=True)
team_b = models.ForeignKey(Team,null=True,related_name='team_two',on_delete=models.DO_NOTHING)
team_b_score = models.PositiveIntegerField(null=True,blank=True)
team_won = models.ForeignKey(Team,null=True,related_name='team', on_delete=models.DO_NOTHING)
Checking if match to return the validated data is not sufficient. You should check the length. You thus return the validated data if len(match) == match_round - 1.
You can however let the database return the number of distinct values, and thus avoid counting yourself:
matches = Matchscore.objects.filter(
gameevent=gameevent,
match_round__range=(1, match_round)
).values('match_round').distinct().count()
if matches == match_round-1:
return validated_data
else:
raise serializers.ValidationError('Enter a valid match_round')

How to implement Elasticsearch advanced search with DRF

I want to implement a search in Elastic Search with Django Rest Framework. I have a form for searching as follows.
I used a serializer to implement this form.
search.py:
class AdvancedSearch(mixins.ListModelMixin, viewsets.GenericViewSet):
serializer_class = AdvancedSearchSerializer
def query_builder(self, *args, **kwargs):
## building related query
return query
#get_db()
def get_queryset(self, db=None, *args, **kwargs):
serializer = self.get_serializer(data=self.request.data)
serializer.is_valid(raise_exception=True)
query = self.query_builder(search_input=serializer.validated_data)
response = db.search(query) # query the elastic with elasticsearch-dsl and return the results
if not response:
raise NoteFound()
return response
def list(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
self.serializer_class = AdvancedSearchSerializer
return super(AdvancedSearch, self).list(request, *args, **kwargs)
serializer.py:
class AdvancedSearchSerializer(serializers.Serializer):
metadata_choices = [('', ''), ...]
name = serializers.CharField(required=False, label='Name')
type = serializers.CharField(required=False, label='Type')
metadata = serializers.CharField(required=False, label='Metadata')
metadata_fields = serializers.MultipleChoiceField(allow_blank=True, choices=metadata_choices)
submit_date = serializers.DateTimeField(required=False)
def to_representation(self, instance):
output = {}
output['es_id'] = instance.meta.id
for attribute_name in instance:
attribute = getattr(instance, attribute_name)
if isinstance(attribute, (str, int, bool, float, type(None))):
# Primitive types can be passed through unmodified.
output[attribute_name] = attribute
elif isinstance(attribute, list):
# Recursively deal with items in lists.
output[attribute_name] = [
self.to_representation(item) for item in attribute
]
elif isinstance(attribute, (dict, AttrDict)):
temp = attribute.to_dict()
for key, value in temp.items():
print(key,value)
# Recursively deal with items in dictionaries.
output[attribute_name] = {
str(key): value
for key, value in temp.items()
}
else:
# Force anything else to its string representation.
output[attribute_name] = attribute
output['highlight'] = instance.meta.highlight.to_dict()
return [output]
With this code, I get the expected result, but I was wondering if this is a right approach.
And also in to_representation I have access to each result, but how can I add a total value like the number of results.
Thanks in advance.

*unsupported operand type(s) for -: 'NoneType' and 'NoneType'

class budgetSerializer(serializers.ModelSerializer):
budget_used = serializers.SerializerMethodField()
budget_remain = serializers.SerializerMethodField()
total_budget = serializers.IntegerField(default=250000)
def get_budget_used(self, obj):
budget_used = budget_u.objects.filter(
user=obj.user
).aggregate(total=Sum('budget_stord__bytes'))['total'] or 0
if budget_used > 250000:
return 'you exceed the total budget limit'
return f'budget : {(budget_used/1000)}'
def get_total_budget(self,obj):
total_budget = 250000
return f'total_budget: {(total_budget/1000)} '
def get_remain(self,obj):
remain = (self.context.get(total_budget)) - (self.context.get(budget_used))
return remain
class Meta:
model = budget_u
fields = ("budget_used","total_budget","budget_remain")
Any help when i run the code above aim getting Error
(self.context.get(total_budget)) - (self.context.get(budget_used)) TypeError:
unsupported operand type(s) for -: 'NoneType' and 'NoneType'
The context does not store values of intermediate calculations, it is a dictionary that is used, for example by a ModelViewSet to inject data into the serializer.
To make matters even worse, even if the context indeed behaved the way as you are using it, it would still not work, since the get_budget_used and get_total_budget methods, return strings. You can not subtract two strings from each other, what would 'foo' - 'bar' mean? Or in this case 'total budget: 25000' - 'budget : 1425'? This may look simple if you interpret the strings, but for Python these are just strings, and the operations need to be non-ambiguous, hence it makes no sense.
You can define methods that return the value, and then use these by calling the functions:
class budgetSerializer(serializers.ModelSerializer):
# …
def _budget_used(self, obj):
return budget_u.objects.filter(
user=obj.user
).aggregate(total=Sum('budget_stord__bytes'))['total'] or 0
def _total_budget(self, obj):
return 250000
def get_budget_used(self, obj):
budget_used = self._budget_used(obj)
if budget_used > 250000:
return 'you exceed the total budget limit'
return f'budget : {(budget_used/1000)}'
def get_total_budget(self, obj):
total_budget = self._total_budget(obj)
return f'total_budget: {(total_budget/1000)} '
def get_remain(self,obj):
return self._total_budget(obj) - self._budget_used(obj)

Haystack and elasticsearch not working with one character

I am trying to make searches using haystack and elasticsearch but for some reason it only returns results when I search a word with more than one character.
How do I enable one character searches?
This is my index
class CustomerIndex(CelerySearchIndex, indexes.Indexable):
text = indexes.CharField(document=True)
first_name_auto = indexes.CharField(model_attr='first_name', default='')
last_name_auto = indexes.CharField(model_attr='last_name', default='')
full_name_auto = indexes.EdgeNgramField(model_attr='get_full_name', default='')
address1 = indexes.CharField(model_attr='address1', indexed=False,
default='')
accounts_customer_auto = indexes.MultiValueField()
def get_model(self):
return Customer
def prepare_accounts_customer_auto(self, obj):
return [a.id for a in obj.accounts.all()]
# def index_queryset(self, using=None):
# """Used when the entire index for model is updated."""
# return Customer.objects.all()
def get_model(self):
return Customer
and this is the query
sqs = SearchQuerySet().filter(
full_name_auto__exact=query_text).order_by('-full_name_auto').models(Customer)
This seems to be an haystack default feature

Resources