Angulary and Django REST - angularjs

How can I filtred my queryset?
Simply example:
.controller('TViewController', ["$scope", "$stateParams", "Ad", "Banner", function($scope, $stateParams, Ad, Banner) {
$scope.ad = Ad.get({ ad_id: $stateParams.ad_id });
$scope.banners = Banner.query();
}])
And
class CBanner(models.Model):
image = models.ImageField(upload_to="img")
ad = models.ForeignKey(CAds, null=True, blank=True)
class CADs(models.Model):
name = models.CharField(max_length=80, null=True, blank=True)
They both have viewset, serializer and routing register
class AdsViewer(viewsets.ModelViewSet):
queryset = CADs.objects.all()
serializer_class = AdsSerializer
etc...
How can I filtered this: $scope.banners = Banner.query(); to get only banners with ad(foreignKey) = ad_id?

You need to add a query parameter to your url, such as:
http://example.com/api/ads/?ad_fk=5
In AdsViewer:
def get_queryset(self):
"""
This view should return a list of all the ads filtered with proper foreign key
"""
ad_fk = self.request.query_params.get('ad_fk', None)
return CADs.objects.filter(ad=ad_fk)
For more info see the doc

Related

Django Post request for many to many field ValueError

I am working on a post request in which the user chooses from a list of tags and makes combinations of tags. The combination of tags should then be posted. Nothing should get changed in the Tag table.
These are the models:
models.py
class Tag(models.Model):
name = models.CharField(max_length=256)
language = models.CharField(max_length=256)
objects = models.Manager()
def __str__(self):
"""Return a human readable representation of the model instance."""
return self.name or ''
#property
def tags(self):
tags = self.tagging.values('tag')
return tags.values('tag_id', 'tag__name', 'tag__language')
class Combination(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
gameround = models.ForeignKey(Gameround, on_delete=models.CASCADE, null=True)
resource = models.ForeignKey(Resource, on_delete=models.CASCADE, null=True)
tag_id = models.ManyToManyField(Tag, null=True)
created = models.DateTimeField(editable=False)
score = models.PositiveIntegerField(default=0)
objects = models.Manager()
def __str__(self):
return str(self.tag_id) or ''
This is the serializer for Combination.
serializers.py
class CombinationSerializer(serializers.ModelSerializer):
tag_id = TagWithIdSerializer(many=True, required=False, write_only=False)
resource_id = serializers.PrimaryKeyRelatedField(queryset=Resource.objects.all(),
required=True,
source='resource',
write_only=False)
gameround_id = serializers.PrimaryKeyRelatedField(queryset=Gameround.objects.all(),
required=False,
source='gameround',
write_only=False)
user_id = serializers.PrimaryKeyRelatedField(queryset=CustomUser.objects.all(),
required=False,
source='user',
write_only=False)
class Meta:
model = Combination
depth = 1
fields = ('id', 'user_id', 'gameround_id', 'resource_id', 'tag_id', 'created', 'score')
def create(self, validated_data):
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
score = 0
tag_data = validated_data.pop('tag_id', None)
combination = Combination(
user=user,
gameround=validated_data.get("gameround"),
resource=validated_data.get("resource"),
created=datetime.now(),
score=score
)
combination.save()
for tag_object in tag_data[0]:
combination.tag_id.add(tag_object)
return combination
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['tag_id'] = TagWithIdSerializer(instance.tag_id.all(), many=True).data
return rep
I have tried posting the following JSON object to the database:
{
"gameround_id": 2015685170,
"resource_id": 327888,
"tag_id": [{"id": 2014077506, "name": "corwn","language": "en"}]
}
I am getting a ValueError: Field 'id' expected a number but got 'name'.
How can I fix this issue?
you need to provide tag id for each tag not all tag data,
Try like this
{
"gameround_id": 2015685170,
"resource_id": 327888,
"tag_id": [2014077506,2014077507]
}

__str__ returned non-string (type Category). when I add post from admin

After I added user and date_added in the Photo models, when I add post from admin its throws me an error saying: str returned non-string (type Category), when I click on the addpost link in the home template its throw another error: 'tuple' object has no attribute 'name'. how can I solve that ?
the models.py:
from django.db import models
from cloudinary.models import CloudinaryField
from django.contrib.auth.models import User
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=100, null=False, blank=False)
def __str__(self):
return self.name
class Photo(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True,
blank=True)
image = CloudinaryField('image')
description = models.TextField(null=True)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.category
the view.py file:
def home(request):
category = request.GET.get('category')
if category == None:
photos = Photo.objects.all()
else:
photos = Photo.objects.filter(category__name=category)
categories = Category.objects.all()
context = {'categories': categories, 'photos': photos}
return render(request, 'home.html', {'categories': categories, 'photos': photos} )
def viewPhoto(request, pk):
photo = Photo.objects.get(id=pk)
return render(request, 'photo.html', {'phpto': photo})
class PostCreativeView(LoginRequiredMixin, CreateView):
model = Photo, Category
fields = ['description', 'image', 'category', 'name']
template_name = 'post_create.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super (PostCreativeView, self).form_valid(form)
Well it has to do with your category name and model you added into post create view.py and so you
have do something like this:
views.py
class PostCreativeView(LoginRequiredMixin, CreateView):
model = Photo
fields = ['description', 'image', 'category']
template_name = 'post_create.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super (PostCreativeView, self).form_valid(form)
#.......
# Models.py
class Photo(models.Model):
#>>>...
def __str__(self):
return str(self.category)
You should return the str(…) of the category, so:
class Photo(models.Model):
# …
def __str__(self):
return str(self.category)

