models.py
class Product(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(decimal_places=5,max_digits= 1500)
summary = models.TextField()
featured = models.BooleanField()
def __str__(self):
return self.title
# return f'product title:{self.title}-product price:{self.price}'workok
class Meta:
ordering = ('-price',)
class Opinion(models.Model):
name = models.CharField(max_length=20)
email = models.EmailField(max_length=20)
body = models.TextField()
opinion_date = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=False)
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='opinion_set')
def __str__(self):
return f'({self.name}) add opinion about ({self.product})'
forms.py:
from django.forms import ModelForm
from .models import Product #space after from keyword
class OpinionModelForm(ModelForm):
class Meta:
model = Product
fields = ['name','email','body','product']
invalid in code line :
fields = ['name','email','body','product'] #---- NOT WORK !!!
, but if i change above code to :
fields = "__all__" # ----it is WORKing ok without any problem !!
question : what is the error? I am not need all the fields in the Product model (like active boolean field), I need only 'name','email','body','product' fields .
According to the error and the code you provided the main problem is that you made a mistake in chosing model in serializer:
class OpinionModelForm(ModelForm):
class Meta:
model = Product
fields = ['name','email','body','product']
Serializer name is OpinionModelForm and listed fields belong to Opinion so I guess you actually wanted to serialize Opinion and no Product as you defined at this line:
model = Product
Simply change it to:
model = Opinion
Related
Looking for solution of this problem I encountered some similar threads, but referring to older versions of Django/DRF and thus not working in my case.
There are these two models:
class CsdModel(models.Model):
model_id = models.CharField("Item ID", max_length=8, primary_key=True)
name = models.CharField("Item Name", max_length=40)
active = models.BooleanField(default=True)
def __str__(self):
return self.model_id
class CsdListing(models.Model):
model_id = models.ForeignKey(CsdModel, on_delete=models.CASCADE, default=0, related_name='m_id')
name = models.ForeignKey(CsdModel, on_delete=models.CASCADE, default=0, related_name='m_name')
(...)
EDIT: Serializers are defined this way:
class CsdModelSerializer(serializers.ModelSerializer):
model_id = serializers.RegexField(regex='^\w{2}\d{3}$', allow_blank=False)
name = serializers.CharField(min_length=6, max_length=50, allow_blank=False)
class Meta:
model = CsdModel
fields = '__all__'
class CsdListingSerializer(serializers.ModelSerializer):
session_id = serializers.RegexField(regex='^s\d{2}$', allow_blank=False)
def validate_session_id(self, value):
(...)
class Meta:
model = CsdListing
fields = '__all__'
What I'd like to see, is model_id and name from CsdModel displayed inside a form created based on CsdListing model. But instead, the ID is duplicated:
How should I rebuild the model(s) to have both ID and name displayed in the form?
You should have only one foreign key. But the listing serializer should then reference the model as a nested serializer.
class CsdListing(models.Model):
model = models.ForeignKey(CsdModel, on_delete=models.CASCADE, default=0, related_name='listing')
class CsdListingSerializer(serializers.ModelSerializer):
model = CsdModelSerializer()
session_id = serializers.RegexField(regex='^s\d{2}$', allow_blank=False)
In my Django Rest Framework api I am attempting to add a property to my model UserPosts that returns all likes for said post. Despite my best efforts I keep running into this error. Here is my post model below:
class UserPosts(models.Model):
userProfile = models.ForeignKey(UserProfile, related_name="posts", on_delete=models.CASCADE)
image = models.ImageField()
caption = models.CharField(max_length=240)
#property
def get_likes(self):
from liked.models import Like
return Like(post=self)
and here is my like model:
class Like(models.Model):
user = models.OneToOneField(UserProfile, on_delete=models.CASCADE,)
post = models.ForeignKey(UserPosts, on_delete=models.CASCADE)
liked_at = models.DateTimeField()
and lastly the post serializer:
class postSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = models.UserPosts
fields = ('userProfile', 'image', 'caption', 'likes')
Thanks.
You have at least three ways. First as #WillemVanOnsem said, by the many_to_one change the likes to like_set
class postSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = models.UserPosts
fields = ('userProfile', 'image', 'caption', 'like_set')
# ^^^^^
Second rename your model's property to likes and fix the queryset inside it
class UserPosts(models.Model):
userProfile = models.ForeignKey(UserProfile, related_name="posts", on_delete=models.CASCADE)
image = models.ImageField()
caption = models.CharField(max_length=240)
#property
def likes(self):
# ^^^^^
from liked.models import Like
return Like.objects.filter(post=self).values() or []
# solution you try ^^^^^^^
return self.like_set.values() or []
# more django way
And Third, the most simple and elegant way for me, is to remove your get_likes and add the related_name to the post ForeignKey:
class Like(models.Model):
user = models.OneToOneField(UserProfile, on_delete=models.CASCADE,)
post = models.ForeignKey(UserPosts, related_name='likes', on_delete=models.CASCADE)
# ^^^^^^^^^^^
liked_at = models.DateTimeField()
Preliminary note: this is a rather newbie question, though I have not found a sufficient answer on StackOverflow; many similar questions, but not this one. So I am asking a new question.
The problem: I'm having difficulty creating records where one field is a foreign key to an existing record, and I do not know what I'm doing wrong in my code.
In my app there are two models in question, a one-to-many relationship between Company and BalanceSheet:
models:
class Company(models.Model):
cik = models.IntegerField(default=0, unique=True)
symbol = models.CharField(max_length=4, unique=True)
name = models.CharField(max_length=255, unique=True)
def __str__(self):
return self.symbol
class BalanceSheet(models.Model):
company = models.ForeignKey(Company,
null=True,
on_delete=models.CASCADE,
related_name='balance_sheets',)
date = models.DateField()
profit = models.BigIntegerField()
loss = models.BigIntegerField()
class Meta:
unique_together = (('company', 'date'),)
def __str__(self):
return '%s - %s' % (self.company, self.date)
serializers:
class BalanceSheetSerializer(serializers.ModelSerializer):
company = serializers.StringRelatedField()
class Meta:
model = BalanceSheet
fields = ('company','date','profit','loss')
class CompanySerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = ('cik', 'symbol', 'name')
Views:
class BalanceSheetCreate(generics.CreateAPIView):
model = BalanceSheet
queryset = BalanceSheet.objects.all()
serializer_class = BalanceSheetSerializer
urls include:
url(r'^(?P<symbol>[A-Z]{1,4})/create-balance-sheet/$', views.BalanceSheetCreate.as_view(),
name='create_balance_sheet'),
To this point, I have zero problem reading data. However, when trying to create records, I get errors I don't understand:
curl http://localhost:8000/financials/AAPL/create-balance-sheet/ -X POST -d "company=AAPL&date=1968-04-17&profit=1&loss=1"
IntegrityError at /financials/AAPL/create-balance-sheet/
null value in column "company_id" violates not-null constraint
Dropping the company data from that curl command results in the same error.
How do I get around this error? I thought I was telling the api what company I'm interested in, both explicitly in the url and in the post data.
Using python3.6, django 1.11, and djangorestframework 3.7.7
You get the IntegrityError because your code will try to create a new BalanceSheet without a company. That's because StringRelatedField is read-only (see docs) and therefore it's not parsed when BalanceSheetSerializer is used in write mode.
SlugRelatedField is what you need here:
class BalanceSheetSerializer(serializers.ModelSerializer):
company = serializers.SlugRelatedField(slug_field='symbol')
class Meta:
model = BalanceSheet
fields = ('company','date','profit','loss')
To answer my own question, here's what I wound up with. Thanks again go to dukebody.
models:
class Company(models.Model):
cik = models.IntegerField(default=0)
symbol = models.CharField(max_length=4)
name = models.CharField(max_length=255)
def __str__(self):
return self.symbol
class BalanceSheet(models.Model):
company = models.ForeignKey(Company,
null=True,
on_delete=models.CASCADE,
related_name='balance_sheets',)
date = models.DateField()
profit = models.BigIntegerField()
loss = models.BigIntegerField()
class Meta:
unique_together = (('company', 'date'),)
def __str__(self):
return '%s - %s' % (self.company, self.date)
serializers:
class CompanySerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = ('cik', 'symbol', 'name')
class BalanceSheetSerializer(serializers.ModelSerializer):
company = CompanySerializer(many=False)
class Meta:
model = BalanceSheet
fields = ('company', 'date', 'profit', 'loss')
def create(self, validated_data):
company_data = validated_data['company']
company, created = Company.objects.get_or_create(**company_data)
validated_data['company'] = company
sheet = BalanceSheet.objects.create(**validated_data)
return sheet
I also had to include the full company data within my curl statement as a nested dict.
I've been trying to use a nested serializer with DRF but it won't display the related item in the output.
Here's my model.py :
class Categorie(models.Model):
nom = models.CharField(max_length=100)
def __unicode__(self):
return unicode(self.nom)
class Item(models.Model):
nom = models.CharField(max_length=100)
disponible_a_la_vente = models.BooleanField(default = True)
nombre = models.IntegerField()
prix = models.DecimalField(max_digits=5, decimal_places=2)
history = HistoricalRecords()
categorie = models.ForeignKey(Categorie, models.CASCADE)
class Meta:
verbose_name = "item"
verbose_name_plural = u"inventaire"
ordering = ['categorie', 'nom']
def __unicode__(self):
return u'{nom} - {nombre}'.format(nom = self.nom, nombre = self.nombre)
and my serializers.py
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('nom',)
class CategorieSerializer(serializers.ModelSerializer):
items = ItemSerializer(many=True)
class Meta:
model = Categorie
fields = ('nom', 'id', 'items')
The view i'm currently testing is very basic :
class InventaireDetail(generics.RetrieveAPIView):
queryset = Categorie.objects.all()
serializer_class = CategorieSerializer
but it gives the error:
AttributeError: Got AttributeError when attempting to get a value for
field items on serializer CategorieSerializer. The serializer
field might be named incorrectly and not match any attribute or key on
the Categorie instance. Original exception text was: 'Categorie'
object has no attribute 'items'.
I've been looking for a while now but i can't get it working even with the help of the doc.
Categorie.items does not exist. By default the reverse relation would get the name Categorie.item_set. You can fix that in two ways.
EITHER: add related_name to your foreign key.
class Item(models.Model):
categorie = models.ForeignKey(Categorie, models.CASCADE, related_name='items')
OR: another solution is to change the CategorieSerializer
class CategorieSerializer(serializers.ModelSerializer):
items = ItemSerializer(many = True, read_only=True, source='item_set')
I can't seem to figure out how to use this thing:
I have these 3 models:
Recipe has an ingredient_list that is comprised of the IngredientType through the Ingredient model.
Here they are (simplified)
class Recipe(models.Model):
name = models.CharField(max_length=200)
ingredient_list = models.ManyToManyField(IngredientType, through='Ingredient')
difficulty =models.CharField(max_length=1,choices=DISH_DIFICULTY,
default=INTERMEDIATE)
cuisine = models.ManyToManyField(Cuisine, related_name='+', null=True,
blank = True)
class Ingredient(models.Model):
ingredient_type = models.ForeignKey(IngredientType)
class Meta:
app_label = 'vcb'
verbose_name = _('Ingredient')
verbose_name_plural = _('Ingredients')
def __unicode__(self):
return ''
class IngredientType(models.Model):
name = models.CharField(max_length=200)
plural_name = models.CharField(max_length=200)
class Meta:
app_label = 'vcb'
verbose_name = _('Ingredient Type')
verbose_name_plural = _('Ingredient Types')
def __unicode__(self):
return self.name
Now in my recipe admin I have:
class IngredientInline(admin.TabularInline):
model = Ingredient
extra = 0
class RecipeAdmin(admin.ModelAdmin):
inlines = [IngredientInline]
My problem is that all the fields, including the Ingredient tab in my admin form are not being translated.
I've specified translations, in the LC_MESSAGES->django.po, to all IngredientTypes objects and all other fields, but when opening the admin api or ingredient list, they're all in English.
(I've compiled the translations and synced them).
I've tried the django-modeltranslation approach, only to find that it can't work with a manyTomany Field.
Is there a form.py I should add? I've been using django default by now, but if that's a lead, do tell.
Help is much appreciated,
Nitzan