I have a resources like these:
models.py
class Place(models.Model):
id = models.CharField(max_length = 256, primary_key = True)
name = models.CharField(max_length = 1024)
class Review(models.Model):
id = models.CharField(max_length = 256, primary_key = True)
p_id = models.ForeignKey(Place, related_name = 'place_review')
text = models.TextField()
api.py
class ReviewResource(ModelResource):
class Meta:
queryset = Review.objects.all()
resource_name = 'place_review'
class PlaceResource(ModelResource):
place_review = fields.OneToManyField(ReviewResource,
'place_review',
full=True)
class Meta:
queryset = Place.objects.all()
resource_name = 'place'
Using above model and resource, I want to limit number of reviews in list view of Place to 3, in detail/show view I want to show more reviews (possible different style, e.g. if review contains image, show it in detail view, hide it in list view)
I have tried to put attribute=lambda bundle: Review.objects.all()[:3], but whenever I don't have any reviews for place it fails with The model '' has an empty attribute ' at 0x7f0a180d0de8>' and doesn't allow a null value. message.
What can you suggest for this case, are there any workarounds for this problem?
Related
I am trying to enable post methods in my borrowedview to enable admins, select from current users, and also select from the available books.
serializers.py
class BookListSerializer(serializers.ModelSerializer):
authors = serializers.SlugRelatedField(many = True, queryset = models.Author.objects.all(),slug_field = 'name',) #To represent the relationship as a string instead of id
genre = serializers.SlugRelatedField(many = True,queryset = models.Genre.objects.all(),slug_field = 'name')
class Meta:
model = models.Book
fields = ('name','authors','rating', 'genre')
class BorrowedSerializer(serializers.ModelSerializer):
who_borrowed = serializers.PrimaryKeyRelatedField(queryset = get_user_model().objects.all() ,source = 'who_borrowed.username',)
name = serializers.PrimaryKeyRelatedField(queryset = models.Book.objects.all(),
source = 'name.name',)
#borrowed_date = serializers.DateTimeField(format = "%H:%M, %d-%m-%Y")
#returned_date = serializers.DateTimeField(format = "%H:%M, %d-%m-%Y" )
class Meta:
model = models.Borrowed
fields = ('who_borrowed','name','has_returned','borrowed_date','returned_date',)
Then my models
models.py
class Book(models.Model):
name = models.CharField(max_length = 150,) #Name of books
authors = models.ManyToManyField(Author,)
genre = models.ManyToManyField(Genre)
publisher = models.ForeignKey(Publisher, on_delete = models.SET_DEFAULT, default = '2')
#A book should have a publisher will include a none field for books without publishers
pub_date = models.DateField()
price = models.DecimalField(max_digits = 10, decimal_places = 2)
isbn = models.CharField(max_length = 13, unique = True, null = True, blank = True,
validators = [MinLengthValidator(13)])
class Borrowed(models.Model): #Model for users borrowing and returning
name = models.ForeignKey(Book, on_delete = models.CASCADE,) #Consider making one to many field
borrowed_date = models.DateTimeField(auto_now_add = True, ) #Date is created as soon as instance is created
has_returned = models.BooleanField(default = False) #Field that determines if a model is returend or not
returned_date = models.DateTimeField(null = True, blank = True,) #Date that changes as soon as book is returned
who_borrowed = models.ForeignKey(get_user_model(), on_delete = models.SET_DEFAULT, default ='9c495b90-3900-43d1-875d-6b15d5d5ab55')
The Django browseable api shows the books to choose from and the user borrowing the book just as I want but when I want to post the request it shows the error from the title.
I don't know how to make a create method that would allow those options to show and would allow the post or put requests.
In a nutshell if I remove the source argument everything works fine, but I want the data shown not to be the Id or the UUID but the usernames and the names of the books instead.
You can refer DRF- doc.
Following changes should be enough in your case.
class BorrowedSerializer(serializers.ModelSerializer):
who_borrowed = serializers.PrimaryKeyRelatedField(queryset = get_user_model().objects.all() ,source = 'who_borrowed.username',)
name = serializers.PrimaryKeyRelatedField(queryset = models.Book.objects.all(),
source = 'name.name',)
class Meta:
model = models.Borrowed
fields = ('who_borrowed','name','has_returned','borrowed_date','returned_date',)
def create(self, validated_data):
return models.Borrowed.objects.create(**validated_data)
# or
# return super(BorrowedSerializer, self).create(validated_data)
class BorrowedSerializer(serializers.ModelSerializer):
who_borrowed = serializers.SlugRelatedField(queryset = get_user_model().objects.all(),slug_field = 'username')
name = serializers.SlugRelatedField(queryset = models.Book.objects.all(), slug_field = 'name')
Changing the "PrimaryKeyRelatedFields" to "SlugRelatedFields" also worked for me.
The message of the error the create method doesn't support writable dotted source fields by default is refering to name.name in the source argument of the customized serializer field,
so other ways to solve this are :
1. add a readonly=True in your new field
2. delete the customized field, so you get back to the id instead of the name.
I tried to use Django's Modelviewset to implement the comment function, but there was a problem.
model :
class Comment(models.Model):
created = models.DateTimeField(auto_now_add= True)
content = models.CharField(max_length = 255, null = True)
author = models.ForeignKey(User, on_delete= models.CASCADE, null = True)
writer = models.CharField(max_length = 255, null = True)
class Meta:
abstract = True
ordering = ['-id']
class TalkComment(Comment):
title = "talk"
post = models.ForeignKey(Talk, on_delete= models.CASCADE, null = True)
serializers :
class TalkCommentSerializer(serializers.ModelSerializer):
class Meta:
model = models.TalkComment
fields = '__all__'
view :
class TalkCommentViewset(viewsets.ModelViewSet):
queryset = models.TalkComment.objects.all()
serializer_class = serializers.TalkCommentSerializer
url :
router.register(r'talk/(?P<id>\d+)/comment', postview.TalkCommentViewset)
/api/talk/2/comment/
All I wanted was to get the comments from that one post, but all the comments are coming.
How can I get a specific comment from a specific post?
You're getting all of the comments cause you initialized queryset to return all of the commnents. For getting comments of one specific post you must change the queryset. To do that you must override get_queryset method (cause you need to get post_id argument from request):
class TalkCommentViewset(viewsets.ModelViewSet):
serializer_class = serializers.TalkCommentSerializer
def get_queryset(self):
post_id = self.kwargs["id"]
queryset = TalkComment.objects.filter(post__id=post_id)
return queryset
I m trying to make a form on the basis of a model. Trouble is that when i create a category via django shell, let's say "Wedding" category, having id=1 and name = "weddings", when i display it in a dropdown(in html form) it shows as Categories object (1) and i would like it to be shown by the name, which is weddings.
As in the documentation i understand that i can attach labels when in the Meta form class but i don't fully understand how i can display dynamically all the category names instead of Categories object 1,2,3,4.
Models.py
class categories(model.Model):
id = models.AutoField(primary_key =True)
name = models.Charfield(max_length = 50)
class Event(models.Model):
id = models.AutoField(primary_key =True)
category = models.ForeignKey(Categories,on_delete=models.SET_NULL,null = True)
owner = models.Charfield(max_length = 50)
Forms.py
class EventForm(forms.ModelForm):
class Meta:
model = Event
fields = ['category','person','owner']
So the actual result when rendering the form is :
Category:(dropdown) - Categories object (1)
Desired result:
Category:(dropdown) - weddings
class categories(model.Model):
id = models.AutoField(primary_key =True)
name = models.Charfield(max_length = 50)
def __str__(self):
return self.name
class Event(models.Model):
id = models.AutoField(primary_key =True)
category = models.ForeignKey(Categories,on_delete=models.SET_NULL,null = True)
owner = models.Charfield(max_length = 50)
def __str__(self):
return self.owner
just add this little magic functions to your model classes.
I have the following models
class STUser(AbstractBaseUser):
email = models.EmailField(unique=True)
name = models.CharField(max_length=255)
companyname = models.CharField(max_length=200, blank=True, null=True)
...
class VenuePermissions(models.Model):
user = models.ForeignKey(STUser, on_delete=models.CASCADE)
venue = models.ForeignKey(Venue, on_delete=models.CASCADE)
signupvaildatestring = models.CharField(max_length=200, blank=True, null=True)
...
I want to grab all the STUser objects and grab all their permissions.
So what I would like is to grab all the VenuePermissions objects. And grab the user and venue object of each venuePermission
Two ways I can do this. use the VenuePermissions_set attribute on STUser but then how do I grab the venue when its just going to be a pk value?
Or focus on the VenuePermissions objects and grab the user and venue from the pk values but how?
I remember nested queries, and I kinda did one in my browse code.
here is an example:
rooms = Room.objects.filter(venue=OuterRef('pk'), sixtyroundseatingoption= True)
venuelist = venuelist.annotate(sixtyrounds=Exists(rooms))
venuelist = venuelist.filter(Q(sixtyrounds = True) | Q(fullbuyoutsixtyroundseatingoption = True))
I've done the set objects in a serializer before
Example serializer:
class RoomAndImageSerializer(serializers.ModelSerializer):
roomimage_set = RoomImageSerializer(many=True, read_only=True)
class Meta:
model = Room
fields = ('pk','name')
any help with this query would be appreciated!
So this is what I am currently trying, I will post an answer if this works:
class VenueUserList(ListAPIView):
serializer_class = VenueUserListSerializer
queryset = VenuePermissions.objects.select_related('user').select_related('venue').filter(signupvaildatestring=None)
class VenueUserListSerializer(serializers.ModelSerializer):
user = UserSerializer()
venue = VenueSerializer()
class Meta:
model = VenuePermissions
fields = ('user', 'venue', 'isvenueviewer', 'isvenueeventplanner', 'isvenueadministrator')
Here is the answer. However I still need to group venues by user. Working on that.
class VenueUserList(ListAPIView):
serializer_class = VenueUserListSerializer
queryset = VenuePermissions.objects.select_related('user').select_related('venue').filter(signupvaildatestring=None)
class VenueUserListSerializer(serializers.ModelSerializer):
user = UserSerializer()
venue = VenueSerializer()
class Meta:
model = VenuePermissions
fields = ('user', 'venue', 'isvenueviewer', 'isvenueeventplanner', 'isvenueadministrator')
models.py
class DailyRecordManager(models.Manager):
def get_query_set(self):
qs = super(DailyRecordManager, self).get_query_set().order_by('date_organised')
return qs
class DailyRecord(models.Model):
date_organised = models.DateField('Ogransied Date', help_text=('Enter Date when the program is organised: CCYY-MM-DD'))
program_name = models.TextField('program name',)
venue = models.CharField('venue', max_length = 255, blank=True)
organiser = models.ForeignKey(Organiser, verbose_name = 'Organiser', related_name = 'organisers')
objects = models.Manager()
public = DailyRecordManager()
class Meta:
verbose_name = 'dailyrecord'
verbose_name_plural = 'dailyrecords'
ordering = ['-date_organised']
def __str__(self):
return self.program_name
class Participant(models.Model):
participant = models.CharField(max_length= 50, unique = True)
daily_record = models.ForeignKey(DailyRecord, verbose_name = 'program_name')
class Meta:
verbose_name = 'participant'
verbose_name_plural = 'participants'
def __str__(self):
return self.participant
views.py
class DailyActivityPageView(SingleTableView):
table_class = DailyRecordTable
queryset = DailyRecord.public.all()
# queryset = Participant(DailyRecord.public.all()) is not working
template_name = 'dailyrecord/daily-activity-record.html'
tables.py
class DailyRecordTable(tables.Table):
date_organised = tables.Column('Date')
program_name = tables.Column( 'Program Name')
venue = tables.Column( 'Venue')
organiser = tables.Column( 'Organiser')
participant = tables.Column( 'dailyrecord.participant')
# daily = tables.RelatedLinkColumn()
class Meta:
model = DailyRecord
Now what I need is to display the data from participant table too, corresponding to the daily_record foreign key.
Click this link to view the snapshot. see the last column of the table. I need the data of Participant.partcipant column here
Sorry for poor English.
Thank You
There are two problems here.
First is, that a daily record can have multiple participants. Thus, in order to fill last column you have to aggregate all possible participants into that column (for example as list).
Second is, that you should make Participant backwards related to DailyRecord by adding attribute "related_name" to daily_record in your Participant model, like this:
daily_record = models.ForeignKey(DailyRecord, verbose_name = 'program_name', related_name="participants")
Now, you should simply get participants from daily_record like this:
participants = DailyRecord.public.first().participants.all()
If you had OneToOneField instead of ForeignKey you could add (single) participant to table like this:
participant = tables.Column( "Participant", accessor='participant')