django serializer field not recognizing attribute clearly defined - django

when i try to run a view I get this error:
AttributeError: Got AttributeError when attempting to get a value for field `inreplytouser` on serializer `ContentFeedPostCommentSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `QuerySet` instance.
Original exception text was: 'QuerySet' object has no attribute 'inreplytouser'.
Here is my model:
class ContentFeedPostComments(models.Model):
inreplytouser = models.ForeignKey(SiteUsers, null=True, related_name='replytouser', blank=True, on_delete=models.CASCADE)
inreplytotopcomment = models.BigIntegerField(null=True, blank=True)
timecommented = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(SiteUsers, on_delete=models.CASCADE)
contentcreator = models.ForeignKey(ContentCreatorUsers, on_delete=models.CASCADE)
contentfeedpost = models.ForeignKey(ContentFeedPost, on_delete=models.CASCADE)
text = models.CharField(max_length=1000)
here is the serializer:
class ContentFeedPostCommentSerializer(ModelSerializer):
id = IntegerField()
inreplytouser = SiteusersSerializer()
user = SiteusersSerializer()
contentcreator = ContentCreatorSerializer()
class Meta:
model = ContentFeedPostComments
fields = ('id','inreplytouser', 'inreplytotopcomment', 'timecommented',
'user', 'contentcreator', 'contentfeedpost', 'text')
here is the view:
class ContentFeedPostsComments(APIView):
def get(self, request, *args, **kwargs):
postid = kwargs.get('postid')
contentfeedpost = get_object_or_404(ContentFeedPost, id=postid)
topcomments = ContentFeedPostComments.objects.filter(contentfeedpost= contentfeedpost, inreplytotopcomment= None).order_by('timecommented')
replycomments = ContentFeedPostComments.objects.filter( contentfeedpost = contentfeedpost, inreplytotopcomment__isnull = False).order_by('timecommented')
serializedtopcomments = ContentFeedPostCommentSerializer(topcomments)
serializedreplycomments = ContentFeedPostCommentSerializer(replycomments)
payload = {
'topcomments': serializedtopcomments.data,
'replycomments': serializedreplycomments.data
}
return Response(payload)
I was reading something about source being passsed into the inreplytouser field of the serializer field but that makes no sense. Your wisdom and knowledge on this situation is greatly appreciated.

Since querysets are a collection of objects, many=True..[DRF-doc] needs to be set in the serializer:
serializedtopcomments = ContentFeedPostCommentSerializer(topcomments, many=True)
serializedreplycomments = ContentFeedPostCommentSerializer(replycomments, many=True)

Related

201 Created - but no new object in SqLite database

Edit 25th Jan:
here's my model!
class rat(models.Model):
name = models.CharField(max_length=132, null =True)
body_colour = models.ForeignKey(BodyColour, on_delete=models.CASCADE, null = True, related_name='body_colour')
eye_colour = models.ForeignKey(EyeColour, on_delete=models.CASCADE, null = True, related_name='eye_colour')
user = models.ForeignKey(User, on_delete=models.CASCADE, null = True)
bio = models.TextField(null = True, blank = True)
born = models.DateField(auto_now_add=True)
image = models.ForeignKey(Image, on_delete=models.CASCADE, null = True, blank=True)
Adding rat.save() to the serializer gives me the following error: TypeError: int() argument must be a string, a bytes-like object or a real number, not 'dict'
I have a button that users can click on to add an object to their account. It's sent through django to my sqlite db, and in the console log there are no errors. It says "201 Created", and yet there is no new object in the database.
Someone else had the same problem as me, the solution was getting rid of some methods in the serializer, but they don't specify what they got rid off.
What's causing this?
Here is my serializer:
class RatSerializer(FlexFieldsModelSerializer, serializers.ModelSerializer):
name = serializers.CharField()
user = serializers.CharField(source='user.username', required=False)
userid = serializers.CharField(source='user.id', required=False)
body_colour = BodyColourSerializer()
eye_colour = EyeColourSerializer()
image = ImageSerializer(required=False)
class Meta:
model = rat
exclude = ['bio']
def create(self, data):
request = self.context.get("request")
user = request.user
return rat( name = data["name"],
body_colour = BodyColour(name=data["body_colour"]["name"]),
eye_colour = EyeColour(name=data["eye_colour"]["name"]),
image = Image(),
user = user)
My views:
class ratViewset(ModelViewSet, APIView):
serializer_class = RatSerializer
# queryset = rat.objects.all()
def get_queryset(self):
user = self.request.user
if user.is_anonymous:
return rat.objects.all()
return rat.objects.filter(user=user.id)
def post(self, request):
rat = request.data.get('rat')
# creates rat with the above data
serializer = RatSerializer(data=rat)
if serializer.is_valid(raise_exception=True):
serializer.save()
print(serializer.data, type(serializer.data))
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status)
Grateful for any help!

Count the number of rows in a Django database : AttributeError

I have database created by Django model, where idRecruteur is the fields of the table Offre.
I need to count the number of rows where idRecruteur = 1.
This is my "Offre" table code:
#python_2_unicode_compatible
class Offre(models.Model):
titre = models.CharField(max_length=100)
dateAjout = models.DateField(auto_now=False, auto_now_add=False)
nature = models.CharField(max_length=50)
duree = models.CharField(max_length=50)
niveau = models.CharField(max_length=50)
description = models.CharField(max_length=50)
salaire = models.FloatField(null=True, blank=True)
idRecruteur = models.ForeignKey(Recruteur, related_name="Offre", on_delete=models.CASCADE)
def __str__(self):
return "Offre: {}".format(self.title)
and this is my queryset:
class OffresparEntrepriseViewSet(ModelViewSet):
queryset = Offre.objects.filter(idRecruteur=1).count()
serializer_class = OffreSerializer
I get the error " AttributeError: 'int' object has no attribute 'model' "
Any ideas what I am doing wrong?
ViewSet's queryset attribute should be QuerySet object, but count() returns integer. You need to use queryset = Offre.objects.filter(idRecruteur=1) as viewset queryset, and move counting functionality to another level. For example using list_route:
class OffresparEntrepriseViewSet(ModelViewSet):
queryset = Offre.objects.filter(idRecruteur=1)
serializer_class = OffreSerializer
#list_route()
def count(self, request):
count = self.queryset.count()
return Response({'count': count})
Now you can get count by accesing viewset_url/count url.

Django REST Framework, PUT/POST serializer data disappearing

I am having trouble with part of my data disappearing when I try to update or post a new instance.
With data like this
data = {
'item': 'Product',
'station': 'Workbench',
'ingredients':[
{'item': 'ing1', 'amount': 2},
{'item': 'ing2', 'amount':1}
]
}
I have a serializer with a nested serializer that get_or_creates ingredients as needed.
class IngredientSerializer(serializers.ModelSerializer):
class Meta:
model = Ingredient
fields = ('item', 'amount')
class WriteableRecipeSerializer(serializers.ModelSerializer):
item = serializers.PrimaryKeyRelatedField(queryset=Item.objects.all())
ingredients = IngredientSerializer(many=True)
station = serializers.PrimaryKeyRelatedField(queryset=Item.objects.all())
def create(self, validated_data):
logger.info(validated_data)
ingredient_data = validated_data.pop('ingredients')
recipe = Recipe.objects.create(**validated_data)
for ingredient in ingredient_data:
ingredient_item = Item.objects.get(name=ingredient['item'])
amount = ingredient['amount']
ingredient, created = Ingredient.objects.get_or_create(item=ingredient_item, amount=amount
)
recipe.ingredients.add(ingredient)
return recipe
def update(self, instance, validated_data):
logger.info(validated_data)
ingredient_data = validated_data.pop('ingredients')
instance.item = validated_data.get('item', instance.item)
instance.station = validated_data.get('station', instance.station)
for ingredient in ingredient_data:
ingredient_item = Item.objects.get(name=ingredient['item'])
amount = ingredient['amount']
ingredient, created = Ingredient.objects.get_or_create(item=ingredient_item, amount=amount)
logger.info('Itering')
instance.ingredients.add(ingredient)
return instance
class Meta:
model = Recipe
fields = ('item', 'amount', 'ingredients', 'station')
The data validates and I get a response code 200, but both the response data and the validated_data a shown by my logger in the create and update methods return something like this:
data = {
'item': 'Product',
'station': 'Workbench',
'ingredients':[]
}
The Ingredients data going AWOL somewhere.
I have tried making the Ingredient Serializer a generic serializer as well as overriding WriteableRecipeSerializer's validation to just return attrs but the problem persists.
Edit for models:
class Ingredient(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
amount = models.IntegerField()
def __str__(self):
return self.item.name + '(' + str(self.amount) + ')'
class Recipe(models.Model):
item = models.OneToOneField(Item, related_name='recipe', on_delete=models.CASCADE)
amount = models.IntegerField(default=1)
ingredients = models.ManyToManyField(Ingredient)
station = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='as_station')
def __str__(self):
return 'Recipe: ' + str(self.item)

Django Rest Framework serilize relations

How to serialize a fields in related models.
I got a models:
class Order(models.Model):
order_id = models.BigIntegerField(verbose_name='Order ID', unique=True)
order_name = models.CharField(verbose_name='Order name', max_length=255)
order_type = models.IntegerField(verbose_name='Campaign type')
class Types(models.Model):
delimiter = models.CharField(verbose_name='Delimiter', max_length=255)
status = models.BooleanField(verbose_name='Status', default=True)
title = models.CharField(verbose_name='Title', max_length=255)
class User(models.Model):
name = models.CharField(verbose_name='User name', max_length=200, unique=True)
class Report(models.Model):
order = models.ForeignKey(Order, to_field='order_id', verbose_name='Order ID')
user = models.ForeignKey(User, verbose_name='User ID')
ad_type = models.ForeignKey(Types, verbose_name='Type')
imp = models.IntegerField(verbose_name='Total imp')
month = models.DateField(verbose_name='Month', default=datetime.datetime.today)
View:
class ReportLisAPIView(ListAPIView):
serializer_class = ReportSerializer
def get_queryset(self):
month = parse_date(self.kwargs['month']) - relativedelta(day=1)
queryset = (
Report.objects.filter(month=month)
.values_list(
'user', 'user__name', 'order__order_id',
'order__order_name', 'order__order_type'
).all().annotate(Sum('imp'))
)
return queryset
Serializer:
class ReportSerializer(ModelSerializer):
class Meta:
model = Report
depth = 1
I need to get all field like in 'queryset' in get_queryset()
but I got an error:
Got AttributeError when attempting to get a value for field imp on
serializer ReportSerializer. The serializer field might be named
incorrectly and not match any attribute or key on the tuple
instance. Original exception text was: 'tuple' object has no attribute
'imp'.
But if I return in get_queryset() just Report.objects.filter(month=month).all() I'll get all objects and related object with all field, without aggregate of imp and not grouping.
So the question is how to make serializer return structure that set in queryset?
The get_queryset method requires to return a queryset but you are returning a tuple beacause of values_list. Either drop it to return a queryset or go with a more generic view like APIView.
I found a way how to do it.
As I use .values_list() it return list object instead of queryset object. So for serializer do understand what is inside the list I defined all fields in serializer. And in to_representation() I return dictionary like it should be.
Serializer:
class ReportSerializer(serializers.ModelSerializer):
user = serializers.IntegerField()
user_name = serializers.CharField()
order_id = serializers.IntegerField()
order_name = serializers.CharField()
order_type = serializers.IntegerField()
imp = serializers.IntegerField()
class Meta:
model = Report
fields = [
'user', 'user_name', 'order_id', 'order_name',
'order_type', 'imp'
]
depth = 1
def to_representation(self, instance):
Reports = namedtuple('Reports', [
'user',
'user_name',
'order_id',
'order_name',
'order_type',
'imp',
])
return super(ReportSerializer, self).to_representation(
Reports(*instance)._asdict()
)
View:
class ReportLisAPIView(ListAPIView):
serializer_class = ReportSerializer
def get_queryset(self):
month = parse_date(self.kwargs['month']) - relativedelta(day=1)
queryset = (
Report.objects.filter(month=month)
.values_list(
'user', 'user__name', 'order__order_id',
'order__order_name', 'order__order_type'
).all().annotate(Sum('imp'))
)
return queryset
def list(self, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.serializer_class(queryset, many=True)
# actualy that's it! part of which is below can be pass and just
# return Response(serializer.data)
result = {
'month': parse_date(self.kwargs['month']).strftime('%Y-%m'),
'reports': []
}
inflcr = {}
for item in serializer.data:
inflcr.setdefault(item['user'], {
'id': item['user'],
'name': item['user_name'],
'campaigns': []
})
orders = {
'id': item['order_id'],
'name': item['order_name'],
'type': item['order_type'],
'impressions': item['imp'],
}
inflcr[item['user']]['campaigns'].append(orders)
result['reports'] = inflcr.values()
return Response(result)

Django - How to do a transaction when saving a form?

I'm saving a form, but there is one save() method that is outside the transaction. The save() method outside a transaction is the save() on the "BicycleAdCategoryForm".
Here is the code:
models.py
class Main(models.Model):
section = models.ForeignKey(Section)
user = models.ForeignKey(User)
title = models.CharField(max_length=250)
date_inserted = models.DateTimeField(auto_now_add=True)
date_last_update = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.title
# To order in the admin by name of the section
class Meta:
ordering = ['date_inserted']
class BicycleAd(models.Model):
main = models.ForeignKey(Main)
bicycleadtype = models.ForeignKey(BicycleAdType)
bicycleaditemkind = models.ForeignKey(BicycleAdItemKind) # MPTT Model
bicycleadcondition = models.ForeignKey(BicycleAdCondition)
country = models.ForeignKey(GeonamesCountry)
city = models.ForeignKey(GeonamesLocal)
date_inserted = models.DateTimeField(auto_now_add=True)
date_last_update = models.DateTimeField(auto_now=True)
# To order in the admin by name of the section
class Meta:
ordering = ['date_inserted']
class BicycleAdCategoryType(models.Model):
n_bicycle_ad_category_type = models.CharField(max_length=100) # COMPRA, VENDA, TROCA
date_inserted = models.DateTimeField(auto_now_add=True)
date_last_update = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.n_bicycle_ad_category_type
# To order in the admin by name of the section
class Meta:
ordering = ['n_bicycle_ad_category_type']
forms.py
class MainForm(forms.ModelForm):
class Meta:
model = Main
exclude = ('user', 'section')
class BicycleAdForm(forms.ModelForm):
class Meta:
model = BicycleAd
exclude = ('main', 'bicycleadtype', 'bicycleaditemkind', 'bicycleadcondition', 'city') # DPS RETIRAR DAQUI A "CITY"
class BicycleAdCategoryForm(forms.ModelForm):
bicycleadcategorytype = forms.ModelMultipleChoiceField(queryset=BicycleAdCategoryType.objects.all(), required=False, widget=forms.CheckboxSelectMultiple) # Se retirar o widget fico uma SELECT box em q posso selecionar varias opcoes
class Meta:
model = BicycleAdCategory
exclude = ('bicyclead',)
def save(self, commit, rel_obj):
data = self.data.getlist('bicycleadcategorytype')
for item in data:
obj_bicycleadcategory = BicycleAdCategory()
obj_bicycleadcategory.bicyclead = rel_obj
obj_bicycleadcategory.bicycleadcategorytype = BicycleAdCategoryType.objects.get(pk=item)
obj_bicycleadcategory.save()
def clean_bicycleadcategorytype(self):
data = self.cleaned_data['bicycleadcategorytype']
try:
for item in data:
bicycleadcategorytype = BicycleAdCategoryType.objects.get(pk=item.pk)
return bicycleadcategorytype
except (KeyError, BicycleAdCategoryType.DoesNotExist):
raise forms.ValidationError('Invalid Bicycle Ad Category Type. Please try again.')
views.py
def submit_ad_view(request):
if request.method == 'POST':
model_main = Main()
model_main.section = Section.objects.get(pk=request.POST['section'])
model_main.user = request.user
model_bicyclead = BicycleAd()
model_bicyclead.bicycleadtype = BicycleAdType.objects.get(pk=2)
model_bicyclead.bicycleaditemkind = BicycleAdItemKind.objects.get(pk=4)
model_bicyclead.bicycleadcondition = BicycleAdCondition.objects.get(pk=2)
model_bicyclead.city = GeonamesLocal.objects.get(pk=4803854)
form_main = MainForm(request.POST, instance = model_main)
form_bicyclead = BicycleAdForm(request.POST, instance = model_bicyclead)
form_bicycleadcategory = BicycleAdCategoryForm(request.POST)
if form_main.is_valid() and form_bicyclead.is_valid() and form_bicycleadcategory.is_valid():
main_f = form_main.save()
bicyclead_f = form_bicyclead.save(commit=False)
bicyclead_f.main = main_f
bicyclead_f.save()
bicycleadcategory_f = form_bicycleadcategory.save(commit=False, rel_obj=model_bicyclead)
resultado = 'valid'
else:
resultado = 'n_valid'
return render_to_response('app/submit_ad.html', {'resultado': resultado}, context_instance=RequestContext(request))
I think main_f and bicyclead_f are inside a transaction but bicycleadcategory_f is outside a transaction. When bicycleadcategory_f fails, main_f and bicyclead_f are stored in the database.
Any clue on what I'm doing wrong?
Best Regards,
Django executes views using the commit_on_success decorator (or at least it behaves that way). If you're view crashes (uncaught exceptions), a rollback should take place. If some data is stored, and some is not there is a possibility that your DB engine does not support transactional processing.
Check out the django doc for more info
https://docs.djangoproject.com/en/dev/ref/databases/
For example, if you're using MySQL with MyISAM you may encounter some problems
edit:
Krzysiek Szularz: I guess everybody is using django TransactionMiddleware or simmilar things, so I skipped it - and mentioned only the logic layer.