FilterSet for ManyToMany relationship existence - django-filter

Basic models:
class ModelA(Model):
name = CharField(...)
class ModelB(Model):
model_a = ManyToManyField(ModelA, blank=True)
class ModelBFilter(filters.FilterSet):
unassigned = BooleanFilter(field_name='model_a', lookup_expr='isnull')
class Meta:
model = ModelB
fields = ['unassigned']
How do I filter (with django-filter) to find the ModelB's that do not have a corresponding related model?

It looks to me that what you have should work. Perhaps the fields = ['unassigned'] is unnecessary? According to the documentation you can also negate the filter thusly:
class ModelBFilter(filters.FilterSet):
assigned = BooleanFilter(field_name='model_a', lookup_expr='isnull', exclude=True)
class Meta:
model = ModelB

Related

Why is my Django serializer telling me an attribute doesn't exist when I see it defined in my model?

I'm using Python 3.7 and the Django rest framework to serialize some models into JSOn data. I have this
data = {
'articlestats': ArticleStatSerializer(articlestats, many=True).data,
and then I have defined the following serializers ...
class LabelSerializer(serializers.ModelSerializer):
class Meta:
model = Label
fields = ['name']
...
class ArticleSerializer(serializers.ModelSerializer):
label = LabelSerializer()
class Meta:
model = Article
fields = ['id', 'title', 'path', 'url', 'label']
class ArticleStatSerializer(serializers.ModelSerializer):
article = ArticleSerializer()
class Meta:
model = ArticleStat
fields = ['id', 'article', 'score']
I have defined my Label model like so ...
class Label(models.Model):
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class Meta:
unique_together = ("name",)
but I'm getting this error when Django processes my serialize line ...
AttributeError: Got AttributeError when attempting to get a value for field `name` on serializer `LabelSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `str` instance.
Original exception text was: 'str' object has no attribute 'name'.
Not sure why it's complaining. The "name" attribute is right there. What else should I be doing?
Edit: Models asked for ...
class ArticleStat(models.Model):
objects = ArticleStatManager()
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articlestats')
score = models.FloatField(default=0, null=False)
class Article(models.Model):
objects = ArticleManager()
title = models.TextField(default='', null=False)
path = models.TextField(default='', null=False)
url = models.TextField(default='', null=False)
label = models.TextField(default='', null=True)
created_on = models.DateTimeField(db_index=True, default=datetime.now)
In Article model the label field is TextField, not any kind of related fields. But in your serializer, it expects a related field.
class ArticleSerializer(serializers.ModelSerializer):
label = LabelSerializer()
class Meta:
model = Article
fields = ['id', 'title', 'path', 'url', 'label']

Django CheckboxSelectMultiple widget : render only selected data by default

Greeting, I have a manytomany field call user in my model_A model, in my form, how can I display only the list of selected data associated to the model_A by default instead of listing entire entries from the User model in my html page? my intention is to create a setting page where I can remove the user associated to a project
below is my code :
model.py :
class model_A(models.Model):
user = models.ManyToManyField(User, blank=True)
form.py :
class EditForm(forms.ModelForm):
prefix = 'edit_form'
class Meta:
model = model_A
fields = '__all__'
widgets = {'user':forms.CheckboxSelectMultiple}
html :
<div class="field">
{{form.user}}
</div>
Any help is much appreciated thanks
Change user queryset inside __init__ method of EditForm class.
class EditForm(forms.ModelForm):
prefix = 'edit_form'
class Meta:
model = model_A
fields = '__all__'
widgets = {'user':forms.CheckboxSelectMultiple}
def __init__(self, **kwargs):
self.event = kwargs.pop('event')
super().__init__(**kwargs)
# replace dots with your conditions in filter
self.fields['user'].queryset = self.user.filter(...)
UPDATE
List users that are associated with Model_A
self.fields['user'].queryset = self.user.all()

How to implement ForeignKey with Django serializer

I have this models:
class Discipline(models.Model):
name = models.CharField(max_length=200)
class Lesson(models.Model):
discipline = models.ForeignKey(Discipline, on_delete=models.CASCADE, null=True)
date = models.DateField()
regular_slot = models.BooleanField(default=False)
And these serializers:
class DisciplineSerializer(serializers.ModelSerializer):
class Meta:
model = Discipline
fields = ('name')
class LessonSerializer(serializers.ModelSerializer):
discipline = serializers.RelatedField(source='Discipline', read_only=True);
class Meta:
model = Lesson
fields = ('discipline', 'date', 'regular_slot')
I have a view to process a JSON request and to save the data:
def cours_list(request):
if request.method == 'POST':
data = JSONParser().parse(request)
serializer = LessonSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JSONResponse(serializer.data, status=201)
return JSONResponse(serializer.errors, status=400)
My JSON request is as follows:
{"discipline":"Mathematiques","date":"2017-12-03"}
However, I have an error saying that:
'Lesson' object has no attribute 'Discipline'
I believe this is because attribute discipline in Lesson refers only to the id and is not of type Discipline. I could'nt find how to solve this. Is the way I define foreignKey is not correct ?
How to insert a foreignKey reference here while I receive a Discipline object from the JSON request ?
I'm going to help you also with this :)
class DisciplineSerializer(serializers.ModelSerializer):
class Meta:
model = Discipline
fields = ('name')
class LessonSerializer(serializers.ModelSerializer):
discipline = DiscliplineSerializer()
class Meta:
model = Lesson
fields = ('discipline', 'date', 'regular_slot')
Doing this is enough as far as I know.
Edit: Reason of your error is that you write "source="Discipline"" but there is no field named Discipline in your Lesson model. Therefore, it gives an error.

Django REST - Resolving Foreign Keys and M2M's in a Serializer

I have the following Models:
class Player(models.Model):
name = models.CharField(max_length=30)
class Achievement(models.Model):
name = models.CharField(max_length=30)
class UnlockedAchievement(models.Model):
achievement = models.ForeignKey(Achievement)
date = models.DateTimeField()
class PlayerAchievements(models.Model):
player = models.ForeignKey(Player)
unlocked_achievements = models.ManyToManyField(UnlockedAchievement, related_name="unlocked_achievements", blank=True, null=True)
With a PUT, I'm trying to resolve both the Player's foreign key as well as the nested relationship of all the Achievements. My JSON data effectively looks like this:
{"name":"playername",
"achievements":
{
"ach1":"timestamp",
"ach2":"timestamp",
}
}
What I can't figure out is the magic combination of which kinds of Serializers to use and, when using them, which serializer fields or nested Serializers to use to be able to resolve Players by name, and the unlocked achievements (and then their Achievement foreign keys) by providing a name.
In this case I don't have access to id numbers, hence why things are done by names.
Such a strange mixture it seems. Can anyone lend a hand? Thanks in advance!
You can use nested relationships to fully include the serialization of a related model:
class AchievementSerializer(serializers.ModelSerializer):
class Meta:
model = Achievement
class UnlockedAchievementSerializer(serializers.ModelSerializer):
achievement = AchievementSerializer(many=False)
class Meta:
model = UnlockedAchievement
class PlayerAchievementsSerializer(serializers.ModelSerializer):
unlocked_achievements = UnlockedAchievementSerializer(many=True)
class Meta:
model = PlayerAchievements
class PlayerSerializer(serializers.ModelSerializer):
player_achievements = PlayerAchievementsSerializer(many=False)
class Meta:
model = Player
Then just filter the Player object by name and serialize it.

Backbone-Relational and Django-Tastypie: many-to-many fields operating example

May somebody provide an example of operating with many-to-many fields of django.db models' instances through django-tastypie and backbone-relational? That's possible now with using intermediate model.
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=42)
class Book(models.Model):
authors = models.ManyToManyField(Author, related_name='books', through='Authorship')
title = models.CharField(max_length=42)
class Authorship(models.Model):
author = models.ForeignKey(Author)
book = models.ForeignKey(Book)
Here are possible tastypie resources' configuration:
from tastypie import fields, resources
class AuthorResource(resources.NamespacedModelResource):
books = fields.ToManyField('library.api.resources.AuthorshipResource', 'books')
class Meta:
resource_name = 'author'
queryset = models.Author.objects.all()
class BookResource(resources.NamespacedModelResource):
authors = fields.ToManyField('library.api.resources.AuthorshipResource', 'authors')
class Meta:
resource_name = 'book'
queryset = models.Book.objects.all()
class AuthorshipResource(resources.NamespacedModelResource):
author = fields.ToOneField('library.api.resources.AuthorResource', 'author')
book = fields.ToOneField('.api.resources.BookResource', 'book')
class Meta:
resource_name = 'authorship'
queryset = models.Authorship.objects.all()
How to save Author related with a few unsaved yet Books using one request to our server?