Django: How to get a model class field from other model class? - django

I am working on my model classes, trying to get a class field from other class, but I am stuck on this.
Here are the classes:
class Cliente(models.Model):
nome = models.CharField(max_length=100, blank=True)
endereco = models.CharField(max_length=100, blank=True)
telefone = models.CharField(unique=True, max_length=10)
data = models.DateField()
def __unicode__(self):
return self.nome
I would like to get the "nome" field from the next class:
class Pedido(models.Model):
idcliente = models.ForeignKey(Cliente, db_column='idCliente')
def __unicode__(self):
return Cliente.objects.get(id=idcliente).nome, Pedido.id
This last method unicode doesn't get the nome from the Client object.
Also, I would like to get the id(primary key), that is not declared in the model, but the field is actually already created in the table. But I don't know how to get both fields.
Anyone please would help me get this thing to work?
Thanks a lot!!

You just have to follow the foreign key field like this:
class Pedido(models.Model):
idcliente = models.ForeignKey(Cliente, db_column='idCliente')
def __unicode__(self):
return self.idcliente.nome, self.id
The Django ORM will automatically perform a database lookup if required to required to load the appropriate Cliente row.
This will get the nome and the id.

Related

How do I access instance of a many-to-many field in django __str__ method

I am having two models;
class Cart(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE, related_name="book")
quantity = models.PositiveIntegerField(default=1, null=True, blank=True)
def __str__(self):
return f"{self.quantity} of {self.book.title}"
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
cart = models.ManyToManyField(Cart)
def __str__(self):
return f"{self.cart.quantity}"
I get:
'ManyRelatedManager' object has no attribute 'quantity'
This usually works for a ForeignKey field; but it seems not to for a ManyToManyField.
Note: I am trying to access quantity that belongs to the cart model from the Order model using ManyToManyField.
Is there any way of doing something like this?
self.cart returns 'ManyRelatedManager'.
you have to write something like this:
self.cart.last().quantity
# OR
self.cart.first().quantity
or get sum of all, with self.cart.all()
sum([_.quantity for _ in self.cart.all()])

Proxy model for Multiple models in Django

