Get Data from Choice field in Django rest framework - django

I have searched and tried out all solutions provided for this question in similar problem but they're not working for me. I am getting the following error when trying to get data from an endpoint
Got AttributeError when attempting to get a value for field
hotel_type on serializer HotelDetailSerializer. The serializer
field might be named incorrectly and not match any attribute or key on
the Hotels instance. Original exception text was: 'Hotels' object
has no attribute 'get_hotel_Type_display'.
This is my model field truncated for clarity
class Hotels(models.Model):
HOTEL_TYPE = (
('hotel', "Hotel"),
('apartment', "Apartment"),
('villa', "Villa"),
hotel_Type = models.CharField(
max_length=20,
choices=HOTEL_TYPE,
default='hotel', null=True, blank=True
#property
def hotel_type(self):
return self.get_hotel_Type_display()
This is my serializer class also truncated for clarity
class HotelDetailSerializer(serializers.ModelSerializer):
hotel_type = serializers.Field(source='hotel_type.hotel_Type')
class Meta:
model = Hotels
fields = ("hotel_type" )
This is the apiview
class HotelDetailAPIView(RetrieveAPIView):
"""Display details of a single hotel"""
queryset = Hotels.objects.all()
serializer_class = HotelDetailSerializer
permission_classes = ()
lookup_field = 'slug'
Could anyone kindly assist me figure out why this is not working? Thanks
EDIT
I am editing this question to add more context. I have been doing some debugging in Django shell. This is what i am getting
>>> from hotels.models import Hotels
>>> h = Hotels.objects.all()
>>> for n in h:
... print (n.hotel_Type)
...
(<django.db.models.fields.CharField>,)
>>> for n in h:
... print (n.get_hotel_Type_display())
...
Traceback (most recent call last):
File "<console>", line 2, in <module>
AttributeError: 'Hotels' object has no attribute 'get_hotel_Type_display'
I am following Django's get_FOO_display() tutorial and i still cannot get this work. I am not seeing anything wrong with my Hotels model. Could this be a bug in Django? Kindly assist

This really has eaten me up. I finally found the issue was a misplaced comma on my model field as shown below
class Hotels(models.Model):
HOTEL_TYPE = (
('hotel', "Hotel"),
('apartment', "Apartment"),
('villa', "Villa"),
hotel_Type = models.CharField(
max_length=20,
choices=HOTEL_TYPE,
default='hotel', null=True, blank=True
),# <--------------This comma was the source of my problems
#property
def hotel_type(self):
return self.get_hotel_Type_display()

Related

Django MPTT tree as model filter in admin

I have a model linked to a related model that is a Django MPTT tree model, I would like to be able to filter the first model using the Django MPTT tree in the admin console.
class Tenders(models.Model):
...
sector=models.ForeignKey(Sector, to_field='sectorId', null=True, blank=True,on_delete=models.CASCADE)
...
class Sector(MPTTModel):
name = models.CharField(max_length = 255)
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True,related_name='children')
sectorId = models.IntegerField(default=0,null=True,unique=True)
In the Django admin I would like to set up the filters for the Tenders model such that the Django-MPTT tree is the filter.
I have tried using the following:
class adminTenders(admin.ModelAdmin):
def linkTo(self,obj):
return mark_safe("""<a href='{}' target="_blank" >Tender Link</a>""".format(obj.tenderLink))
linkTo.short_description=''
list_display=(
'title',
'linkTo',
'sector',
'region',
'repository',
'id',
)
list_filter=(
('sector', TreeRelatedFieldListFilter),
)
admin.site.register(Tenders,adminTenders)
However I get the following error when trying to run this and I cant figure it out:
File "py36/lib/python3.6/site-packages/mptt/admin.py", line 314, in field_choices
mptt_level_indent * levels_dict[pk])
KeyError: 0
Any help would be greatly appreciated.
Edit 1: I think I have isolated the issue to the fact that my foreign key in Tenders to Sectors uses a to_field='sectorId instead of the default to link to the pk column. This had to be done for backwards compatibility to an old database scheme that I am stuck with.
So it turns out this is a bug in the django-mptt code for the field_choices function in the TreeRelatedFieldListFilter class.
To fix it I had to subclass and over ride that function to use the to_field that I had defined.
Here is the custom code:
class TreeRelatedForSectors(TreeRelatedFieldListFilter):
# Modified from django-mptt code to fix to_field problem
def field_choices(self, field, request, model_admin):
mptt_level_indent = getattr(model_admin, 'mptt_level_indent', self.mptt_level_indent)
language_bidi = get_language_bidi()
initial_choices = field.get_choices(include_blank=False)
pks = [pk for pk, val in initial_choices]
models = field.related_model._default_manager.filter(sectorId__in=pks)
levels_dict = {model.sectorId: getattr(model, model._mptt_meta.level_attr) for model in models}
choices = []
for pk, val in initial_choices:
padding_style = ' style="padding-%s:%spx"' % (
'right' if language_bidi else 'left',
mptt_level_indent * levels_dict[pk])
choices.append((pk, val, mark_safe(padding_style)))
return choices

Django ManyToMany relationship having through parameter [duplicate]

I have a many-to-many relationship with a through table like so:
class Chapter(models.Model):
name = models.CharField(max_length=255,)
slides = models.ManyToManyField('Slide', blank=True, related_name='chapters', through='SlideOrder')
# ...
class Slide(models.Model):
title = models.CharField(max_length=255,)
# ...
class SlideOrder(models.Model):
chapter = models.ForeignKey(Chapter)
slide = models.ForeignKey(Slide)
number = models.PositiveIntegerField()
I am able to get the slides for a chapter in order like so:
chapter = Chapter.objects.get(pk=1)
chapter_slides = chapter.slides.order_by('slideorder')
However, when working on an individual slide instance I am unable to access the slide order:
slide = Slide.objects.get(pk=1)
If I do the following on my slide instance I can see all possible fields:
print slide._meta.get_all_field_names()
['title', u'chapters', 'slideorder', u'id']
However trying to access the slideorder field gives me the following:
slide.slideorder
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Slide' object has no attribute 'slideorder'
I am able to access all attributes listed except slideorder. How can I access a slide's order?
You can either filter on the SlideOrder model directly
slide = Slide.objects.get(pk=1)
slide_orders = SlideOrder.objects.filter(slide=slide)
for slide_order in slide_orders:
print slide_order.number
or follow the foreign key backwards:
slide = Slide.objects.get(pk=1)
slide_orders = slide.slideorder_set.all()
for slide_order in slide_orders:
print slide_order.number
See the docs on extra fields on many-to-many relationships for more info.
You can use slide.slideorder_set as documented in the django docs

Filtering queryset if one value is greater than another value

I am trying to filter in view my queryset based on relation between 2 fields .
however always getting the error that my field is not defined .
My Model has several calculated columns and I want to get only the records where values of field A are greater than field B.
So this is my model
class Material(models.Model):
version = IntegerVersionField( )
code = models.CharField(max_length=30)
name = models.CharField(max_length=30)
min_quantity = models.DecimalField(max_digits=19, decimal_places=10)
max_quantity = models.DecimalField(max_digits=19, decimal_places=10)
is_active = models.BooleanField(default=True)
def _get_totalinventory(self):
from inventory.models import Inventory
return Inventory.objects.filter(warehouse_Bin__material_UOM__UOM__material=self.id, is_active = true ).aggregate(Sum('quantity'))
totalinventory = property(_get_totalinventory)
def _get_totalpo(self):
from purchase.models import POmaterial
return POmaterial.objects.filter(material=self.id, is_active = true).aggregate(Sum('quantity'))
totalpo = property(_get_totalpo)
def _get_totalso(self):
from sales.models import SOproduct
return SOproduct.objects.filter(product__material=self.id , is_active=true ).aggregate(Sum('quantity'))
totalso = property(_get_totalpo)
#property
def _get_total(self):
return (totalinventory + totalpo - totalso)
total = property(_get_total)
And this is line in my view where I try to get the conditional queryset
po_list = MaterialFilter(request.GET, queryset=Material.objects.filter( total__lte = min_quantity ))
But I am getting the error that min_quantity is not defined
What could be the problem ?
EDIT:
My problem got solved thank you #Moses Koledoye but in the same code I have different issue now
Cannot resolve keyword 'total' into field.Choices are: am, author, author_id, bom, bomversion, code, creation_time, description, id, inventory, is_active, is_production, itemgroup, itemgroup_id, keywords, materialuom, max_quantity, min_quantity, name, pomaterial, produce, product, slug, trigger_quantity, uom, updated_by, updated_by_id, valid_from, valid_to, version, warehousebin
Basically it doesn't show any of my calculated fields I have in my model.
Django cannot write a query which is conditioned on a field whose value is unknown. You need to use a F expression for this:
from django.db.models import F
queryset = Material.objects.filter(total__lte = F('min_quantity'))
And your FilterSet becomes:
po_list = MaterialFilter(request.GET, queryset = Material.objects.filter(total__lte=F('min_quantity')))
From the docs:
An F() object represents the value of a model field or annotated
column. It makes it possible to refer to model field values and
perform database operations using them without actually having to pull
them out of the database into Python memory

Django Tastypie POST request for OneToOne relation

I have recently started django-tastypie and so far loving the framework. With said that, I am getting below issue on POST for OneToOne relation to model and spent good amount of time but couldn't figured whats missing. Here is the Model and Resource code -
Model
class Question(TimeStampedModel):
question_title = models.CharField("question title", max_length=100)
question_desc = models.TextField("question description", max_length=1000)
.......
Second model is having OneToOne relation with Question -
class QuestionAnswer(TimeStampedModel):
question = models.OneToOneField(Question)
.....
Resource
QuestionAnswerResource -
class QuestionAnswerResource(ModelResource):
question = fields.ForeignKey('myapp.api.QuestionResource', 'question')
class Meta:
queryset = QuestionAnswer.objects.all()
resource_name='questionanswer'
QuestionResource -
class QuestionResource(ModelResource):
questionanswer = fields.OneToOneField('myapp.api.QuestionAnswerResource', 'questionanswer', full=True)
class Meta:
queryset = Question.objects.all()
resource_name = 'question'
With the above setup, I get correct response on GET with Question instance along with its answer attribute. However when I try to POST data to save question/answer on this one it fails with below error -
"{"error_message": "", "traceback": "Traceback (most recent call
last):\n\n File
\"/Library/Python/2.7/site-packages/tastypie/resources.py\", line 192,
...................................................................................... line 636, in hydrate\n
value = super(ToOneField, self).hydrate(bundle)\n\n File
\"/Library/Python/2.7/site-packages/tastypie/fields.py\", line 154, in
hydrate\n elif self.attribute and getattr(bundle.obj,
self.attribute, None):\n\n File
\"/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/db/models/fields/related.py\", line 343, in get\n raise
self.field.rel.to.DoesNotExist\n\nDoesNotExist\n"}"
Can someone point out what I am missing?
I think that this:
questionanswer = fields.OneToOneField('myapp.api.QuestionAnswerResource', 'questionanswer', full=True)
causes problem. There is no questionanswer field in your Question model and Django expects that.
To test, you may want to see whether you can create instances in the shell. Tastypie docs say the following about the ToOneField:
This subclass requires Django’s ORM layer to work properly.
and I think this might not be the case here.
To provide answers for a question you may want to set related_name, like so:
question = fields.ForeignKey('myapp.api.QuestionResource', 'question', related_name = 'questionanswer')

What does it mean for an object to be unscriptable?

I don't know what's going on here... I just want to check the value of a model field and then update it accordingly... any help or insight is appreciated!
model:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
beta = models.CharField(max_length=1, blank=True, null=True)
view:
from internal.accounts.models import UserProfile
from django.contrib.auth.models import User
#login_required
def beta_testers(request):
user = User.objects.get(username=request.user.username)
user_profile = user.get_profile()
count = UserProfile.objects.filter(beta='1').count()
if count < 50 and not user_profile['beta']:
user_profile['beta'] = '1'
user_profile.save()
error:
TypeError at /utilities/beta-signup/
'UserProfile' object is unsubscriptable
Request Method: GET
Request URL: http://localhost/utilities/beta-signup/?x=1&y=15
Django Version: 1.2.1
Exception Type: TypeError
Exception Value:
'UserProfile' object is unsubscriptable
Exception Location: C:/django\internal\cms_helper\views.py in beta_testers, line 284
The error is "unSUBscriptable". Your user_profile object isn't a dictionary. Use user_profile.beta, not user_profile['beta'].
Alternatively, you can use a string with getattr:
getattr(user_profile, 'beta', False)
False is the default value; which, in your case would work with checking if the value is set or not. I found this very helpful, so I thought I would post this solution, even though the question was asked years ago. :)
Method One
model_name.object.filter(column_name='value').last
Method Two
This error happens when you tries to insert a model object in text filed