Django add new item to dict - django

thread_list = thread.objects.select_related().filter(thread_forum_id = current_obj.id).order_by('-thread_date')
for thread in thread_list:
count = post.objects.select_related().filter(post_thread_id = thread.id).count()
thread.post = count
How do that?
thread.post = count
^
class thread(models.Model):
mess = models.CharField(max_length=5000)
objects = thread_manager()
I want add new item to the list manualy.

Your question is not well-written, but I believe what you are looking for is annotation (docs here):
from django.db.models import Count
thread_list = thread.objects.select_related().filter(thread_forum_id=current_obj.id) \
.order_by('-thread_date').annotate(post_count=Count('post_thread_set'))
# I'm just guessing this name: 'post_thread_set'
The returned value is not a list of dicts, rather it is a queryset, which is an iterable of objects. You can then access post_count as an attribute:
thread_list[0].post_count

You way is good.
But there is a conflict:
thread_list = thread.objects.select_related().filter(thread_forum_id = current_obj.id).order_by('-thread_date')
for thread in thread_list:
count = post.objects.select_related().filter(post_thread_id = thread.id).count()
thread.post = count
Your class have name thread and your loop have name like class.
for thread in thread_list:
Just do that:
for threads in thread_list:
count = post.objects.select_related().filter(post_thread_id = threads.id).count()
threads.post = count
or something like this. Just change loop - i add 's' at the end of a word

Related

For each item update database

I'm a total beginner with Python/Django and trying to understand why this isn't working. I have a function that contains a for loop, doing some logic and then updating a model. but when I have more than 1 item in the loop I get a UNIQUE constraint failed: app_token.token_name error.
So I think I'm misunderstanding how the loop is working?
function
tokens = Token.objects.all()
for item in tokens:
if item.token_contract_address is not None:
token = Token.objects.get(pk=item.id)
parameters = {
'address':token.token_contract_address
}
session = Session()
session.headers.update(headers)
response = session.get(url, params=parameters)
resp = json.loads(response.text)
token_id = (resp['data'][next(iter(resp['data']))]['id'])
logo = (resp['data'][next(iter(resp['data']))]['logo'])
url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest'
parameters = {
'id':token_id
}
session = Session()
session.headers.update(headers)
response = session.get(url, params=parameters)
id = str(token_id)
price = (json.loads(response.text)['data'][id]['quote']['USD']['price'])
market_cap = (json.loads(response.text)['data'][id]['quote']['USD']['market_cap'])
change = (json.loads(response.text)['data'][id]['quote']['USD']['percent_change_24h'])
r = Token.objects.update(token_capture_date = formatedDate, token_price = price, token_name=item.token_name )
I'm expecting the this Token.objects.update(token_capture_date = formatedDate, token_price = price, token_name=item.token_name ) to update the model based on the item loop?
The model is very simple:
class Token(models.Model):
token_name = models.CharField(max_length=50, blank=False, unique=True)
token_slug = models.CharField(max_length=50, blank=True,null=True)
token_price = models.FloatField(blank=True,null=True)
token_capture_date = models.DateField(blank=True,null=True)
token_contract_address = models.CharField(max_length=50, blank=True,null=True)
def __str__(self):
return str(self.token_name)
I'm using the update on the objects and have tried removing the token_name, and tried using token.token_name
If I remove token_name= it updates both items in the database with the same values? which makes me think its this line r = Token.objects.update(token_capture_date = formatedDate, token_price = price, token_name=item.token_name ) do i need to apply some kinda of filter?
Thanks
I believe that by calling Token.objects.update() you actually end up trying to update all Token objects. Since token_name has to be unique, and you are giving it the same name as another Token object it throws that error.
Since you are already in a for loop, you can simply update the token that is currently being processed.
My suggestion would be to use this code instead:
item.token_capture_date = formattedDate
item.token_price = price
item.save()
This will make it so that the current token object which is being processed in the for loop has its respective field values updated and saved in the database.
Also, this line is unnecessary: token = Token.objects.get(pk=item.id) as we already have access to the token through the looping variable item.
Do let me know if this helps!

Computed Property for Google Datastore