I would like to display a model in the django admin but with the logic to choose between 2 models to display.
Current Implementation:
Models
class User(models.Model):
created = models.DateTimeField(auto_now_add=True, null=True)
last_updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=30, blank=True)
class ExpectedNames(User):
class Meta:
proxy=True`
Admin
#admin.register(ExpectedNames)
class ExpectedNamesAdmin(admin.ModelAdmin):
date_hierarchy = 'created'
What I Would like to DO: # something like this
Models
class User(models.Model):
created = models.DateTimeField(auto_now_add=True, null=True)
last_updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=30, blank=True)
class User2(models.Model):
created = models.DateTimeField(auto_now_add=True, null=True)
last_updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=30, blank=True)
class ExpectedNames(User):
class Meta:
proxy=True
if name == "Rick":
return User
else:
return User2
Admin
#admin.register(ExpectedNames)
class ExpectedNamesAdmin(admin.ModelAdmin):
date_hierarchy = 'created'
Any suggestions not sure if this is the correct way to do this.
I think this is not possible as it states in the Django Documentation:
Base class restrictions:
A proxy model must inherit from exactly one non-abstract model class. You can’t inherit from multiple non-abstract models as the proxy model doesn’t provide any connection between the rows in the different database tables. A proxy model can inherit from any number of abstract model classes, providing they do not define any model fields. A proxy model may also inherit from any number of proxy models that share a common non-abstract parent class.
https://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models
I use magic method new in same situation.
I have model Documen with field document_type. If document_type is 'contract' i want ContractProxy, if 'offer' - OfferProxy.
For do this I create new proxy:
class RelatedDocumentProxy(Document):
class Meta:
proxy = True
def __new__(cls, *args, **kwargs):
doc_type = args[1]
if doc_type == 'contract':
return ContractProxy(*args, **kwargs)
return OfferProxy(*args, **kwargs)
document_type is first field and will first arg who pass to method

Local field 'created_at' in class 'BandRating' clashes with field of the same name from base class 'Rating'

I've recently tried to create two separate models inheriting from Rating but upon migration I get the error mentioned in the title. I assume this is due to rogue migrations as it seems that there should be no clashes in my code? I initially had Rating which had two optional fields, Venue or Band but I feel this is better structure.
For future reference, what would be the ideal way to do this without running into this kind of issue?
class Rating(models.Model, Activity):
created_at = models.DateTimeField(auto_now_add=True, null=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
rating = models.IntegerField(default=0)
description = models.CharField(max_length=200, null=True)
class Meta:
abstract = True
def get_author(self):
if self.author is None:
return "Anonymous"
else:
return self.author
#property
def activity_actor_attr(self):
return self.author
class BandRating(Rating):
band = models.ForeignKey(Band)
def __str__(self):
return str(self.band) + " rating"
class VenueRating(Rating):
venue = models.ForeignKey(Venue)
def __str__(self):
return str(self.venue) + " rating"
It seems that you are trying to "hide" the Rating.created_at field which is declared in the Activity model from which you inherit - that's not possible when inheriting from a non-abstract model.
More info here:
https://docs.djangoproject.com/en/dev/topics/db/models/#field-name-hiding-is-not-permitted

Django model primary key as a pair

I am trying to make an app where users will login to their profile and can add songs to their favorite list. I am defining a M2M relationship for this.
My question is how to say combination of (song, singer) is unique?
I searched and found that it may be possible through unique_together. Is this the correct way of setting this?
models.py:
from django.contrib.auth.models import User
class Singer(models.Model):
name = models.CharField(max_length=500, unique=True)
def __str__(self):
return self.name
class Song(models.Model):
id = models.AutoField(primary_key=False)
singer = models.ForeignKey(Singer, on_delete=models.CASCADE, related_name='song')
name = models.CharField(max_length=500)
Class Meta:
unique_together = (singer, id)
def __str__(self):
return self.name
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
songs = models.ManyToManyField(Song, related_name='profile')
def __str__(self):
return self.user.username
Please feel free to correct my models.py, if you think the relationship is not correct.
Thanks,
I would use a default primary key (auto field), and use the meta class property, unique_together
class Song(models.Model):
singer = models.ForeignKey(Singer, on_delete=models.CASCADE, related_name='song')
name = models.CharField(max_length=500)
class Meta:
unique_together = (("singer", "name"),)
It would act as a "surrogate" primary key column.
You don't specify id in your model song. I would also recommend to use slug field of django and specify unique on the same. Just in case you have two singers with the same name. Then the second or more you put like abc, abc-1, abc-2, in which case you don't have to change the name and unique_together clause works just fine.
class Song(models.Model):
singer = models.ForeignKey(Singer, on_delete=models.CASCADE, related_name='song')
name = models.CharField(max_length=500)
class Meta:
unique_together = (("singer", "name"),)
def __str__(self):
return self.name

Correct way of getting count on FK

What is the correct way of getting the 'contact' count from within my 'Group'?
I was thinking of just creating a new method within 'group' and filter(), but this means hitting the db again which seems bad, right?
class GroupManager(models.Manager):
def for_user(self, user):
return self.get_query_set().filter(user=user,)
class Group(models.Model):
name = models.CharField(max_length=60)
modified = models.DateTimeField(null=True, auto_now=True,)
#FK
user = models.ForeignKey(User, related_name="user")
objects = GroupManager()
def get_absolute_url(self):
return reverse('contacts.views.group', args=[str(self.id)])
class Contact(models.Model):
first_name = models.CharField(max_length=60)
last_name = models.CharField(max_length=60)
#FK
group = models.ForeignKey(Group)
group_object.contact_set.count() should do it. Django creates the relation by adding _set to the end of the foreign key's model name.
Have a look at the docs on related objects for more info.