Add Django model property field to model's dictionary - python

I tried to search elsewhere, but I couldn't find a way to solve it. I can't figure out a way to add the model property to the model's dictionary. Is there a way to do it?
Here's how it is right now, I'm trying to add the property in the natural_key function.
[EDIT] It's going to be used with Django Json serializer.
class Departamento(models.Model):
class Meta:
db_table = 'Departamento'
def __unicode__(self):
return self.descricao
def natural_key(self):
return dict(id=self.id, descricao=self.descricao,
abreviacao=self.abreviacao,
coordenadoria_adjunta=self.coordenadoria_adjunta,
ramal=self.ramal)
def obter_funcionarios(self):
from modelos.funcionario import Funcionario
return Funcionario.objects.filter(departamento_id=self.id)
descricao = models.CharField(max_length=255, null=True)
abreviacao = models.CharField(max_length=255, null=True)
coordenadoria_adjunta = models.ForeignKey(CoordenadoriaAdjunta, null=True)
ramal = models.ForeignKey(Ramal, null=True)
funcionarios = property(obter_funcionarios)

Related

How to have two tag fields i.e. two Taggable Managers in the same model?

I have a model for uploaded files and I now need to have two tag fields in that model. One for user tags and one for admin tags. I've tried several solutions but neither worked.
Here is my code now and it doesn't work. Not sure if this is to create two separate tables, one for user tags and for admin tags so any help would be appreciated. Also, if you could maybe explain to me what I'm doing because I'm lost.
class UserTags(CommonGenericTaggedItemBase, TaggedItemBase):
object_id = models.CharField(max_length=50, db_index=True)
objects = models.Manager()
class BaseTag(TagBase):
pass
class AdminTags(CommonGenericTaggedItemBase, TaggableManager):
object_id = models.CharField(max_length=50, db_index=True)
tag = models.ForeignKey(BaseTag, on_delete=models.CASCADE)
objects = models.Manager()
# Model for all uploaded files
class Uploaded(models.Model):
objects: models.Manager()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="users")
time_uploaded = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=50)
file = models.FileField(upload_to=MEDIA_ROOT)
tag = TaggableManager(blank=True, through=UserTags, related_name='user_tags')
tags = TaggableManager(blank=True, through=AdminTags, related_name='admin_tags')
additional_description = models.CharField(max_length=50, blank=True)
def __str__(self):
return f"{self.name} {self.file}"
I would try to implement it like this.
from django.db import models
from taggit.managers import TaggableManager
from taggit.models import TaggedItemBase, ItemBase
class AdminTag(ItemBase):
pass
class UserTag(ItemBase):
pass
class ThroughAdminTag(TaggableManager):
content_object = models.ForeignKey('AdminTag', on_delete=models.CASCADE)
class ThroughUserTag(TaggableManager):
content_object = models.ForeignKey('UserTag', on_delete=models.CASCADE)
# Model for all uploaded files
class Uploaded(models.Model):
objects = models.Manager()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="users")
time_uploaded = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=50)
file = models.FileField(upload_to=MEDIA_ROOT)
tag = TaggableManager(blank=True, through=ThroughUserTag, related_name='user_tags')
tags = TaggableManager(blank=True, through=ThroughAdminTag, related_name='admin_tags')
additional_description = models.CharField(max_length=50, blank=True)
def __str__(self):
return f"{self.name} {self.file}"
Not sure whether AdminTag and UserTag need any fields. Inheriting them from ItemBase should, in theory, cover that.

Update records depending on fields - Django

I want to override the save method of a model in Django.
Consider this model:
class OtherClass(models.Model):
name = models.CharField(max_length=255, blank=True, null=True)
class MyClass(models.Model):
admin = models.ForeignKey(OtherClass, on_delete=models.CASCADE)
myfield1 = models.CharField(max_length=128)
myfield2 = models.CharField(max_length=128)
myfield3 = models.CharField(max_length=128, blank=True, null=True)
myfield4 = models.CharField(max_length=128, blank=True, null=True)
myfield5 = models.TextField(blank=True)
What I want, is to update the model only if myfield5 is present in whatever form or view the user is filling. This is the current save method I have:
def save(*args, **kwargs):
fieldgroup = f"{self.myfield2}\n{self.myfield3}"
self.myfield5 = f"{fieldgroup}\n{self.field1} {self.field4} {self.field5}"
super().save(*args, **kwargs)
Any ideas?
Maybe it would be better to achieve this on a form rather than directly into the model?
You can check self.pk to determine whether the object was already previously saved or not (the first time self.pk is None).
So in combination with self.field5, you can do this:
if self.pk and self.field5:
self.field5 = ... # update field5 as you need
super().save(...)
elif not self.pk:
super().save(...)
# no saving if self.pk and not self.fields
You can use required=True in your Model field or Form field