How do i access another column from related table other than the foreign key, when creating an API view

Im using django for a web app and i am creating REST API views. Is there a way i can access two tables in one view? If not, how can can i retrieve a non-foreign key column from a related record. The below code is retrieving a vase record based on a URL parameter. I want to access the artistName which is stored in artist table (a one-to-many with Vase table), not artist_id which is stored in Vase
class FilterVases(generics.ListAPIView):
serializer_class = VaseSerializer
def get_queryset(self):
queryset = Vase.objects.all()
artist_id = self.request.query_params.get('artist_id')
if artist_id is not None:
queryset = queryset.filter(artist_id=artist_id)
vaseID = self.request.query_params.get('vaseID')
if vaseID is not None:
queryset = queryset.filter(vaseID=vaseID)
return queryset
edited to add
This is models for Artist and Vase:
class Artist(models.Model) :
artistID = models.CharField(max_length=10)
artistName = models.CharField(max_length=100)
class Vase(models.Model):
vaseID = models.CharField(max_length=10)
vaseRef = models.CharField(max_length=255,blank=True,null=True)
inscription = models.CharField(max_length=255,blank=True,null=True)
fabric = models.CharField(max_length=100, blank=True,null=True)
subject = models.CharField(max_length=255,blank=True,null=True)
technique = models.CharField(max_length=100,blank=True,null=True)
height = models.FloatField(max_length=100,blank=True,null=True)
diameter = models.FloatField(max_length=100,blank=True,null=True)
shape = models.ForeignKey(Shape, on_delete=models.CASCADE)
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
provenance = models.ForeignKey(Provenance, on_delete=models.CASCADE)
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
In the Vase model add this:
def artist_name(self):
return self.artist.artistName
Hence, it will look like:
class Vase(models.Model):
vaseID = models.CharField(max_length=10)
vaseRef = models.CharField(max_length=255,blank=True,null=True)
inscription = models.CharField(max_length=255,blank=True,null=True)
fabric = models.CharField(max_length=100, blank=True,null=True)
subject = models.CharField(max_length=255,blank=True,null=True)
technique = models.CharField(max_length=100,blank=True,null=True)
height = models.FloatField(max_length=100,blank=True,null=True)
diameter = models.FloatField(max_length=100,blank=True,null=True)
shape = models.ForeignKey(Shape, on_delete=models.CASCADE)
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
provenance = models.ForeignKey(Provenance, on_delete=models.CASCADE)
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
def artist_name(self):
return self.artist.artistName
In the VaseSerializer add the 'artist_name' to the fields Meta.
If you want to add this custom fields to all Vase Model fields, refer to this topic Django Rest framework, how to include '__all__' fields and a related field in ModelSerializer ?
class VaseSerializer(serializers.ModelSerializer):
class Meta:
model = models.Vase
fields = '__all__'
extra_fields = ['artist_name']
def get_field_names(self, declared_fields, info):
expanded_fields = super(VaseSerializer, self).get_field_names(
declared_fields, info)
if getattr(self.Meta, 'extra_fields', None):
return expanded_fields + self.Meta.extra_fields
else:
return expanded_fields
Below should your view:
class FilterVases(generics.ListAPIView):
serializer_class = VaseSerializer
def get_queryset(self):
queryset = Vase.objects.all()
query_artist = self.request.query_params.get('artist_name')
if query_artist is not None:
try:
artist = Artist.objects.get(artistName=query_artist)
queryset = queryset.filter(artist=artist)
except:
pass
vaseID = self.request.query_params.get('vaseID')
if vaseID is not None:
queryset = queryset.filter(vaseID=vaseID)
return queryset

