For example, I have 2 models:
class User(AbstractUser):
achievement = models.ManyToManyField('Achievement')
class Achievement(models.Model):
name = models.CharField(max_length=50)
I need get all achievements of several users, i think, it should be something like this:
for user in User.objects.filter(bla-bla):
achievement_list += user.achievement
But it returns error "'ManyRelatedManager' object is not iterable"
user.achievement is a ManyRelatedManager, similar to how, say, Achievement.objects is a Manager. Try instead user.achievement.all() or user.achievement.filter(...) (with whatever filter you may want).
Related
hey guys let's say I have these models
class Object1:
.....
class Object2:
user = models.ForeignKey(User)
rel = models.ForeignKey(Object1, related_name = 'objects')
isCOmpleted = models.BooleanField()
and I wanted to perform this query:
Object1.objects.all().prefetch_related(Prefetch('objects', Object2.objects.filter(user = specific_user))).annotate(is_completed=F('objects__isCompleted'))
and the user is only related to one object from the Object2, but I got duplicate objects in my query, and I know the reason is that I have two objects from Object2 in my database for two different users, but the problem is that F expression didn't look in my prefetched query using prefetch_related method, I tried the exact same thing in the shell and it's giving me the results that I have expected but not in the view, so what's the problem here exactly any help would be really appreciated
I am creating a Django app and this questions comes to hit me again (I've already run into it but I resolved it in a way I don't think is correct).
So I have these models:
def Person(models.Model):
name = models.CharField(max_length=30)
status = models.ManyToManyField(Status)
def Status(models.Model):
name = models.CharField(max_length=30)
Any person may have up to 3 status (or none). And this was supposed to be a string array containing only a few possible status. e.g. happy, lucky, strong.
However a CharField with choices would not be possible here, as one person may feel happy and strong at the same time.
Is my current approach the best one possible?
You will need to validate the statuses count for each person in the clean method.
from django.db import models
from django.core.exceptions import ValidationError
class Status(models.Model):
name = models.CharField(max_length=30)
class Person(models.Model):
name = models.CharField(max_length=30)
status = models.ManyToManyField(Status)
def clean(self):
# check person status count
if self.status.all().count() > 3:
raise ValidationError("Person can not have more than 3 statuses")
Update
Since it's a ManyToMany relationship, you will never get this validated during the creation of the object, unless you have a separate form for adding statuses for persons.
If you have statuses field in the same form of person creation, then this check MUST be in the form.
class PersonForm(forms.ModelForm):
class Meta:
model = Person
def clean(self):
statuses = self.cleaned_data.get('status')
if status.count() > 3:
raise ValidationError("Person can not have more than 3 statuses")
Why this method
This design of models will allow you to have many different ways of querying. such as get people who are happy! or count of people who are sad and finally get people with similar statuses
Just a quick addition - if you're using PostgreSQL (and that's probably the best decision) you could also use an Array Field, for which you can specify a max size.
https://docs.djangoproject.com/en/1.8/ref/contrib/postgres/fields/
Another option is to use a tagging library like Django-taggit
I've looked through Tastypie's documentation and searched for a while, but can't seem to find an answer to this.
Let's say that we've got two models: Student and Assignment, with a one-to-many relationship between them. The Assignment model includes an assignment_date field. Basically, I'd like to build an API using Tastypie that returns Student objects sorted by most recent assignment date. Whether the sorting is done on the server or in the client side doesn't matter - but wherever the sorting is done, the assignment_date is needed to sort by.
Idea #1: just return the assignments along with the students.
class StudentResource(ModelResource):
assignments = fields.OneToManyField(
AssignmentResource, 'assignments', full=True)
class Meta:
queryset = models.Student.objects.all()
resource_name = 'student'
Unfortunately, each student may have tens or hundreds of assignments, so this is bloated and unnecessary.
Idea #2: augment the data during the dehydrate cycle.
class StudentResource(ModelResource):
class Meta:
queryset = models.Student.objects.all()
resource_name = 'student'
def dehydrate(self, bundle):
bundle.data['last_assignment_date'] = (models.Assignment
.filter(student=bundle.data['id'])
.order_by('assignment_date')[0].assignment_date)
This is not ideal, since it'll be performing a separate database roundtrip for each student record. It's also not very declarative, nor elegant.
So, is there a good way to get this kind of functionality with Tastypie? Or is there a better way to do what I'm trying to achieve?
You can sort a ModelResource by a field name. Check out this part of the documentation http://django-tastypie.readthedocs.org/en/latest/resources.html#ordering
You could also set this ordering by default in the Model: https://docs.djangoproject.com/en/dev/ref/models/options/#ordering
I'd like to find how to select all objects whose ManyToMany field contains another object. I have the following models (stripped down)
class Category(models.Model):
pass
class Picture(models.Model):
categories = models.ManyToManyField(Category)
visible = models.BooleanField()
I need a function to select all the Pictures in one or more Categories:
def pics_in_cats(cat_ids=()):
pass
BUT it needs to return a QuerySet if possible so that I can do something like:
pics_in_cats((1,2,3)).filter(visible=True)
It could be done by loading all the relevant Category objects and merging their picture_set attributes, but that seems inefficient. I'd also like to avoid falling back to raw SQL if possible.
Thanks in advance
Why write a custom function and not use something like this? (untested)
pics = Picture.objects.filter(categories__in = [1,2,3]).filter(visible=True)
I have a couple of models in django which are connected many-to-many. I want to create instances of these models in memory, present them to the user (via custom method-calls inside the view-templates) and if the user is satisfied, save them to the database.
However, if I try to do anything on the model-instances (call rendering methods, e.g.), I get an error message that says that I have to save the instances first. The documentation says that this is because the models are in a many-to-many relationship.
How do I present objects to the user and allowing him/her to save or discard them without cluttering my database?
(I guess I could turn off transactions-handling and do them myself throughout the whole project, but this sounds like a potentially error-prone measure...)
Thx!
I would add a field which indicates whether the objects are "draft" or "live". That way they are persisted across requests, sessions, etc. and django stops complaining.
You can then filter your objects to only show "live" objects in public views and only show "draft" objects to the user that created them. This can also be extended to allow "archived" objects (or any other state that makes sense).
I think that using django forms may be the answer, as outlined in this documentation (search for m2m...).
Edited to add some explanation for other people who might have the same problem:
say you have a model like this:
from django.db import models
from django.forms import ModelForm
class Foo(models.Model):
name = models.CharField(max_length = 30)
class Bar(models.Model):
foos = models.ManyToManyField(Foo)
def __unicode__(self):
return " ".join([x.name for x in foos])
then you cannot call unicode() on an unsaved Bar object. If you do want to print things out before they will be saved, you have to do this:
class BarForm(ModelForm):
class Meta:
model = Bar
def example():
f1 = Foo(name = 'sue')
f1.save()
f2 = foo(name = 'wendy')
f2.save()
bf = BarForm({'foos' : [f1.id, f2.id]})
b = bf.save(commit = false)
# unfortunately, unicode(b) doesn't work before it is saved properly,
# so we need to do it this way:
if(not bf.is_valid()):
print bf.errors
else:
for (key, value) in bf.cleaned_data.items():
print key + " => " + str(value)
So, in this case, you have to have saved Foo objects (which you might validate before saving those, using their own form), and before saving the models with many to many keys, you can validate those as well. All without the need to save data too early and mess up the database or dealing with transactions...
Very late answer, but wagtail's team has made a separate Django extension called django-modelcluster. It's what powers their CMS's draft previews.
It allows you to do something like this (from their README):
from modelcluster.models import ClusterableModel
from modelcluster.fields import ParentalKey
class Band(ClusterableModel):
name = models.CharField(max_length=255)
class BandMember(models.Model):
band = ParentalKey('Band', related_name='members')
name = models.CharField(max_length=255)
Then the models can be used like so:
beatles = Band(name='The Beatles')
beatles.members = [
BandMember(name='John Lennon'),
BandMember(name='Paul McCartney'),
]
Here, ParentalKey is the replacement for Django's ForeignKey. Similarly, they have ParentalManyToManyField to replace Django's ManyToManyField.