Django CreateAPIView not saving image portion of django model - django-models

I am trying to make a django rest api which allows admin users to add images which the api clients can sync and display. My view responsible for creating the Clothing model, which holds a title and an image, is not working as it only saves the title but not the image.
Here is the Clothing model:
class Clothing(models.Model):
title = models.CharField(max_length=50, blank=False)
img = models.ImageField(blank=True, null=True, upload_to='catalog/')
Here is the view:
class AddClothingView(CreateAPIView):
queryset = Clothing.objects.all()
serializer_class = ClothingSerializer
And here is the serializer:
class ClothingSerializer(ModelSerializer):
class Meta:
model = Clothing
fields = '__all__'
How can I fix this such that the images are saved in the catalog/ folder in my project?

Related

Django Rest Framework: Form field populated with object representation after validation error

After the form is validated the field is populated with object representation from memory.
Form screenshot
I am using MoneyField in my Product model from django-money library.
models.py
class Product(models.Model):
CURRENCY_CHOICES = (
('EUR', 'EUR'),
('USD', 'USD'),
('GBP', 'GBP'),
('PLN', 'PLN')
)
price = MoneyField(max_digits=10, decimal_places=2, blank=False,
currency_choices=CURRENCY_CHOICES)
serializers.py
class ProductSerializer(serializers.ModelSerializer):
price_currency = serializers.ChoiceField(choices=Product.CURRENCY_CHOICES)
class Meta:
model = Product
fields = (
'price','price_currency',
)
views.py
class ProductList(generics.ListCreateAPIView):
serializer_class = ProductSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
queryset = Product.objects.all()
I would really appreciate any suggestions on why this is happening.

How to show this blog django backend by its id in react frontend

models
class Blog(models.Model):
title = models.CharField(max_length=50)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
serializers
class BlogSerializer(serializers.ModelSerializer):
class Meta:
model = Blog
fields = '__all__'
views
class BlogDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Blog.objects.all()
serializer_class = BlogSerializer
and urls
from django.urls import path
from .views import BlogDetailView
urlpatterns = [
path('blog/<int:pk>/', BlogDetailView.as_view()),
]
I'm trying to make a blog website. How can we show blogs by id in react js
I think you want to get list of blogs ordering by id. So, you can do like this-
views -
class BlogDetailView(generics.ListAPIView):
queryset = Blog.objects.all().order_by('-id') # descending order
serializer_class = BlogSerializer

ImageChooserPanel wrongfully showing as Select widget

I find stack overflow very difficult to use and I am probably going to be slammed for trying but here goes.
I am trying to get an image field to bring up the standard wagtail image chooser dialog but it's displaying in wagtail admin as a Select widget with no option to upload new image.
from django.db import models
from modelcluster.fields import ParentalKey
from wagtail.core.models import Page, Orderable
from modelcluster.models import ClusterableModel
from wagtail.admin.edit_handlers import (
FieldPanel,
MultiFieldPanel,
InlinePanel,
PageChooserPanel,
)
from wagtail.images.edit_handlers import ImageChooserPanel
class HomePage(Page):
def get_context(self, request):
context = super().get_context(request)
# Add extra variables and return the updated context
context['sections'] = Sections.objects.all()
return context
class Sections(ClusterableModel):
title = models.CharField(max_length = 60, blank = False, null= True)
section_image = models.ForeignKey(
"wagtailimages.Image",
null=True,
blank=False,
on_delete=models.SET_NULL,
related_name="+",
)
panels = [
FieldPanel("title"),
ImageChooserPanel("section_image"),
InlinePanel("albums"),
]
class Albums(ClusterableModel):
title = models.CharField(max_length = 60, blank = False, null= True)
section = ParentalKey("Sections", related_name="albums")
panels = [
FieldPanel("title"),
InlinePanel("images"),
]
class GalleryImage(Orderable):
album = ParentalKey("Albums", related_name="images")
galleryimage = models.ForeignKey(
"wagtailimages.Image",
null=True,
blank=False,
on_delete=models.SET_NULL,
related_name="+",
)
panels = [
ImageChooserPanel("galleryimage"),
]
This is probably a rookie mistake and would appreciate if someone can show me why gallery image is not rendering correctly.
Unfortunately this is an open bug in Wagtail: https://github.com/wagtail/wagtail/issues/5126
Historically, nesting InlinePanels has not been well-supported in Wagtail - there are some improvements in progress which will hopefully make it into the forthcoming 2.7 release, but this particular issue is still outstanding.

