Iterate through all related objects changing a value - django

I'm trying to work out a way i can iterate through each related object and change the 'show' value from True to False.
class Device(models.Models):
name = models.Charfield(max_length=100)
type = models.Charfield(max_length=100)
class Log(models.Modles):
device = models.ForeignKey(Device, related_name='msgs', on_delete=models.CASCADE)
log = models.Charfield(max_length=100)
date_time = models.DateTimeField(auto_now=True)
show = models.BooleanField(default=True)
I've tried the following but it's not working.
device = Device.objects
for host in device.all():
Log.objects.filter(device=host).update(show=False)
but i get 'Log' object has no attribute 'update'. any ideas?
Edit: Just to make it more clear what i'm trying to do. There are multiple 'Log' objects per 'Device' object. On a particular view i'd like to set the 'show' value to false because that means they have all been read and don't need to show in the top bar of my site any more.

ok answer is this.
selected_device = Device.objects.get(id.self.kwargs['device_id']
Log.objects.filter(device=selected_device).update(show=False)
I don't know why this works but it does. i can't see how it iterates through each log per device but it does so i'm just going to accept it works.

Related

in Django: How to get and display in template verbose_name of a model that their value is true, while name of field unknown?

I have a model than has a lot of models.BooleanField declarations.
class a_lot_of_booleans(model.Models):
old_or_new = models.BooleanField(default=False,verbose_name="is it an old or a new item")
product_for_teens = models.BooleanField(default=False,verbose_name="is this product for teens")
in_original_package = models.BooleanField(default=False,verbose_name="is this product in original package?")
Which then is used in some other classes like:
class product_for_sale(a_lot_of_booleans):
U_Id = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
product_name=models.CharField(max_length=50)
class product_for_buying(a_lot_of_booleans):
U_Id = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
product_name=models.CharField(max_length=50)
The class a_lot_of_booleans might change over time. Some booleans might get added some might get removed. What I need is to display a list of several entries, of the verbose_name, of only the true fields on one of the classes that inherit the a_lot_of_booleans class and the value of product_name, belonging to specific user.
What I"m trying in the views.py is the following:
def view_rfps(request):
list=product_for_sale.objects.all().filter(U_Id=request.user)
for item in list:
values=item._meta.fields
for value in values:
res=item.objects.filter(**{value:'True'}) ##<< lines that fail
print(res)
the above code fails on res=item.objects.filter(**{value:'True'}) on "Manager isn't accessible via search_for_constructor_rfp instances"
The idea later to pass on the res variable to view, however I cannot pass this point.
I have several items in list and for every list several boolean fields, that I"m not sure what they names gonna be in a future, so I cannot just use product_for_sale. in template later.
Any suggestion how to display the verbose name of unknown boolean field name ?
edit
Found a way:
def view_rfps(request):
list=product_for_sale.objects.all().filter(U_Id=request.user)
for item in list:
values=item._meta.fields
for value in values:
temp=getattr(item,value.name)
if temp:
print(value.verbose_name)
But if someone knows more efficient way, I"d love to hear
This is what worked for me:
def view_rfps(request):
list=product_for_sale.objects.all().filter(U_Id=request.user)
for item in list:
values=item._meta.fields
for value in values:
temp=getattr(item,value.name)
if temp:
print(value.verbose_name)

Determine count of object retrieval per day in django

In a model like the one below
class Watched(Stamping):
user = models.ForeignKey("User", null=True, blank=True, on_delete=models.CASCADE)
count = models.PositiveIntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Anytime an object is retrieved, I increment the count attribute.
Now my problem is how to get the number of times an object was retrieved for each day of the week
For example, WatchedObject1 will have {'Sun': 10, 'Tue': 70, 'Wed': 35}
This seems like a use case for auditing and there are plugins for Django that can help you with that. If you don't want to add this dependency you would have to create another model that you store your intended data.
class RetrievalOfData(models.Model):
date_of_retrieval = models.datetimefield(auto_now_add=True)
object_retrieved = models.ForeignKey("Watched")
You could probably also override the manager to create these objects everytime the model is queried: https://docs.djangoproject.com/en/3.2/topics/db/managers/
You might find it better to have a separate WatchedModelStats table, and perhaps link it you your model with Django signals. Whenever a countable event takes place, execute something like
try:
counter = WatchedModelStats.objects.get( name=model_name, date=today)
counter.count += 1
except WatchedModelStats.DoesNotExist:
counter = WatchedModelStats( name=model_name, date=today, count=1 )
counter.save()
One advantage is extensibility. You could easily implement multiple counts for differerent event types, if the need later becomes apparent.

Add new object to model with a foreign key

So this seems to be asked before but for the life of me, i cannot get any of the solutions to work.
I have two classes, Device and Log. There are many logs per device and i'd like to be able to add new items to the Log objects.
class Device(models.Models):
name = models.Charfield(max_length=100)
type = models.Charfield(max_length=100)
class Log(models.Modles):
device = models.ForeignKey(Device, related_name='msgs', on_delete=models.CASCADE)
log = models.Charfield(max_length=100)
date_time = models.DateTimeField(auto_now=True)
I've been trying things like this in my view:
device = Device.objects.filter(name=hostname)
device.msgs.add(log=new_log_msg)
but nothing i try is working. any ideas?
You need a Device instance, but filter always gives a queryset. You should use get.
device = Device.objects.get(name=hostname)
device.msgs.add(log=new_log_msg)
Get device object as
device = Device.objects.filter(name=hostname) # If hostname not found throw exception
For creating a new log
log = Log.objects.create(device=device, log='')
use get instead of filter in queryset and for creating and updating the alway intitiate the instance.
device = Device.objects.get(name=hostname)
device.msgs.add(log=new_log_msg)
For adding data in log
Log.objects.create(device=device, log='')
The device=device is foriegn key.

Django Save Model Idiom

Let's say you've got a ActiveDirectoryUser model:
class ActiveDirectoryUser(models.Model):
object_guid = models.CharField(max_length=200, unique=True)
mail = models.EmailField(unique=True)
name = models.CharField(max_length=200)
This model is populated from an Active Directory query. Every day, I rerun a job in batch that queries Active Directory, gets the results back, and checks if the person is already in AD. If they are it checks if anything has changed, and if not they get added to the Database. I found myself writing:
try:
ad_user = ActiveDirectoryUser.objects.get(object_guid=object_guid)
ad_user.object_guid = object_guid
ad_user.mail = mail
ad_user.name = name
ad_user.save()
except ActiveDirectoryUser.DoesNotExist:
ActiveDirectoryUser(
object_guid=object_guid,
mail=mail,
name=name).save()
Basically, I try to get the object with the attributes and if that throws a DoesNotExist exception, I know it's not already there and so I create a new one. Is this the right/best/idiomatic way of either updating or saving a new object into the database? I know it works, but it looks wrong somehow. Inelegant.
No, django has a built-in way to do this.
entry, created = ActiveDirectory.objects.get_or_create(
object_guid = 'your_value',
name = = 'your_value',
mail = 'your_value'
)

Django: Store Hierarchical Data

I'm trying to store sections of a document in a Django app. The model looks like:
class Section(models.Model):
project = models.ForeignKey(Project)
parent_section = models.ForeignKey('Section', blank=True, null=True, related_name='child_set')
predecessor_section = models.ForeignKey('Section', blank=True, null=True, related_name='predecessor_set')
name = models.CharField(max_length=100)
text = models.TextField(blank=True, null=True)
I create a whole lot of sections, link them (parent_section, predecessor_section) and store them by calling each of their save methods. However, when I look into the table after saving it, the parent_section_id and the predecessor_section_id are not set, even though I had objects attached to them before saving.
I assume it has to do with the fact that some parent_section instances don't have an id assigned as their instance hasn't been stored yet, but using manual transactions couldn't solve the problem.
Any thoughts on that?
Cheers,
Max
objects do not have an id until you save them in Django ORM.
So I'd say you need to save() the object, then reference it in your parent/child sections (and re-save the sections).
However, another option to storing prec and next as pointers is to store an sequence_index (spaced by 10 to allow further inserts wiothout reordering) and order by this index.
Try doing a save() on all the objects, then update their relations, and then save() all of them again.
When you assign a foreignkey, the related (target) object's id is copied. since at the moment of assigning the relations (parent_section, predecessor_section) the related objects don't have an id yet, you get a funky result:
A = Section(name='A')
B = Section(name='B')
B.parent_section = A
A.save()
B.save()
B.parent_section # this will say A
B.parent_section_id # this will say **None**
But this should work:
A = Section(name='A')
B = Section(name='B')
A.save()
B.save()
B.parent_section = A
B.parent_section # this will say A
B.parent_section_id # this will say A.id
B.save() # don't forget this one :)