Using replace method on list of model objects - python

I want to print out a list of objects, which at the moment looks like this: [<model.Name: value_of_field1>, <model.Name: value_of_field2>, etc]. I would like to get only the values, so I am hoping for an outcome like:
value_of_field1, value_of_field2, etc
My attempt to do this was by using: list = [item.replace('model.Name: ', '') for item in list], however, this resulted in the following error: 'model.Name' object has no attribute 'replace'.
How can I get a clean list, that I can later on use?
EDIT:
I forgot to mention that I tried using values_list(), however, it does not give the wanted result. My models look something like this:
class Article(models.Model):
title = models.ForeignKey(Title)
class Title(models.Model):
author = models.ForeignKey(User)
name = models.ForeignKey(NameArchive)
def __str__(self):
return '%s, %s' % (self.author, self.name)
where, author consists of 2 names. So, the values in the list (value_of_field1 etc) will look something like this - author_first_name author_last_name, article_name and values_list() gives only the last one and not all three.

The model's __repr__() method is reponsible for the additional <model:Name output that you're seeing.
You can call __str__() directly to give you the string representation you're after.
[str(o) for o in list_of_objects]

Related

Django Model.objects.all() doesn't give all the objects

In my Django model I have 2 field. When I execute below code it just prints the resolution field. How can I get the all fields data in a list?
x = ResolutionsModel.objects.all()
for i in x:
print(i)
models.py
class ResolutionsModel(models.Model):
resolution = models.TextField(max_length=30,blank=True)
act_abbreviation = models.TextField(max_length=30)
def __str__(self):
return self.resolution
So your model says that to represent an instance of itself as a string it should use the value of resolution. So by printing an instance, that's what you're getting - the value of resolution.
If you pass your queryset to a template you could output the values from all the fields.
For the purposes of your test in python you'd have to specifically include each field;
x = ResolutionsModel.objects.all()
for i in x:
print(i.resolution)
print(i.act_abbreviation)
If you actually want to get data in a list, you might want to read about how to use values_list on a queryset; https://docs.djangoproject.com/en/4.0/ref/models/querysets/#values-list
For the purpose of getting to know django you could also adapt your str method;
def __str__(self):
return f"{self.resolution}, {self.act_abbreviation}"
In your case:
x = ResolutionsModel.objects.all()
The x here is a query set, which returns a bunch of entries from data base, each entry is a database entry:
for i in x:
print(i)
i # is a database entry, you can access i.resolution & i.act_abbreviation at each loop.
In the end, everything is an object.

TypeError : count() takes at least 1 argument (0 given)

i am getting TypeError: count() takes at least 1 argument (0 given).
it would be great if anybody could figure out where i am doing thing wrong. thank you so much in advance.
class CommentsSerializer(serializers.ModelSerializer):
comment_count = serializers.SerializerMethodField()
class Meta:
model = Comments
fields = [
"id", "title", "name", "subject", "comment_count",
]
def get_comment_count(self, obj):
return obj.subject.count()
Your implementation does not make sense. I think you are trying to get count of all the Comments object, but here you are trying to count subject, probably that is a string or a list. On them, count works like this:
IN >> "aaaaa".count('a')
OUT >> 5
IN >> [1,2,3,4].count(1)
OUT >> 1
Now, to fix your problem, we need to understand what you want to achieve here. If you want to get count of comments for a particular post, then you can try like this:
If you have a model like this:
class Comments(models.Model):
post = models.ForeignKey(Post)
Then you can take this approach:
def get_comment_count(self, obj):
return obj.post.comments_set.count()
This is count() function from Django queryset. And obj.post.comments_set will return a queryset(for having a reverse relationship). If you have defined related_name="post_comments"(docs), then it will become obj.post.post_comments.count().
You may check the function description here
It counts the occurrence of an object in a list, so you need to pass an object as a parameter to count() function, and apply this on a list.
Also, it would be better if you give a sample program that you got the error.
count() requires exactly one argument and returns the number of instances of the provided argument in the list.
If you just want to count number of elements in a list, use:
return len(obj.subject)
count requires an argument. It returns the number of instances of a particular item in a list.
l=[1,2,5,4,5,6,7,10]
l.count(5)
2
2 here is the number of 5s in the list.

Iterating list and collecting corresponding field value from model