Django-autocomplete-light returns object names instead of corresponding field values

My problem whith django-autocomplete-light (dal 3) is that in the admin, instead of showing the choices corresponding tom my designated field (i.e. birth_nation see forms.py section), I always get a list of the str values of my queryset objects (see #models.py section) which is actually the last_name field.
# models.py
class MyModel(models.Model):
id_name = models.CharField(primary_key=True, max_length=255)
first_name = models.CharField(max_length=255, blank=True, null=True)
middle_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255)
birth_city = models.CharField(max_length=255, blank=True, null=True)
birth_nation = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return self.last_name
class Meta:
managed = False
db_table = 'mytable'
# forms.py
class MyModelForm(forms.ModelForm):
birth_nation = forms.ModelChoiceField(
queryset=MyModel.objects.all(),
widget=autocomplete.ModelSelect2(url='country-autocomplete',
attrs={'data-minimum-input-length': 2}
)
)
class Meta:
model = MyModel
fields = ('__all__')
# views.py
class MyModelAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated():
return MyModel.objects.none()
qs = MyModel.objects.all()
if self.q:
qs = qs.filter(birth_nation__istartswith=self.q)
return qs
Obviously, I want to get my choices that correspond to the birth_nation, what is wrong in my code?
try this:
def __str__(self):
return self.birth_nation
Autocomplete return value is a query object. If you want to see specific field in the object, write that field in your model class or change your autocomplete class return value.

Trouble accessing ForeignKey elements

I currently have two models set up in my Django app that have a ForeignKey relationship.
class Post(models.Model):
title = models.CharField(max_length=100)
body = RichTextField(config_name='awesome_ckeditor')
pub_date = models.DateTimeField('date', null=True)
description = models.CharField(max_length=100, blank=True, null=True)
photo = models.ImageField(upload_to='media/', blank=True, null=True)
def __unicode__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey(Post, related_name="comments", blank=True, null=True)
name = models.CharField(max_length=100, null=True)
comment = models.TextField(blank=True)
pub_date = models.DateField("date", blank=True, null=True)
def __unicode__(self):
return unicode(self.name)
What I am not getting is making queries between the two. I have tried making queries through the shell but to no success. If I set Post(title="Cat") and then make c = Comment(name="Dog"), I can query each models respective title or name through something like p = Post.object.get(pk=1) and p.title will output Cat. But if I do p.comment or p.comment_id, there is an error. Likewise with any Comment objects. However when I do print c.post, I get None. What am I missing in order to make p.<field_here>" =Dog`?
Since you have related name "comments", access to set foreign model from Post should be called this way:
p.comments
But since you can have many comments for a same Post, this won't return a unique value, but a related manager that you need to query. So you could get:
p.comments.filter(name="Dog")

Django, ModelManager with a query based on model property

I have this models.py:
class PieceManager(models.Manager):
def top_ten(self):
# return self.get_queryset().order_by(total_likes)
# How can I get the first n-items ordered by the property total_likes?
class Piece(models.Model):
name = models.CharField(max_length=250)
description = models.TextField(blank=True, null=True)
museum = models.ForeignKey(Museum, blank=True, null=True)
objects = PieceManager()
#property
def total_likes(self):
return self.likes.count()
class Like(models.Model):
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
piece = models.ForeignKey(Piece, blank=True, null=True, related_name="likes")
How can I get the first -items ordered by total_likes property? What is the right way to do that? There is some better way? Thanks.
As a simple search would have shown, you can't sort by the result of a property or method.
However in this case you don't need to, since you can do it much better and more efficiently with aggregation:
from django.db.models import Count
self.annotate(likes_count=Count('like')).order_by('likes_count')

Categories