Updating rows in database using Django RESTAPI and AngularJS

I am trying to make it so that I can POST and update database rows from my angularJS app but I seem to be having trouble adding new entries to my database.
Things are posted without error but when I go and check the database then all added data is "None".
I have written this method to save Notes with a corresponding Lecture ID, where Lecture is an attribute of Notes.
saveNotes: function(notes, lecture_id, callback) {
$http({
method: 'POST',
url: apiRoute + 'notes/',
data: {
"notes": notes,
"lecture_id": lecture_id
}
}).success(callback);
}
I have written these views:
class LectureViewSet(viewsets.ModelViewSet):
serializer_class = LectureSerializer
def get_queryset(self):
course_id = self.request.query_params.get('course',False)
if course_id:
lectures = Lecture.objects.filter(course=course_id)
else:
lectures = Lecture.objects.all()
return lectures
class NotesViewSet(viewsets.ModelViewSet):
queryset = Notes.objects.all()
serializer_class = NotesSerializer
And these serializers:
class LectureSerializer(serializers.ModelSerializer):
class Meta:
model = Lecture
fields = ('id', 'lecture_no', 'title', 'youtubeLink', 'course', 'keywords')
class NotesSerializer(serializers.ModelSerializer):
lecture = LectureSerializer(read_only=True, many=True)
class Meta:
model = Notes
fields = ('id', 'notes', 'lecture')
Can anyone spot the error that is causing this addition of "None" values? Also, is there a way to make these fields update instead of post new ones?
Thanks!
Included models:
class Lecture(models.Model):
lecture_no = models.IntegerField(null=True)
title = models.CharField(max_length=128, unique=True, null=True)
youtubeLink = models.CharField(max_length=128, unique=True, null=True)
course = models.ForeignKey(Course, null=True)
keywords = models.TextField(max_length=300, null=True)
#Could add Next Rerun Date & Time
def __str__(self):
return self.title
class Notes(models.Model):
notes = models.TextField(null=True)
lecture = models.ForeignKey(Lecture, null=True)
def __str__(self):
return str(self.notes)

POST request to update data fields - AngularJS, Django

I have two models:
class Lecture(models.Model):
lecture_no = models.IntegerField(null=True)
title = models.CharField(max_length=128, unique=True, null=True)
youtubeLink = models.CharField(max_length=128, unique=True, null=True)
course = models.ForeignKey(Course, null=True)
keywords = models.TextField(max_length=300, null=True)
#Could add Next Rerun Date & Time
def __str__(self):
return self.title
class Notes(models.Model):
notes = models.TextField(null=True)
lecture = models.ForeignKey(Lecture, null=True, related_name='lecture')
def __str__(self):
return self.notes
These serializers:
class NotesSerializer(serializers.ModelSerializer):
lecture = LectureSerializer(read_only=True, many=True)
class Meta:
model = Notes
fields = ('id', 'notes', 'lecture')
class KeywordSerializer(serializers.ModelSerializer):
lecture = LectureSerializer(read_only=True, many=True)
class Meta:
model = Keyword
fields = ('id', 'notes', 'lecture')
and these views:
class LectureViewSet(viewsets.ModelViewSet):
serializer_class = LectureSerializer
def get_queryset(self):
course_id = self.request.query_params.get('course',False)
if course_id:
lectures = Lecture.objects.filter(course=course_id)
else:
lectures = Lecture.objects.all()
return lectures
class NotesViewSet(viewsets.ModelViewSet):
queryset = Notes.objects.all()
serializer_class = NotesSerializer
and I'm trying to make it so that I can update the "notes" field for a specific lecture. Currently I'm using a POST http request:
saveNotes: function(notes, lecture_id, callback) {
$http({
method: 'POST',
url: apiRoute + 'notes/',
data: {
"notes": notes,
"lecture_id": lecture_id
}
}).success(callback);
}
But this just adds a new row to the database every time. How do you update fields instead?
Thanks

Resources