I have 2 similars forms so I decide to inherite one form from another and it looks like:
class EditModuleForm(forms.Form):
category_name = forms.CharField(label='Name', max_length=100)
image = forms.ImageField(label='Icon', required=False)
def clean_image(self):
image = self.cleaned_data.get('image', None)
if image:
check_image_size(image)
class NewCategoryForm(EditModuleForm):
category_slug = forms.CharField(label="Slug", max_length=10)
field_order = ['category_name', 'category_slug', 'image']
def clean_image(self):
super(NewCategoryForm, self).clean_image()
and during using NewCategoryForm image is not validated and value is None. Looks like this form can't get value from image field. Could somebody give me a hint what I'm doing wrong?
You aren't returning the cleaned data from your clean_image method, the clean_<field> methods allow us to change the data for the field and hence we must return the data from the method. Also you don't need to override the method inside your subclass:
class EditModuleForm(forms.Form):
category_name = forms.CharField(label='Name', max_length=100)
image = forms.ImageField(label='Icon', required=False)
def clean_image(self):
image = self.cleaned_data.get('image', None)
if image:
check_image_size(image)
return image
class NewCategoryForm(EditModuleForm):
category_slug = forms.CharField(label="Slug", max_length=10)
field_order = ['category_name', 'category_slug', 'image']
Related
My class is
from django.db import models
from .dir import my_func
class Upload(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(upload_to='images')
img_content = my_func(image)
def __str__(self):
return self.title
and I'm not able to pass the image because of an E006 error
is there a way to avoid it?
because I can call the function but I need to know the name of the newly uploaded image.
thanks in advnace
You define a property that will obtain the value for image:
class Upload(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(upload_to='images')
#property
def img_content(self):
return my_func(self.image.name)
I want to tag users in an image and save it, I used nested serializer since you can tag more than one user in an image.
The problem is that the image is saved without the tags(they are none).
Here is the codes:
models.py
class TagUsername(models.Model):
# the tag is person
tag = models.ManyToManyField(User, related_name='tag_username')
image = models.ForeignKey(Image)
# # De tection Rectangle specs(width,height, coordinate x & coordinate y)
# width = models.FloatField()
# length = models.FloatField()
# xCoordinate = models.FloatField()
# yCoordinate = models.FloatField()
# who added this tag
user = models.ForeignKey(User, on_delete=models.CASCADE)
serializers.py
class TagUsernameSerializer(serializers.ModelSerializer):
tag = UsernameTagSerializer(read_only=True, many=True)
user = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field="username")
image = serializers.CharField(source='image_id')
class Meta:
model = TagUsername
fields = ('tag', 'user', 'image')
UsernameTagSerializer:
class UsernameTagSerializer(serializers.ModelSerializer):
# username = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field="username")
class Meta:
model = User
# fields I want only
fields = ('username', )
Any idea whats wrong !
You need to override create method to save nested objects. Try this:
def create(self, validated_data):
tag_username = super().create(validated_data)
for tag in validated_data['tag']:
user = User.objects.get(username=tag['username']
tag_username.tag.add(user)
return tag_username
You can find more details about writable nested serialization in docs.
How to create an object for a Django model with a many to many field?
From above question i come to know we can save Many to Many field later only.
models.py
class Store(models.Model):
name = models.CharField(max_length=100)
class Foo(models.Model):
file = models.FileField(upload_to='')
store = models.ManyToManyField(Store, null=True, blank=True)
views.py
new_track.file = request.FILES['file']
new_track.save()
And file uploading working fine then later i modify my code to add store then i am here...
Now i am sure db return id's here. Then i tried with my below code but that's given me error only
x = new_track.id
new = Foo.objects.filter(id=x)
new.store.id = request.POST['store']
new.save()
ok so the error here is 'QuerySet' object has no attribute 'store'
And also i tried with add that's now working either.
So the question is how to save()
the right way of saving objects with manytomany relations would be:
...
new_track.file = request.FILES['file']
new_track.save()
new_store = Store.objects.get(id=int(request.POST['store']))
new_track.store.add(new_store)
As of 2020, here's my approach to saving ManyToMany Field to a given object.
Short Answer
class HostingRequestView(View):
def post(self, request, *args, **kwargs):
form = VideoGameForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.updated_by = request.user
obj.save()
selected_categories = form.cleaned_data.get('category') #returns list of all selected categories e.g. ['Sports','Adventure']
#Now saving the ManyToManyField, can only work after saving the form
for title in selected_categories:
category_obj = Category.objects.get(title=title) #get object by title i.e I declared unique for title under Category model
obj.category.add(category_obj) #now add each category object to the saved form object
return redirect('confirmation', id=obj.pk)
Full Answer
models.py
class Category(models.Model):
title = models.CharField(max_length=100, null=True, unique=True)
class VideoGame(models.Model):
game_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50, blank=False, null=False)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=False, on_delete=models.CASCADE)
category = models.ManyToManyField(Category) #ManyToMany Category field
date_added = models.DateTimeField(auto_now_add=True, verbose_name="date added")
forms.py ModelForm
class VideoGameForm(forms.ModelForm):
CATEGORIES = (
('Detective', 'Detective'),
('Sports', 'Sports'),
('Action', 'Action'),
('Adventure', 'Adventure'),
)
category = forms.MultipleChoiceField(choices=CATEGORIES, widget=forms.SelectMultiple())
class Meta:
model = VideoGame
fields = ['name', 'category', 'date_added']
views.py on POST
class HostingRequestView(View):
def post(self, request, *args, **kwargs):
form = VideoGameForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.updated_by = request.user
obj.save()
selected_categories = form.cleaned_data.get('category') #returns list of all selected categories e.g. ['Sports','Adventure']
#Now saving the ManyToManyField, can only work after saving the form
for title in selected_categories:
category_obj = Category.objects.get(title=title) #get object by title i.e I declared unique for title under Category model
obj.category.add(category_obj) #now add each category object to the saved form object
return redirect('confirmation', id=obj.pk)
URL path for redirect
urlpatterns = [
path('confirmation/<int:id>/', Confirmation.as_view(), name='confirmation'),
]
I hope this can be helpful. Regards
new.stores.all()
returns all stores linked to the object.
Maybe:
Change Foo to Tracks
Tracks.objects.filter(id=x) to Tracks.objects.get(id=x)
Let me know how it goes
why this confusion so much.. you are getting the id there then, call the store like
new_track.save()
new_track.store.add(request.POST['store'])
I have following problem:
I'm writing an AJAX view in django that serves JSON data about image list from a model that uses ImageSpecField from django-imagekit extension:
class Image(models.Model):
title = models.CharField(max_length=120)
img = models.ImageField(upload_to="images")
thumb = ImageSpecField(source="img",
id="core:image:image_thumbnail"
)
objects = models.Manager()
json_data = JSONConvertibleManager()
The model uses custom manager for conversion into JSON (JSONConvertibleManager) using built-in Django serializer (instance of django.core.serializers).
My problem is that all the fields are properly serialized except for the ImageSpecField which is getting completely ommited. Is it possible to return instance.thumb.url value during serialization?
Just for info I was using Django Rest Framework and so used the serializer class from that library.
My model:
class Photo(models.Model):
""" Photograph """
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=255)
original_image = models.ImageField(upload_to='boxes')
formatted_image = ImageSpecField(source='original_image', format='JPEG',
options={'quality': 90})
thumbnail = ImageSpecField([Adjust(contrast=1.2, sharpness=1.1),
ResizeToFill(200, 115)], source='original_image',
format='JPEG', options={'quality': 90})
num_views = models.PositiveIntegerField(editable=False, default=0)
My serializer:
class PhotoSerializer(serializers.ModelSerializer):
original_image = serializers.Field('original_image.url')
thumbnail = serializers.Field('thumbnail.url')
class Meta:
model = Photo
fields = ('id', 'title', 'original_image', 'thumbnail',)
Unfortunately, the accepted answer does not work anymore due to changes in DRF (prob. v2.x). Substitute this line and it will work with current versions (3.5.3):
thumbnail = serializers.ReadOnlyField(source="thumbnail.url")
Another solution to have more control (e.g. url modifications) would be:
class PhotoSerializer(serializers.ModelSerializer):
original_image = serializers.SerializerMethodField()
class Meta:
model = Photo
fields = ('id', 'title', 'original_image')
def get_original_image(self, obj):
# some processing
return obj.original_image.url
A little improvement based on the nice solution given by #Insa ...
class PhotoSerializer(serializers.ModelSerializer):
original_image = serializers.SerializerMethodField()
class Meta:
model = Photo
fields = ('id', 'title', 'original_image')
def get_original_image(self, obj):
if bool(obj.original_image):
return self.context['request'].build_absolute_uri(obj.original_image.url)
return ''
to obtain the absolute url for the thumbnail, as happens by default for all ImageFields
I have a model like this:
class MyModel(models.Model):
REGULAR = 1
PREMIUM = 2
STATUS_CHOICES = ((REGULAR, "regular"), (PREMIUM, "premium"))
name = models.CharField(max_length=30)
status = models.IntegerField(choices = STATUS_CHOICES, default = REGULAR)
class MyForm(forms.ModelForm):
class Meta:
model = models.MyModel
In a view I initialize one field and try to make it non-editable:
myform = MyForm(initial = {'status': requested_status})
myform.fields['status'].editable = False
But the user can still change that field.
What's the real way to accomplish what I'm after?
Step 1: Disable the frontend widget
Use the HTML readonly attribute:
http://www.w3schools.com/tags/att_input_readonly.asp
Or disabled attribute:
http://www.w3.org/TR/html401/interact/forms.html#adef-disabled
You can inject arbitrary HTML key value pairs via the widget attrs property:
myform.fields['status'].widget.attrs['readonly'] = True # text input
myform.fields['status'].widget.attrs['disabled'] = True # radio / checkbox
Step 2: Ensure the field is effectively disabled on backend
Override your clean method for your field so that regardless of POST input (somebody can fake a POST, edit the raw HTML, etc.) you get the field value that already exists.
def clean_status(self):
# when field is cleaned, we always return the existing model field.
return self.instance.status
From django 1.9:
from django.forms import Textarea
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = '__all__'
widgets = {'my_field_in_my_model': Textarea(attrs={'cols':80,'rows':1}),}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['my_field_in_my_model'].disabled = True
Have you tried using the exclude function?
something like this
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title')
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
exclude = ('birth_date',)
Reference Here
Just customize the widget instance for the status field:
class MyModel(models.Model):
REGULAR = 1
PREMIUM = 2
STATUS_CHOICES = ((REGULAR, "regular"), (PREMIUM, "premium"))
name = models.CharField(max_length=30)
status = models.IntegerField(choices = STATUS_CHOICES, default = REGULAR)
class MyForm(forms.ModelForm):
status = forms.CharField(widget=forms.TextInput(attrs={'readonly':'True'}))
class Meta:
model = models.MyModel
see: Django Documentation
There is a very easy way of doing it:
class GenerateCertificate(models.Model):
field_name = models.CharField(
max_length=15,
editable=False)
def __unicode__(self):
return unicode(self.field_name)
The editable=False will make the field disabled for editing.