I have two Models:
class Category(MPTTModel):
name = models.CharField(max_length=50,unique=True)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
def __unicode__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=50)
categories = models.ManyToManyField(Category,related_name='products')
def __unicode__(self):
return self.name
The categories follow a tree like structure and I want to add products only to 'leaf categories'.
When I call my_category.products.create(...) or similar and my_category.is_leaf_node() == False then it should fail.
The same for my_category.children.create(...) if my_category has products already then it should fail.
Those checks go in the save method? in a custom manager? or some where else? I would the verification to be at model level.
The proper location for model-level validation is in the clean() function. You can raise a django.core.exceptions.ValidationError here to describe your error. Have a look at the documentation for clean()
Related
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()])
I have been playing around with Django's many to many field with the following models:
class ProjectLanguage(models.Model):
title = models.CharField(max_length=15)
def __str__(self):
return self.title
class Project(models.Model):
title = models.CharField(max_length=30)
img = models.CharField(max_length=50)
main_text = models.TextField(default="main project description ...", null=True, blank=True)
languages = models.ManyToManyField(ProjectLanguage)
def __str__(self):
return self.title
I want to get a list of projects ordered by their ProjectLanguage title. How do I achieve this with Django ?
Thanks
Mark
You can define a method like this:
class Project(models.Model):
...
def ordered_languages(self):
return self.languages.all().order_by('title')
Or you may want to use a through table with ordering.
I'm working on a Django project generated via Mezzanine. I've been able to create my models, however I want to have a form where an admin can select from a list to assign a value in a many to many or a one to many relationship. For example, I have a model for Schemas:
class Schema(AutoCreatedUpdatedMixin, SoftDeleteMixin):
"""List of all Schemas in a given database"""
name = models.CharField(max_length=128, null=False)
status = models.BooleanField(max_length=128, null=False, default=True, verbose_name="Is Active")
description = models.CharField(max_length=65535, null=True, blank=True, default=None)
database = models.ForeignKey(Database, on_delete=models.CASCADE)
pull_requests = models.ManyToManyField(Link)
questions = models.ManyToManyField(Question, blank=True)
comments = models.ManyToManyField(Comment, blank=True)
technical_owners = models.ManyToManyField(Employee, related_name='technical_owners_schemas', blank=True)
business_owners = models.ManyToManyField(Employee, related_name='business_owners_schemas', blank=True)
watchers = models.ManyToManyField(Employee, related_name='watchers_schemas', blank=True)
def __unicode__(self):
return "{}".format(self.name)
And I have a model for Employees
class Employee(AutoCreatedUpdatedMixin, SoftDeleteMixin):
"""List of people with any involvement in tables or fields: business or technical owners, developers, etc"""
name = models.CharField(max_length=256, blank=False, null=False, default=None, unique=True)
email = models.EmailField(blank=True, null=True, unique=True)
def __unicode__(self):
return "{}".format(self.employee)
An employee can own multiple schemas and a schema can be owned by multiple employees. My database has an active employee in it, however when I try to create a Schema the employee shows up as Employee Object. Rather I would want the form to show the Employee.name. How can I do this? My admin file contains the following:
class SchemasAdmin(admin.ModelAdmin):
list_display = ['name', 'status', 'database', 'description']
ordering = ['status', 'database', 'name']
actions = []
exclude = ('created_at', 'updated_at', 'deleted_at')
First of all are you using python 2 or 3? For 3, the __str__ method should be used instead of __unicode__. I am writing this because it seems that there's a problem with the __unicode__ method of Employee, which although is defined as:
def __unicode__(self):
return "{}".format(self.employee)
th Employee class does not have an employee attribute (unless there's such an attribute in the mixins that class inherits from (AutoCreatedUpdatedMixin, SoftDeleteMixin) but I don't think that is the case.
In any case, the problem is that you haven't defined a propery __str__ (if using python 3) or __unicode__ (for python 2) method on the Employee class - just define it like:
return self.name
and you should see the employee's name in the django admin select fields.
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
class Categories(models.Model):
id = models.ForeignKey('auth.User',primary_key=True)
name = models.CharField(max_length=100)
description = models.CharField(max_length=300)
def __str__(self):
return Categories.name
class Meta:
order_with_respect_to = 'id'
class Specializations(models.Model):
id = models.ForeignKey('auth.User',primary_key=True)
name = models.CharField(max_length=100)
description = models.CharField(max_length=300)
categories = models.ForeignKey(Categories, on_delete=models.CASCADE)
def __str__(self):
return Specializations.name
courses.Categories.id: (fields.W342) Setting unique=True on a ForeignKey has the same effect as using a OneTo
OneField.
HINT: ForeignKey(unique=True) is usually better served by a OneToOneField.
courses.Courses.id: (fields.W342) Setting unique=True on a ForeignKey has the same effect as using a OneToOne
Field.
HINT: ForeignKey(unique=True) is usually better served by a OneToOneField.
courses.Specializations.id: (fields.W342) Setting unique=True on a ForeignKey has the same effect as using a
OneToOneField.
This warning or error raises although the relation is one to many !! not one to one
The way you designed your models it is essentially a OneToOne relationship, because you set the ForeignKey to be the primary_key (this automatically aplies unique=True).
Do you really want to the user to be the primary_key of Categories or Specializations?
I think you want something like this:
class Categories(models.Model):
user = models.ForeignKey('auth.User')
name = models.CharField(max_length=100)
description = models.CharField(max_length=300)
def __str__(self):
return self.name
class Specializations(models.Model):
user = models.ForeignKey('auth.User')
name = models.CharField(max_length=100)
description = models.CharField(max_length=300)
categories = models.ForeignKey(Categories, on_delete=models.CASCADE)
def __str__(self):
return self.name
With this a User can have many Categories and Specializations
I also changed the __str__ method to self.name