I can't update my object within nested object field. In here I can't update name from Movie model. Here is my model.py:
class Movie(models.Model):
name = models.CharField(max_length=800, unique=True)
imdb_rating = models.IntegerField(null=True)
movie_choice = (
('Act', 'Action'),
...........
)
movie_type = models.CharField(max_length=3, choices=movie_choice)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Hiren(models.Model):
movie = models.ForeignKey(Movie)
watched_full = models.BooleanField(default=True)
rating = models.IntegerField()
source = models.CharField(max_length=500, null=True)
watched_at = models.DateField()
quality_choice = (
..................
)
video_quality = models.CharField(max_length=3, choices=quality_choice)
created_at = models.DateField(auto_now_add=True)
updated_at = models.DateField(auto_now=True)
and serializer.py
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields = '__all__'
class HirenSerializer(serializers.ModelSerializer):
movie = MovieSerializer()
class Meta:
model = Hiren
fields = ('movie', 'id', 'watched_full', 'rating', 'source', 'video_quality', 'watched_at')
def update(self, instance, validated_data):
instance.movie.name = validated_data.get('movie.name', instance.movie.name)
instance.watched_full = validated_data.get('watched_full', instance.watched_full)
instance.rating = validated_data.get('rating', instance.rating)
instance.source = validated_data.get('source', instance.source)
instance.video_quality = validated_data.get('video_quality', instance.video_quality)
instance.watched_at = validated_data.get('watched_at', instance.watched_at)
instance.save()
return instance
You didn't call save on related object
def update(self, instance, validated_data):
instance.movie.name = validated_data.get('movie', {}).get('name') or instance.movie.name
instance.watched_full = validated_data.get('watched_full', instance.watched_full)
instance.rating = validated_data.get('rating', instance.rating)
instance.source = validated_data.get('source', instance.source)
instance.video_quality = validated_data.get('video_quality', instance.video_quality)
instance.watched_at = validated_data.get('watched_at', instance.watched_at)
# here
instance.movie.save()
instance.save()
return instance
Related
I would like to add data to table which having a foreignkey relatonship with user model through Django Rest API.
models.py:
class Artiste(models.Model):
slug = models.SlugField(unique=True)
name = models.CharField(max_length=200)
name_vo = models.CharField(max_length=200, blank=True, null=True)
name_vo_romanji = models.CharField(max_length=200, blank=True, null=True)
biographie = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to=artiste_get_upload_to, blank=True, null=True)
date_birth = models.DateTimeField(blank=True, null=True)
date_death = models.DateTimeField(blank=True, null=True)
nationnality = models.ForeignKey(Countrie, related_name='Artiste_countrie', on_delete=models.CASCADE, null=True)
profession = models.ManyToManyField(Profession, related_name='Artiste_profession', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Countrie(models.Model):
slug = models.SlugField(unique=True)
code = models.CharField(unique=True, max_length=2)
name = models.CharField(unique=True, max_length=200)
nationnality = models.CharField(unique=True, max_length=200)
image = models.ImageField(upload_to=countrie_get_upload_to, null=True)
serializers.py:
class ArtisteSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
slug = serializers.SlugField(required=False)
name = serializers.CharField()
name_vo = serializers.CharField(required=False)
name_vo_romanji = serializers.CharField(required=False)
biographie = serializers.CharField(style={'base_template': 'textarea.html'}, required=False)
image = serializers.ImageField(required=False)
date_birth = serializers.DateTimeField(required=False)
date_death = serializers.DateTimeField(required=False)
nationnality = CountrieSerializer(required=False)
profession = ProfessionSerializer(many=True, required=False)
created_at = serializers.DateTimeField(read_only=True)
updated_at = serializers.DateTimeField(read_only=True)
def create(self, validated_data):
print(validated_data)
return Artiste.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.slug = validated_data.get('slug', instance.code)
instance.name = validated_data.get('name', instance.name)
instance.name_vo = validated_data.get('name_vo', instance.name_vo)
instance.name_vo_romanji = validated_data.get('name_vo_romanji', instance.name_vo_romanji)
instance.biographie = validated_data.get('biographie', instance.biographie)
instance.image = validated_data.get('image', instance.image)
instance.date_birth = validated_data.get('date_birth', instance.date_birth)
instance.date_death = validated_data.get('date_death', instance.date_death)
instance.nationnality = validated_data.get('nationnality', instance.nationnality)
instance.save()
return instance
class CountrieSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
slug = serializers.SlugField(required=False)
code = serializers.CharField()
name = serializers.CharField()
nationnality = serializers.CharField()
image = serializers.ImageField(required=False)
def create(self, validated_data):
return Countrie.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.slug = validated_data.get('slug', instance.code)
instance.code = validated_data.get('code', instance.code)
instance.name = validated_data.get('name', instance.name)
instance.nationnality = validated_data.get('nationnality', instance.nationnality)
instance.image = validated_data.get('image', instance.image)
instance.save()
return instance
I would like to have this data when I post a new artiste.
{
'name': 'Bob lenon',
'name_vo': 'test5',
'name_vo_romanji': 'test5',
'nationnality': 1,
}
When I print validated_data of ArtisteSerialiser, I only have this {'name': 'test5', 'name_vo': 'test5', 'name_vo_romanji': 'test5'}, but I sent nationnality data.
you should write 'nationnality = CountrieSerializer(required=False)' line in your ArtisteSerializer . I give advise to you ModelSerializer which form rest_framework.serializer import .
Because in it you write not necessarily each field, you just write them include fields = ()
I am doing CRUD data which has foreign keys and serializers(since I am told to use serializers instead of Forms),even though I have put the correct model and it's names in the product_edit page, the data is showing blank instead of thier saved data ,the wrong sub_category name is coming,this is how the edit page currently looks
serializer:
class CategoriesSerializer(serializers.ModelSerializer):
class Meta:
model = Categories
fields = "__all__"
extra_kwargs = {'category_name': {'required': False}}
class ColorsSerializer(serializers.ModelSerializer):
class Meta:
model = Colors
fields = "__all__"
class POLLSerializer(serializers.ModelSerializer):
# categories = serializers.StringRelatedField(many=False)
# sub_categories = serializers.StringRelatedField(many=False)
# color = serializers.StringRelatedField(many=False)
# size = serializers.StringRelatedField(many=False)
class Meta:
model = Products
fields = "__all__"
class SizeSerializer(serializers.ModelSerializer):
class Meta:
model = Size
fields = "__all__"
class SUBCategoriesSerializer(serializers.ModelSerializer):
class Meta:
model = SUBCategories
fields = "__all__"
below are the models of my CRUD
class Products(models.Model):
categories = models.ForeignKey(Categories,on_delete=models.CASCADE)
sub_categories = models.ForeignKey(SUBCategories,on_delete=models.CASCADE)
color = models.ForeignKey(Colors,on_delete=models.CASCADE)
size = models.ForeignKey(Size,on_delete=models.CASCADE)
# image = models.ImageField(upload_to = 'media/',width_field=None,height_field=None,null=True)
title = models.CharField(max_length=50)
price = models.CharField(max_length=10)
sku_number = models.CharField(max_length=10)
product_details = models.CharField(max_length=300)
quantity = models.IntegerField(default=0)
isactive = models.BooleanField(default=True)
class Categories(models.Model):
#made changes to category_name for null and blank
category_name = models.CharField(max_length=20)
category_description = models.CharField(max_length=20)
isactive = models.BooleanField(default=True)
def __str__(self):
return self.category_name
class Colors(models.Model):
color_name = models.CharField(max_length=10)
color_description = models.CharField(max_length=10)
isactive = models.BooleanField(default=True)
def __str__(self):
return self.color_name
class Size(models.Model):
size_name = models.CharField(max_length=10)
size_description = models.CharField(max_length=20)
isactive = models.BooleanField(default=True)
def __str__(self):
return self.size_name
class SUBCategories(models.Model):
category_name = models.ForeignKey(Categories, on_delete=models.CASCADE)
sub_categories_name = models.CharField(max_length=20)
sub_categories_description = models.CharField(max_length=20)
isactive = models.BooleanField(default=True)
def __str__(self):
return self.sub_categories_name
update function
def update(request,id):
if request.method == 'GET':
print('GET',id)
edit_products = SUBCategories.objects.filter(id=id).first()
s= SUBCategoriesSerializer(edit_products)
category_dict = Categories.objects.filter(isactive=True)
category = CategoriesSerializer(category_dict, many=True)
sub_category_dict = SUBCategories.objects.filter(isactive=True)
sub_category = SUBCategoriesSerializer(sub_category_dict,many=True)
color_dict = Colors.objects.filter(isactive=True)
color = ColorsSerializer(color_dict,many=True)
size_dict = Size.objects.filter(isactive=True)
size = SizeSerializer(size_dict,many=True)
hm = {"context": category.data,"sub_context":sub_category.data,"color_context":color.data,"size_context":size.data,"SUBCategories":s.data}
return render(request,'polls/product_edit.html',hm)
else:
print('POST',id)
editproducts = {}
d = Products.objects.filter(id=id).first()
if d:
editproducts['categories']=request.POST.get('categories')
editproducts['sub_categories']=request.POST.get('sub_categories')
editproducts['color']=request.POST.get('color')
editproducts['size']=request.POST.get('size')
editproducts['title']=request.POST.get('title')
editproducts['price']=request.POST.get('price')
editproducts['sku_number']=request.POST.get('sku_number')
editproducts['product_details']=request.POST.get('product_details')
# print(editsubcategories)
form = SUBCategoriesSerializer(d,data= editproducts)
if form.is_valid():
form.save()
print("form data",form.data)
print('form error',form.errors)
messages.success(request,'Record Updated Successfully...!:)')
return redirect('polls:show')
else:
print(form.errors)
return redirect("polls:show")
where am I going wrong in the code?
you must create product serializer like below
class ProductSerial(ModelSerializer):
class Meta:
model = Products
fields = '__all__'
and pass editproducts to this serializer
and also you have to be careful that pass id's of
categories
sub_categories
color
size
into request.POST data
I have a cartmodel, cartitem and offlinecheckout model. I want to display cartitem instead of cartmodel id, I want to display all the cartitem data which have cart_id = offlinecheckout cart_id. But I got this response.
I tried a lot but didn't get. Anybody will please help me.
views.py
class GetAPI(APIView):
def get(self, request, *args, **kwargs):
serializer = OfflineSerializer()
return Response(serializer.data)
models.py
class OfflineCheckOut(models.Model):
billing_name = models.CharField(max_length=254)
billing_phone_no = models.CharField(max_length=15)
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
cart = models.ForeignKey('cart.CartModel', on_delete=models.CASCADE)
cartitem = models.ManyToManyField(CartItem, blank=True)
# time_slot = models.ForeignKey('category.TimeSlot', on_delete=models.CASCADE)
address = models.ForeignKey('cart.CustomerAddress', on_delete=models.CASCADE)
status_choice = [
('0', 'Offline'),
('1', 'Online')
]
status = models.CharField(max_length=3, choices=status_choice, default=0)
# date = models.DateField()
date = models.DateField()
time_slot = models.ForeignKey('category.TimeSlot', on_delete=models.SET_NULL, null=True, blank=True)
order_id = models.CharField(max_length=254, blank=True)
# date = models.DateField()
razorpay_payment_id =models.CharField(max_length=254, blank=True)
razorpay_signature = models.CharField(max_length=254, blank=True)
paid = models.BooleanField(default=False)
service = models.ForeignKey('service.ServiceProvider', on_delete=models.SET_NULL, null=True, blank=True)
class CartModel(models.Model):
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
status_choice = [
('1', 'open'),
('2', 'closed')
]
status = models.CharField(max_length=2, choices=status_choice, default=1)
validated = models.BooleanField(default=False)
def __str__(self):
return self.user.username
#property
def total_price(self):
return self.cartitem_set.aggregate(
total_price=Sum(F('quantity') * F('price'))
)['total_price'] or Decimal('0')
class CartItem(models.Model):
cart = models.ForeignKey('CartModel', on_delete=models.CASCADE)
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
service = models.ForeignKey('accounts.SubCategory', on_delete=models.CASCADE)
defects = models.ForeignKey('category.Defects', on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
price = models.IntegerField()
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now_add=True)
order_placed = models.BooleanField(default=False)
serializers.py
class OfflineSerializer(serializers.ModelSerializer):
def total(self, obj):
return obj.total
total = serializers.IntegerField(read_only=True)
cartitems = CartItemSerializer( read_only=True, many=True)
class Meta:
model = OfflineCheckOut
fields = ['user', 'billing_name','billing_phone_no','cartitem', 'cartitems','cart', 'date', 'time_slot', 'address', 'total']
extra_fields = ['total', 'cartitems']
You have to put them in a serializer for CartModel. Then OfflineSerializer will use that for cart field.
class CartModelSerializer(serializers.ModelSerializer):
cartitem_set = CartItemSerializer(read_only=True, many=True)
class Meta:
model = CartModel
fields = [
"cartitems_set",
# other fields here
]
class OfflineSerializer(serializers.ModelSerializer):
def total(self, obj):
return obj.total
total = serializers.IntegerField(read_only=True)
cart = CartModelSerializer(read_only=True)
class Meta:
model = OfflineCheckOut
fields = ['user', 'billing_name','billing_phone_no','cartitem', 'cartitems','cart', 'date', 'time_slot', 'address', 'total']
extra_fields = ['total', 'cartitems']
EDIT: Changed the related name serializer from cartlineitems_set to cartlineitem_set
I can be able to add the first data entry but after that editing the existing data or adding the new data causes MultiValueDictKeyError at /admin/api/digitalpost/9b763eae-cb8b-4473-af5d-5d4d91323ae1/change/
"u'contentlist_set-0-basemodel_ptr'".
Models.py
class BaseModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
version = models.FloatField(default=1.0)
created_at = models.DateTimeField(auto_now_add=True)
def image_tag(self):
self.url = 'http://127.0.0.1:8000/' + self.picture.name
return u'<img src="%s" />' % self.picture.url
image_tag.short_description = 'Thumbnail'
image_tag.allow_tags = True
class Client(BaseModel):
parent = models.ForeignKey('self',on_delete=models.SET_NULL, blank=True, null=True, related_name='brands')
name = models.CharField(max_length=120, unique=True)
picture = models.ImageField(upload_to="static/images/digital")
list_display = ('name','parent',)
description = models.CharField(max_length=250)
def __unicode__(self):
if self.parent:
return "{} {}".format(self.parent.name, self.name)
else:
return self.name
def parent_brand(self):
return str(self)
parent_brand.short_description = 'NAME'
class Meta:
ordering = ['parent__name','name']
class Category(BaseModel):
title = models.CharField(max_length=64, unique=64)
description = models.CharField(max_length=256, null=True, blank=True)
def __unicode__(self):
return self.title
class Meta:
ordering = ['-created_at']
verbose_name_plural = "categories"
class DigitalPost(BaseModel):
title = models.CharField(max_length=100)
brand = models.ForeignKey(Client, on_delete=models.SET_NULL, blank=True, null=True, )
launch_date = models.DateField(blank=True, null=True)
order = models.IntegerField()
def __unicode__(self):
return self.title
class Meta:
ordering = ['order']
class ContentList(BaseModel):
title = models.CharField(max_length=100)
description = models.CharField(max_length=256, null=True, blank=True)
picture = models.ImageField(upload_to="static/images/digital", blank=True)
post = models.ForeignKey(DigitalPost, on_delete=models.SET_NULL, null=True, blank=True)
# post_category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
def __unicode__(self):
return self.title
class Meta:
ordering = ['title']
admin.py
class ContentListForm(forms.ModelForm):
class Meta:
model = models.ContentList
fields = '__all__'
class ContentListInline(admin.TabularInline):
model = models.ContentList
form = ContentListForm
fk_name = 'post'
exclude = ('id', 'version')
class DigitalPostForm(forms.ModelForm):
class Meta:
model = models.DigitalPost
fields = '__all__'
#admin.register(models.DigitalPost)
class DigitalPostAdmin(ActiveStaffPermittedModel):
inlines = [
ContentListInline,
]
form = DigitalPostForm
actions = ['delete_selected']
exclude = ('id', 'version',)
readonly_fields = ('created_at',)
def delete_selected(self, request, obj):
for o in obj.all():
self.delete_one(request, o)
delete_selected.short_description = "Delete selected Posts"
I want to edit the cuisines associated with a dish on the dish panel in django admin. I am trying to use InlineModelAdmin. The problem is that I can edit the DishCuisinesMap objects but not the cuisines object.
Here is the screenshot:
This is my models.py:
class Cuisines(models.Model):
cuisine_id = models.IntegerField(primary_key=True)
cuisine_mtom = models.ManyToManyField('DishInfo', through='DishCuisinesMap')
name = models.TextField()
cuisine_sf_name = models.TextField()
type = models.IntegerField()
insert_time = models.DateTimeField()
update_time = models.DateTimeField()
class Meta:
managed = False
db_table = 'cuisines'
class DishCuisinesMap(models.Model):
dish = models.ForeignKey('DishInfo', on_delete=models.PROTECT,
related_name='dcm_dish')
cuisine = models.ForeignKey(Cuisines, on_delete=models.PROTECT,
related_name='dcm_cuisine')
insert_time = models.DateTimeField()
update_time = models.DateTimeField()
class Meta:
managed = False
db_table = 'dish_cuisines_map'
unique_together = (('dish', 'cuisine'),)
class DishInfo(models.Model):
dish_id = models.BigIntegerField(primary_key=True)
bid = models.ForeignKey(Brands, on_delete=models.PROTECT, db_column='bid',
related_name='dinfo_brand')
name = models.TextField()
is_live = models.IntegerField()
veg_nonveg_ind = models.SmallIntegerField(blank=True, null=True)
sf_name = models.TextField()
descr = models.TextField(blank=True, null=True)
expert_tag = models.TextField(blank=True, null=True)
special_desc = models.TextField(blank=True, null=True)
reco_percent = models.IntegerField(blank=True, null=True)
one_liner = models.TextField(blank=True, null=True)
nutrition = JSONField()
insert_time = models.DateTimeField()
update_time = models.DateTimeField()
images = ArrayField(models.TextField())
class Meta:
managed = False
db_table = 'dish_info'
unique_together = (('bid', 'name'), ('bid', 'sf_name'),)
def __unicode__(self):
brand_name = self.bid.name
return self.name
and this is my admin.py:
class CityDishFilter(admin.SimpleListFilter):
title = ('city name')
parameter_name = 'city_id'
def lookups(self, request, model_admin):
list_of_cities = list()
queryset = Cities.objects.all()
for city in queryset:
list_of_cities.append(
(str(city.city_id), city.name)
)
return list_of_cities
def queryset(self, request, queryset):
query_params = request.GET
if self.value():
city_query = DelLocations.objects.filter(city__city_id=self.value())\
.values('del_id')
loc_query = DelLocationsMapping.objects.filter(del_loc__in=
city_query).values('plot')
dopm_query = DishOutletPlatMapping.objects.filter(plot__in
=loc_query).values('dish')
final_query = DishInfo.objects.filter(dish_id__in=dopm_query)
if 'veg_nonveg_ind' in query_params:
final_query = final_query.filter(veg_nonveg_ind=query_params.get('veg_nonveg_ind'))
if 'is_live' in query_params:
final_query = final_query.filter(is_live=query_params.get('is_live'))
return final_query
return queryset
class BrandDishFilter(admin.SimpleListFilter):
title = ('brand name')
parameter_name = 'brand_id'
def lookups(self, request, model_admin):
query_params = request.GET
list_of_brands = list()
if 'city_id' in query_params:
city_query = DelLocations.objects.filter(city__city_id=query_params.get('city_id'))\
.values('del_id')
loc_query = DelLocationsMapping.objects.filter(del_loc__in=
city_query).values('plot')
dopm_query = DishOutletPlatMapping.objects.filter(plot__in
=loc_query).values('dish')
dish_query = DishInfo.objects.filter(dish_id__in=dopm_query).\
values('bid').distinct()
brand_query = Brands.objects.filter(bid__in=dish_query).order_by('name')
for brand in brand_query:
list_of_brands.append(
(str(brand.bid), brand.name)
)
return list_of_brands
else:
brand_query = Brands.objects.all().order_by('name')
for brand in brand_query:
list_of_brands.append(
(str(brand.bid), brand.name)
)
return list_of_brands
def queryset(self, request, queryset):
if 'brand_id' in request.GET:
queryset = queryset.filter(bid=self.value())
return queryset
return queryset
class DishCuisinesInline(admin.TabularInline):
model = DishCuisinesMap
extra = 1
class CuisinesAdmin(admin.ModelAdmin):
inlines = [DishCuisinesInline,]
fields = ("name", "cuisine_sf_name", "type")
class DishInfoAdmin(admin.ModelAdmin):
list_select_related = ('bid',)
list_display = ('name', 'brand_name')
fieldsets = (
(None, {'fields': ('name', 'sf_name', 'is_live', 'veg_nonveg_ind',
'one_liner',
)
}
),
('Advanced options', {'classes': ('collapse',),
'fields': ('descr', 'images')
}
)
)
search_fields = ['name', 'bid__name']
list_filter = ('veg_nonveg_ind', 'is_live', CityDishFilter, BrandDishFilter) #, 'bid__name'
inlines = [DishTimingsInline, DishCuisinesInline]
# changing the size of the text fields:
formfield_overrides = {
models.TextField: {'widget': Textarea(
attrs = {'rows': 4,
'cols': 50})
},
}
def brand_name(self, obj):
return obj.bid.name
admin.site.register(DishInfo, DishInfoAdmin)
admin.site.register(Cuisines, CuisinesAdmin)
The django docs here say that membership objects can be edited from Person or the Group detail pages, but what is way to edit the group from the person details page?
In my case I need a way to edit the cuisines from the dish page , I am pretty new to django. Any help is greatly appreciated.