I am not sure exactly how achieve this.
I have a model defined as
class Post(ndb.Model):
author_key = ndb.KeyProperty(kind=Author)
content = ndb.StringProperty(indexed=False)
created = ndb.DateTimeProperty(auto_now_add=True)
title = ndb.StringProperty(indexed=True)
topics = ndb.StructuredProperty(Concept, repeated=True)
concise_topics = ndb.ComputedProperty(get_important_topics())
#classmethod
def get_important_topics(cls):
cls.concise_topics = filter(lambda x: x.occurrence > 2, cls.topics)
return cls.concise_topics
I like to set the value of concise_topics (Which is on the same type as topics) to a subset acheived via get_important_topics method. This should happen the moment the topics property has been set.
How do I define the "concise_topics" property in the Post class ?
With class method, you don't have access to the instance values. And also you shouldn't call the function, only pass it to the computed property, and let it call by itself.
class Post(ndb.Model):
author_key = ndb.KeyProperty(kind=Author)
content = ndb.StringProperty(indexed=False)
created = ndb.DateTimeProperty(auto_now_add=True)
title = ndb.StringProperty(indexed=True)
topics = ndb.StructuredProperty(Concept, repeated=True)
def get_important_topics(self):
return filter(lambda x: x.occurrence > 2, self.topics)
concise_topics = ndb.ComputedProperty(get_important_topics)
As far as I remember the computed property is set on each put call, so your topics should be already there by that time.

How passing string on filter keyword to Django Objects Model?

How can i pass variables on a keyword object filter on a view?
I have:
my_object = MyModel.objects.filter(my_keyword =my_filter_values)
I want to grab my_keyword from a variable coming from a string, like this:
my_string = 'my_keyword'
my_object = MyModel.objects.filter(my_string=my_filter_values)
But this doesn't work because Django doesn't know my_string from MyModel.
Edit: I've found this SO question - I'll test and report back.
You can do something like this:
my_filter = {}
my_filter[my_keyword] = my_filter_value
my_object = MyModel.objects.filter(**my_filter)
As an example, your variables might be:
my_keyword = 'price__gte'
my_filter_value = 10
Which would result in getting all objects with a price >= 10. And if you want to query on more than one field, you can just add another line below my_filter[my_keyword]:
my_filter[my_keyword] = my_filter_value
my_filter[my_other_keyword] = my_other_filter_value

Django: Simplifying long 'join's?

I've got a few long queries (for checking capabilities) which look like this:
widgets = Widget.objects.filter(
Q(owner__memberships = current_user),
Q(owner__memberships__memberships__capabilities__name = "widget_list")
)
Is there any reasonable way of simplifying that query? Or do I just need to live with it?
The relevant models are:
class Widget(m.Model):
owner = m.ForeignKey(Group)
class Group(m.Model):
memberships = m.ManyToManyField(User, through=GroupMembership)
class GroupMembership(m.Model):
user = m.ForeignKey(User)
group = m.ForeignKey(Group)
capabilities = m.ManyToMany(Capability)
class Capability(m.Model):
name = m.CharField(...)
You don't need to wrap your parameters in Q() objects, you can use the key/value pairs directly:
widgets = Widget.objects.filter(
owner__memberships = current_user,
owner__memberships__memberships__capabilities__name = "widget_list"
)

filter using Q object with dynamic from user?

In my views.py I have a method:
#......
def get_filter_result(self, customer_type, tag_selected):
list_customer_filter=[]
customers_filter = Customer.objects.filter(Q(type__name=customer_type),
Q(active=True),
Q(tag__id=tag_selected))
for customer_filter in customers_filter:
customer_filter.list_authorize_sale_type = sale_type_selected(customer_filter.authorize_sale_type)
list_customer_filter.append(customer_filter)
return list_customer_filter
**My case tag_selected is the checkbox values that user checked
I have a problems with tag_selected(is the list=1,2,3,...) that pass from my url
/?customer_type=TDO&tag=2 ===>filter okay
/?customer_type=TDO&tag=3 ===>filter okay
?customer_type=TDO&tag=2,3 ===>How Can I add And condition in filter?
for example
if len(tag_selected)==1:
customers_filter = Customer.objects.filter(Q(type__name=customer_type),
Q(active=True),
Q(tag__id=tag_selected))
else:
customers_filter = Customer.objects.filter(Q(type__name=customer_type),
Q(active=True),
Q(tag__id=tag_selected[0])
Q(tag__id=tag_selected[1])
Q(tag__id=tag_selected[2])
...
)
This works for both single and multiple conditions:
idseq = request.POST['tag'].split(',')
tag_qs = reduce(operator.or_, (Q(tag__id=x) for x in idseq))
Customers.objects.filter(..., tag_qs)