How to retrieve and assign current user object to a field in Wagtail admin?

I have a few Django models that I display in the admin using wagtail’s modelAdmin. few of the fields in the models are referencing the user model. Since I’m not creating the form/page and it’s handled by wagtail, how do I pass the current user object to the field when it’s saved? That is, the created and updated by fields should have the current user object assigned to them.
See code snippet below, currently I'm assigning the user manually by querying, instead I'd like to get the current user.
from django.db import models
from django.conf import settings
from django.contrib.auth import get_user_model
from wagtail.admin.forms import WagtailAdminPageForm
STATUS_CHOICES = (
(1, 'Active'),
(2, 'Inactive')
)
class BasePageForm(WagtailAdminPageForm):
def save(self, commit=True):
auth_user_model = get_user_model()
default_user = auth_user_model.objects.get(username='admin')
page = super().save(commit=False)
if not page.pk:
page.created_by = default_user
page.updated_by = default_user
else:
page.updated_by = default_user
if commit:
page.save()
return page
class BaseModel(models.Model):
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='created%(app_label)s_%(class)s_related'
)
created_at = models.DateTimeField(auto_now_add=True)
updated_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='updated%(app_label)s_%(class)s_related'
)
updated_at = models.DateTimeField(auto_now=True)
status = models.IntegerField(choices=STATUS_CHOICES, default=1)
class Meta:
abstract = True # Set this model as Abstract
base_form_class = BasePageForm

Wagtail generic gallery implementation and OneToOneField

http://docs.wagtail.io/en/v1.13.1/getting_started/tutorial.html
The wagtail getting_started tutorial intros a blog gallery feature, implements as below:
class BlogPage(Page):
...
class BlogPageGalleryImage(Orderable)
page = ParentalKey(BlogPage, related_name='gallery_images')
image = ...
This way works, however BlogPageGalleryImage couples with BlogPage model. My intention is to make a generic gallery model which can be embbed with any model(page). The idea is using an intermediate Gallery model:
class BlogPage(Page):
gallery = models.OneToOneField(Gallery, on_delete=models.SET_NULL, null=True)
...
class Gallery(Page):
pass
class GalleryImage(Orderable):
gallery = ParentalKey(Gallery, related_name='images')
Then in code, we can get the images via blog.gallery.images.
My question is how to get it work with wagtail admin interface to inline create/edit the gallery object (OneToOneField) when editing the blog page object.
One way to do this is via a more generic relationship for your Page-Image connection, relating this to the Page model, rather than a specific BlogPage model.
This means that any page can have gallery images, you just need to expose the field to content panels via an InlinePanel.
You can also create a Mixin class to make some helpful methods available without rewriting them each time.
Here is an example:
from django.db import models
from wagtail.admin.edit_handlers import InlinePanel
from wagtail.core.models import Orderable, Page
from wagtail.images.edit_handlers import ImageChooserPanel
class ImageGalleryRelationship(Orderable, models.Model):
""" Relationship between any `Page` and `Image` for an image gallery."""
page = ParentalKey(Page, related_name='gallery_page')
image = models.ForeignKey('wagtailimages.Image', related_name='gallery_image')
panels = [ImageChooserPanel('image')]
class PageGalleryMixin():
def gallery_images(self):
images = [g.image for g in self.gallery_page.all()]
return images
class BlogPage(Page, PageGalleryMixin):
# all page fields, gallery does not need to be defined here
content_panels = Page.content_panels + [
InlinePanel('gallery_page', label='Image Gallery'),
#...
]
Note: This is not a OneToOne connection, InlinePanel requires a ParentalKey relationship. There is no real 'Gallery' model in this solution just a set of orderable relationships.
In general app (or wherever), models.py
class PageGalleryImage(Orderable):
page = ParentalKey(Page,
on_delete=models.CASCADE,
related_name='image_gallery')
image = models.ForeignKey('wagtailimages.Image',
on_delete=models.CASCADE,
related_name='page_gallery_image')
caption = models.CharField(blank=True, max_length=250)
panels = [
ImageChooserPanel('image'),
FieldPanel('caption'),
]
Other apps as blog, models.py:
class BlogPage(Page):
content_panels = Page.content_panels + [
...
InlinePanel('image_gallery', label="Gallery images"),
]
This provides one app = one gallery.

Resources