I have model which consist of three fields and in the table should look something like this:
drg_code | drg_kof | drg_count
---------+----------+------------
A08A | 0.45 | 215
A08B | 0.75 | 656
B03A | 0.33 | 541
B03C | 0.22 | 125
Code for it models.py
class DrgCode(models.Model):
drg_code = models.CharField(max_length=4)
drg_kof = models.DecimalField(max_digits=6, decimal_places=3)
drg_count = models.IntegerField()
def __str__(self):
return self.drg_code
I created form for user input which returns QuerySet of drg_code variables. It looks like this in in print: <QuerySet [<DrgCode: A05Z>, <DrgCode: A06A>, <DrgCode: A06C>]>. So I converted it into list.
Now I need to iterate through that list and using drg_code variables, find corresponding model fields values, and store them in separate lists so in the end I should end with 3 lists: one for drg_code, one for drg_kof and one for drg_count (these list will be needed for future calculations).
I tried using method from my earlier question, but I keep getting error AttributeError saying 'str' object has no attribute 'objects' or similar (depending on code variation I tried) on obj = DRGkodas.objects.first() line.
My relevant view.py code:
from catalog.models import DrgCode
from catalog.forms import DrgCalculator
#up to this part everything works so I emit irrelevant code
chosen_drg = form.cleaned_data['drg_choose']
psrDRG_list = list([str(i) for i in chosen_drg]) #converting QuerySet into list (seems to work fine)
psr_atv_sk = [] #list for drg_count variables
psr_atv_kof = [] #list for drg_kof variables
for item in psrDRG_list:
drg_code = item
obj = DrgCode.objects.first()
atv_sk = getattr(obj, drg_code)
psr_atv_sk.append(atv_sk)
'''
in here I tried different approach of
getting corresponding field value, but do
not know if it works since code never
reached this part
'''
atv_kof = DrgCode.drg_kof
psr_atv_kof.append(atv_kof)
Why I am getting AttributeError what I am doing wrong? And am I correctly trying to catch corresponding field values? Which method is right?
Why not using get()
DrgCode.objects.get(drg_code = item)
Also read about first() see
I feel stupid, since I wrote code in my native language (variable names in native) then I posted code here and translated it for easier reading I emitted original reason why I was getting and error - variable name in models.py and views.py was the same so I was getting AttributeError because of that.
Other than that, Mahmoud Adel answer got me on the right track. Code for accessing another field value looks like this:
for item in psrDRG_list:
obj = DrgCode.objects.get(drg_code = item)
atv_sk = obj.drg_count

TestCase self.assertEqual does not match a similar string

I'am trying to create a model unittest for a ManyToMany relationship.
The aim is to check, if there is the right category saved in the table Ingredient.
class IngredientModelTest(TestCase):
def test_db_saves_ingredient_with_category(self):
category_one = IngredientsCategory.objects.create(name='Food')
first_Ingredient = Ingredient.objects.create(name='Apple')
first_Ingredient.categories.add(category_one)
category_two = IngredientsCategory.objects.create(name='Medicine')
second_Ingredient = Ingredient.objects.create(name='Antibiotics')
second_Ingredient.categories.add(category_two)
first_ = Ingredient.objects.first()
self.assertEqual('Apple', first_.name)
self.assertEqual(first_.categories.all(), [category_one])
self.assertEqual(first_, first_Ingredient)
for self.asserEqual(first_.categories.all(), [category_one]) in the second last row I get this weird assert:
AssertionError: [<IngredientsCategory: Food>] != [<IngredientsCategory: Food>]
I tried many other different ways, but none of it worked. Does any one suppose how I can get the information of first_.categories.all() to compare it with something else?
That'll be because they're not equal - one is a QuerySet, the other is a list - they just happen to have the same str representations.
You could either cast the QuerySet to a list with list(first_.categories.all()), or a possible solution for this situation may be:
self.assertEqual(first_.categories.get(), category_one)

how to add a condition of comparing two fields of the model itself in Django model query

As mentioned by the title, in Django:
Say I have a model name QuestionRecord, with two fields: full_score and actual_score.
I want to realize the SQL:
select * from QuestionRecord as QR where QR.full_score!=QR.actual_score.
Maybe using raw sql is OK, but I want to implement it like this:
class QuestionRecord_QuerySet(models.query.QuerySet):
def incorrect(self):# Find out those whose full_score and actual_score are not equal
return self.filter(...) # **What should I write here??**
class QuestionRecord_Manager(models.Manager):
def get_query_set(self):
return QuestionRecord_QuerySet(self.model)
class QuestionRecord(models.Model):
objects = QuestionRecord_Manager()
Is there any way to do it?
Sure, that's what the "F" object is for!
from django.db.models import F
# snip
return self.exclude(full_score = F('actual_score'))
Use QuerySet.exclude here, as you want to not get the results that match.
If you really want to use QuerySet.filter, you can use a negated "Q" object: self.filter(~Q(full_score = F('actual_score'))).

Categories