Im have two models, Manager and Template, one Template has n Managers,
I want with the template id to get all the managers of the same
I tried to make an api that takes the url template id, and filters the relationship table but it returns me empty
This my models
class Template(TimestampedModel, permissions.TemplatesPermission):
title = models.CharField(
max_length=1000,
db_column='titulo',
verbose_name='título',
db_index=True,
)
description = models.TextField(
db_column='descricao',
verbose_name='descrição',
)
active = models.BooleanField(
default=True,
)
managers = models.ManyToManyField(
Manager,
through='TemplateManager',
)
validity_date = models.DateTimeField(
db_column='data_vigencia',
verbose_name='data de vigência',
)
class Meta:
db_table = 'declaracoes_template'
verbose_name = 'Template'
verbose_name_plural = 'Templates'
def __str__(self):
return self.title
class Manager(TimestampedModel):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
models.CASCADE,
verbose_name='usuário',
)
file = models.CharField(
max_length=1000,
db_column='assinatura',
verbose_name='assinatura do gestor',
)
position = models.ForeignKey(
Position,
models.PROTECT,
db_column='cargo',
verbose_name='cargo',
)
class Meta:
db_table = 'declaracoes_gestor'
verbose_name = 'Gestores'
verbose_name_plural = 'Gestores'
def __str__(self):
return self.user
class TemplateManager(TimestampedModel):
manager = models.ForeignKey(
Manager,
on_delete=models.PROTECT,
db_column='gestor_id',
)
template = models.ForeignKey(
Template,
on_delete=models.CASCADE,
db_column='template_id',
)
This my view
class TemplateManagerView(APIView):
pagination_class = BasePagination
def get(self, request, id):
template = get_object_or_404(models.Template.objects.all(), id=id)
managers = (models.TemplateManager.objects
.filter(template=template)
.all())
serializer = serializers.ManagerSerializer(managers, many=True)
return Response(serializer.data)
and my serializers
class ManagerSerializer(serializers.ModelSerializer):
position = PositionSerializer()
user = serializers.CharField(source='user.first_name')
class Meta:
model = models.Manager
fields = ['id', 'user', 'file', 'position']
class ManagerTemplateSerializer(serializers.ModelSerializer):
manager = ManagerSerializer(many=True)
template = TemplateSerializer(many=True)
class Meta:
fields = ['manager', 'template']
model = models.Template
my url something like /id/managers
First, you don't need to pass a query to get_object_or_404. This will work just fine:
get_object_or_404(models.Template, id=id)
Also, you are passing the wrong queryset:
managers = (models.TemplateManager.objects
.filter(template=template)
.all())
This can be changed to this:
models.TemplateManager.objects
.filter(template=template)
Which is a queryset from TemplateManager model while you're using the serializer for
ManagerSerializer serializer for Manager model.
Now, to fix this:
1 - change model in ManagerTemplateSerializer to TemplateManager instead of Template.
2 - change serializer = serializers.ManagerSerializer(managers, many=True) to serializer = serializers.ManagerTemplateSerializer(managers, many=True)
Related
class Teams(models.Model):
name = models.CharField(max_length=20)
file = models.FileField(upload_to='team_icons', null='True', blank='True')
members = models.ManyToManyField(User, related_name='member')
class ToDo(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
owner = models.ForeignKey('auth.user', related_name='todos', on_delete=models.CASCADE)
file = models.FileField(upload_to='uploads', null='True', blank='True')
teamOwner = models.ForeignKey("Teams", related_name='team', on_delete=models.CASCADE)
==> the serializers
class ToDoSerializer(serializers.ModelSerializer):
class Meta:
fields= (
'id',
'title',
'description',
'owner',
'file',
'teamOwner',
)
model = ToDo
class TeamSerializer(serializers.ModelSerializer):
# name = serializers.SerializerMethodField()
class Meta:
fields = (
'id',
'name',
'file',
)
model = Teams
And finally the view code of the query:
class ListTodo(generics.ListCreateAPIView):
queryset = models.ToDo.objects.all()
serializer_class = serializers.ToDoSerializer
def get_queryset(self):
owner_queryset = self.queryset.filter(Teams)
return owner_queryset
Every combination in .filter(xxx) fails. ik want as outcome the Team ID or PK number in the return queryset.
Iam a beginner so i hope i explained my problem in a clear way
you can write like ;
def get_queryset(self):
# if you want to logged user teams' todo list
owner_queryset = self.queryset.filter(Teams=self.request.user)
return owner_queryset
Best regards,
I am trying to generate a random object from my Model. The problem is that it will only work one time, then I have to restart the server to get a new object. It just keeps giving me the same object until the restart.
I have been looking for solution on stack overflow but haven't found any.
Views.py
def dailyaskist(category):
qs = Task.objects.filter(category=category)
max_num = len(qs)
while True:
pk = random.randint(1, max_num)
task = Task.objects.filter(pk=pk).first()
if task:
return task.pk
class DailyTaskEcommerceViewSet(viewsets.ModelViewSet):
category = 'ecommerce'
task_pk = dailyaskist(category)
queryset = Task.objects.filter(pk=task_pk)
serializer_class = TaskSerializer
serialisers.py
class StepSerializer(serializers.HyperlinkedModelSerializer):
task_id = serializers.PrimaryKeyRelatedField(queryset=Task.objects.all(), source='task.id')
class Meta:
model = Step
fields = ('title', 'description', 'done', 'task_id')
class TaskSerializer(serializers.HyperlinkedModelSerializer):
steps = StepSerializer(many=True, read_only=True)
class Meta:
model = Task
fields = ('title', 'description', 'video', 'done', 'steps')
models.py
Categories = (
('ecommerce', 'Ecommerce'),
)
class Task(models.Model):
title = models.CharField(max_length=50)
description = models.TextField(max_length=360)
video = models.CharField(max_length=30, default='')
category = models.CharField(choices=Categories, default='', max_length=30)
done = models.BooleanField(default=False)
def __str__(self):
return self.title
class Step(models.Model):
task = models.ForeignKey(Task, related_name='steps', on_delete=models.CASCADE)
title = models.CharField(max_length=50)
description = models.TextField(max_length=360)
done = models.BooleanField(default=False)
def __str__(self):
return self.title
I want to receive a new object (task) each time I make a GET request using the DailyTaskEcommerceViewSet.
Thanks in advance! :D
You would do this in a method. In this case, get_queryset seems the right place.
class DailyTaskEcommerceViewSet(viewsets.ModelViewSet):
serializer_class = TaskSerializer
category = 'ecommerce'
def get_queryset(self):
task_pk = dailyaskist(self.category)
return Task.objects.filter(pk=task_pk)
There are two Django models - ClientCompany & Proposal and the foreign key of ClientCompany is within the Proposal model. In Proposal how do I display the name of the ClientCompany instead of the foreign key id?
models.py:
class ClientCompany(models.Model):
name = models.CharField("Client Name", max_length=255)
abn_acn = models.BigIntegerField("ABN / ACN")
def __str__(self):
return self.name
class Proposal(models.Model):
proj_name = models.CharField("Project Name", max_length=255)
loc_state = models.CharField(
max_length=3,
)
proj_type = models.CharField(
max_length=30,
)
prop_status = models.CharField(
max_length=20,
)
client = models.ForeignKey(ClientCompany, on_delete=models.CASCADE)
oneic = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='main_engineer')
twoic = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='second_engineer')
created_at = models.DateTimeField(default=datetime.now)
def __str__(self):
return self.proj_name
serializers.py:
class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = ClientCompany
fields = ('id', 'name', 'abn_acn')
class ProposalSerializer(serializers.ModelSerializer):
class Meta:
model = Proposal
fields = ('id', 'proj_name', 'loc_state', 'proj_type', 'prop_status', 'client', 'oneic', 'twoic',)
queryset api.py:
class ProposalViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated, ]
queryset = Proposal.objects.all()
serializer_class = ProposalSerializer
currentlyshows the client foreign key id
I've been stuck on this, tried to apply the existing solutions recommended for similar problems but had no luck... if someone can tell me what I'm missing - thanks
I found this worked in the end by adding the serializers.SlugRelatedField line in serializers.py:
class ProposalSerializer(serializers.ModelSerializer):
client = serializers.SlugRelatedField(slug_field="name", read_only=True)
class Meta:
model = Proposal
fields = ('id', 'proj_name', 'loc_state', 'proj_type', 'prop_status',
'client', 'oneic', 'twoic',)
Update your serializer like this:
class ProposalSerializer(serializers.ModelSerializer):
client = ClientSerializer()
class Meta:
model = Proposal
fields = ('id', 'proj_name', 'loc_state', 'proj_type', 'prop_status', 'client', 'oneic', 'twoic',)
I have three models like following:
from model_utils.managers import InheritanceManager
class Product(models.Model):
name = models.CharField(max_length=50, blank=False, verbose_name="Type here name",)
class Pub(Product):
product = models.OneToOneField(Product, parent_link=True, )
seating_capacity = models.IntegerField(null=False, verbose_name="Seating capacity of the Pub",)
class Restaurant(Product):
product = models.OneToOneField(Product, parent_link=True, )
food_speciality = MultiSelectField(choices = MY_CHOICES)
I have implemented django-cart and have attached Product as my product model. I return all the products to my frontend. This basically sends product objects with only product specific attributes to the frontend, and hence it is hard to distinguish which product is Pub and which one is Restaurant.
How can I handle this on backend itself? Is there any way to extract/send also the type of products?
This is how my view looks like:
#api_view(('GET',))
def show(request):
cart = Cart(request.session)
products = cart.products
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
It returns for example:
[{"id":1,"name":"Shreyas","price":"45000.00000","avg_user_rating":"4.50000","city":1},{"id":4,"name":"Phadake","price":"350.00000","avg_user_rating":"5.00000","city":2}]
Serializer:
class ProductSerializer(serializers.ModelSerializer):
category = serializers.ReadOnlyField()
class Meta:
model = Product
fields = '__all__'
Option 1
Add the Meta class with verbose_name to you models:
class Pub(Product):
product = models.OneToOneField(Product, parent_link=True, )
seating_capacity = models.IntegerField(null=False, verbose_name="Seating capacity of the Pub",)
class Meta:
verbose_name = 'Pub'
class Restaurant(Product):
product = models.OneToOneField(Product, parent_link=True, )
food_speciality = MultiSelectField(choices = MY_CHOICES)
class Meta:
verbose_name = 'Restaurant'
Add these lines to ProductSerializer:
category = serializers.SerializerMethodField()
def get_category(self, obj):
return obj._meta.verbose_name
Option 2
Alternatively, you can add a property to each model.
class Pub(Product):
product = models.OneToOneField(Product, parent_link=True, )
seating_capacity = models.IntegerField(null=False, verbose_name="Seating capacity of the Pub",)
#property
def category(self):
return 'Pub'
class Restaurant(Product):
product = models.OneToOneField(Product, parent_link=True, )
food_speciality = MultiSelectField(choices = MY_CHOICES)
#property
def category(self):
return 'Restaurant'
Then add this line to ProductSerializer:
category = serializers.ReadOnlyField()
Option 3
Of course, you also have the option do this if you don't want to add Meta or properties to your models:
def get_category(self, obj):
return obj.__class__.__name__
But then you would have the restriction that every category would be equal to the class's name, which might be a problem.
I have model NewsModel and 2 serializers for him:
models.py
class NewsModel(models.Model):
title = models.CharField('Заголовок', max_length=255, help_text='Максимальная длина - 255 символов')
announce = models.TextField('Анонс', help_text='Краткий анонс новости')
author = models.ForeignKey(settings.AUTH_USER_MODEL, help_text='Автор новости', related_name='news')
full_text = models.TextField('Полный текст новости', help_text='Полный текст новости')
pub_date = models.DateTimeField('Дата публикации', auto_now_add=True, default=timezone.now, help_text='Дата публикации')
def comments_count(self):
return NewsComment.objects.filter(news=self.id).count()
def get_author_full_name(self):
return self.author.get_full_name()
class Meta:
db_table = 'news'
ordering = ('-pub_date',)
serilizers.py:
from rest_framework import serializers
from .models import NewsModel
from extuser.serializers import UserMiniSerializer
class NewsReadSerializer(serializers.ModelSerializer):
author = UserMiniSerializer()
class Meta:
model = NewsModel
fields = ('id', 'title', 'announce', 'comments_count', 'reviews', 'author_name')
def get_author_full_name(self, obj):
return obj.get_author_full_name()
class NewsWriteSerializer(serializers.ModelSerializer):
def validate_author(self, value):
value = self.request.user.id
return value
class Meta:
model = NewsModel
I select serializers in the api.py:
class NewsList(ListCreateAPIView):
queryset = NewsModel.objects.order_by('-pub_date')
def get_serializer_class(self, *args, **kwargs):
if self.request.method == 'GET':
return NewsReadSerializer
return NewsWriteSerializer
class Meta:
model = NewsModel
But when I will create NewsModel item, I see Error 400: Bad request [{'author': 'This field is required'}]
How I can set current user id as NewsItem.author value on creating new item?
I don't think you're using the serializer properly. A better practice to set request related data is to override perform_create in your view:
def perform_create(self, serializer):
serializer.save(author=self.request.user)
def perform_update(self, serializer):
serializer.save(author=self.request.user)
and then set your author serializer to read-only:
author = UserMiniSerializer(read_only=True)
this way you can simply use one single NewsSerializer for both read and write actions.
In new DRF you can write
owner = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
See http://www.django-rest-framework.org/api-guide/validators/#currentuserdefault
In DRF version prior 3 field must be declader with allow_null=True and default=None. DRF don't run checking fields without this params. Result code:
class NewsReadSerializer(serializers.ModelSerializer):
"""
Serializer only for reading.
author field serialized with other custom serializer
"""
author = UserMiniSerializer()
class Meta:
model = NewsModel
fields = ('id', 'title', 'announce', 'comments_count', 'reviews', 'author', 'pub_date',)
class NewsWriteSerializer(serializers.ModelSerializer):
"""
Serializer for creating and updating records.
author here is the instance of PrimaryKeyRelatedField, linked to all users
"""
author = serializers.PrimaryKeyRelatedField(
queryset=User.objects.all(), # Or User.objects.filter(active=True)
required=False,
allow_null=True,
default=None
)
# Get the current user from request context
def validate_author(self, value):
return self.context['request'].user
class Meta:
model = NewsModel
fields = ('title', 'announce', 'full_text', 'author',)
I would try something like this:
your models.py
class NewsModel(models.Model):
title = models.CharField(
'Заголовок', max_length=255,
help_text='Максимальная длина - 255 символов')
announce = models.TextField('Анонс',
help_text='Краткий анонс новости')
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
help_text='Автор новости', related_name='news')
full_text = models.TextField(
'Полный текст новости',
help_text='Полный текст новости')
pub_date = models.DateTimeField(
'Дата публикации', auto_now_add=True,
default=timezone.now, help_text='Дата публикации')
def comments_count(self):
return NewsComment.objects.filter(news=self.id).count()
def get_author_full_name(self):
return self.author.get_full_name()
class Meta:
db_table = 'news'
ordering = ('-pub_date',)
serializers.py
(ref.: http://www.django-rest-framework.org/api-guide/validators/#currentuserdefault)
from <yourapp>.models import NewsModel
from rest_framework import serializers
class NewsModelSerializer(serializers.ModelSerializer):
author = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = NewsModel
Also you should set settings.py to something like this:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',)
}