How do I upload an image with Django with an ImageField? - python

guys.
I have a problem where I want to change the thumbnail on my website of a Model (talking about 3D printing here but also Django ones) but Django does not change it.
models.py
class Model3D(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=300)
description = models.TextField(max_length=800, blank=True)
thumbnail = models.ImageField(upload_to='models/thumbnails', null=True)
I tried two different forms.py
Version 1
class ImageUploadForm(forms.Form):
"""Image upload form."""
image = forms.ImageField()
Version 2 (ignore the following name, it was just a fast test)
class ModelCreateForm(forms.ModelForm):
class Meta:
model = Model3D
fields = ['name', 'thumbnail']
help_texts = {
'thumbnail': ("Gebe hier den Namen des Modelles ein.")
}
views.py
def save_settings(request, pk):
model = get_object_or_404(Model3D, pk=pk)
if request.method == 'POST':
# print("request.method == 'POST'" + str(dir(saveModel)))
model.name = request.POST.get('name', model.name)
model.description = request.POST.get('description', model.description)
form = ImageUploadForm(request.POST, request.FILES)
if form.is_valid():
model.thumbnail = form.cleaned_data['image']
model.save()
return HttpResponse('image upload success')
model.save()
return redirect('settings_model', pk=model.pk)
return redirect('settings_model', pk=model.pk)
I do have enctype="multipart/form-data in my template. Please help!

Related

Failure to save certain attributes from ModelForm to django database (Logic error)

I have a ModelForm called ListingForm. It takes data from a user but I have stopped some of the model attributes from appearing in this form as I want to feed data to those myself. I have put print statements in my createlisting function in views.py to inspect if the data is actually being saved correctltly, it turns out the data is being saved. Here is the createlisting function:
def create_listing(request):
if request.method == 'POST':
import datetime
listing_form = ListingForm(request.POST, request.FILES)
if listing_form.is_valid():
bid = listing_form.cleaned_data['starting_bid']
print(bid)
listing_form.save(commit=False)
listing_form.user = request.user
print(listing_form.user)
listing_form.date_made = datetime.datetime.today()
listing_form.is_active = True
listing_form.category = Category.objects.get(name=listing_form.cleaned_data['listing_category'])
print(listing_form.category)
#The form is being saved correctly here, and the print statements give the correct results in my terminal
listing_form.save()
Bid.objects.create(user= request.user, value=bid, listing=listing_form.instance)
all_listings = Listing.objects.all()
return render(request, 'auctions/index.html', {
'all_listings': all_listings })
else:
listing_form = ListingForm()
return render(request, 'auctions/createlisting.html',{
'listing_form':listing_form
})
However, when I try to access the data from the model Listing from which the ListingForm is inheriting, the print statements I have put for debugging return the default values for certain fields (category and user) instead of the values I have saved in the ListingForm.
Here is the code that allows me to view the data for the model instance I have created. Mind you, all the other fields have saved correctly except for the fields category and user:
def view_listing(request, listing_id):
listing = Listing.objects.get(pk=listing_id)
#the print results return the default values for the fields category and user instead of the values I saved in my ModelForm
print(listing.category)
print(listing.user)
if request.user == listing.user:
return render(request, 'auctions/view_listing.html', {
'listing': listing,
'flag':True,
'count': listing.bids.all().count()
})
else:
return render(request, 'auctions/view_listing.html',{
'listing':listing,
'count': listing.bids.all().count()
})
What could be the problem with my code?
Also, let me provide the code for some of my models and a form as the error might be embedded in those:
Listing Model:
class Listing(models.Model):
NAME_CHOICES = [
('Fashion', 'Fashion'),
('Toys','Toys'),
('Electronics','Electronics'),
('Home', 'Home'),
('Other', 'Other')
]
title = models.CharField(max_length= 64)
date_made = models.DateTimeField(auto_now_add=True)
description = models.TextField()
user = models.ForeignKey(User, to_field='username', on_delete=models.CASCADE, related_name='user_listings', null=True)
starting_bid = models.DecimalField(decimal_places=2, max_digits=264, default=10.00)
upload_image = models.ImageField(blank=True, upload_to='media/media')
category = models.ForeignKey(Category, on_delete=models.CASCADE, to_field='name', related_name='category_listings', default=NAME_CHOICES[4][0], db_constraint=False)
listing_category = models.CharField(max_length=12, choices=NAME_CHOICES, null=True, default=NAME_CHOICES[4][0])
is_active = models.BooleanField(default=True)
watchlist = models.ForeignKey('Watchlist', on_delete=models.DO_NOTHING, related_name='listings', null=True)
Category Model:
class Category(models.Model):
NAME_CHOICES = [
('Fashion', 'Fashion'),
('Toys','Toys'),
('Electronics','Electronics'),
('Home', 'Home'),
('Other', 'Other')
]
name = models.CharField(max_length=12, choices= NAME_CHOICES, unique=True)
User Model:
class User(AbstractUser):
def __str__(self):
return f'{self.username} '
ListingForm`` (ModelForm```):
class ListingForm(ModelForm):
class Meta:
model = Listing
exclude = [
'date_made',
'user',
'category',
'is_active',
'watchlist'
]
Any form of help would be greatly appreciated.
When you call listing_form.save(commit=False) it returns an unsaved model instance with the submitted values. If you assign that to a variable, you can use it to set the other field values and save:
def create_listing(request):
if request.method == 'POST':
import datetime
listing_form = ListingForm(request.POST, request.FILES)
if listing_form.is_valid():
bid = listing_form.cleaned_data['starting_bid']
listing = listing_form.save(commit=False)
listing.user = request.user
listing.date_made = datetime.datetime.today()
listing.is_active = True
listing.category = Category.objects.get(name=listing_form.cleaned_data['listing_category'])
listing.save()
Bid.objects.create(user=request.user, value=bid, listing=listing)
# You should probably use HttpResponseRedirect to an `all_listings` page, rather than displaying them here
all_listings = Listing.objects.all()
return render(request, 'auctions/index.html', {
'all_listings': all_listings })
Here's a link to the ModelForm.save() docs.

how can i create rows in 2 models(tables) with reusable functions based on one form

I want to save data in two models from a single POST request. Two different models (OF, Encours)
Here's my models.py:
class OF(models.Model):
Id_OF= models.BigAutoField(primary_key=True)
Numero_Of = models.BigIntegerField(unique=True,blank=False)
class Dimension_OF(models.TextChoices):
PD_inférieur_à_500mm="PD"
MD_Entre_500_et_1500mm="MD"
GD_supérieur_à_1500mm="GD"
Dimension_OF = models.CharField(max_length=20, blank=False,choices=Dimension_OF.choices)
class Machine(models.TextChoices):
MGP1="MGP1"
MGP2="MGP2 "
MGP3="MGP3"
MGP4="MGP4"
MGP5="MGP5"
MGP6="MGP6"
MGP7="MGP7"
MGP8="MGP8"
Machine=models.CharField(max_length=10,choices=Machine.choices, blank=False)
class Scenario(models.TextChoices):
Ajustage_Controle="scenario1"
Ajustage_Redressage_Controle="scenario2"
Ajustage_Formage_Controle="scenario3"
Ajustage_Redressage_Formage_Controle="scenario4"
Scenario = models.CharField(max_length=50,choices=Scenario.choices, blank=False)
Date_E_initial=models.DateTimeField(auto_now_add=True,auto_now=False)
Date_S_Final=models.DateTimeField(null=True, blank=True)
Etat_OF=models.CharField(max_length=50, null=True, blank=True)
Nb_jrs_att_Usin=models.DurationField(null=True, blank=True)
Nb_jrs_att_TM=models.DurationField(null=True, blank=True)
Nb_jrs_att_total=models.DurationField(null=True, blank=True)
def _str_(self):
return self.Scenario
class Encours(models.Model):
Id_encours=models.IntegerField(primary_key=True)
OF = models.ForeignKey(OF, on_delete=models.CASCADE )
class Nom_encours(models.TextChoices):
EN_MGP1="Encours MGP1"
EN_MGP2="Encours MGP2"
EN_MGP3="Encours MGP3"
EN_MGP4="Encours MGP4"
EN_MGP5="Encours MGP5"
EN_MGP6="Encours MGP6"
EN_MGP7="Encours MGP7"
EN_MGP8="Encours MGP8"
EN_AJU_GD="Encours Ajustage GD"
EN_AJU_MD="Encours Ajustage MD"
EN_AJU_PD="Encours Ajustage PD"
EN_RED="Encours Redressage"
EN_For="Encours Formage"
EN_Contr_GD="Encours Contrôle GD"
EN_Contr_MD="Encours Contrôle MD"
EN_Contr_PD="Encours Contrôle PD"
Nom_encours = models.CharField(max_length=30,choices=Nom_encours.choices)
Capacite = models.IntegerField(default=0)
Date_E_Encours=models.DateTimeField(null=True, blank=True)
Date_S_Encours=models.DateTimeField(null=True, blank=True)
def _str_(self):
return self.Nom_encours
But before saving data into Encours I want to define some functions to test field
for exemple ; if OF.Machine=='MGP1' then create a row in Encours model with Nom_Encours='Encours MGP1' and Date_E_Encours = Date_E_initial that automatically added.
views.py
def lancerOF(request):
form = OFLancementForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
messages.success(request, 'OF lancé avec succès', extra_tags='alert')
return redirect('lancer')
else:
messages.warning(request, 'Verifiez les données saisies')
return render(request, "lancerOF.html",{'form':form})
and i use a simple form
class OFLancementForm(forms.ModelForm):
class Meta:
model = OF
fields = {
'Numero_Of',
'Dimension_OF',
'Machine',
'Scenario'
}
widgets = { "Dimension_OF": forms.RadioSelect ,"Machine": forms.RadioSelect ,"Scenario": forms.RadioSelect}
if this is possible, where can i do test to check OF attributes and save data into my models.
PS: this is my first real project with django.
Can anyone help me please?
def lancerOF(request):
form = OFLancementForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
myobject = form.save()
# here you can do your logic
if myobject.Machine == "MPG1":
...
messages.success(request, 'OF lancé avec succès', extra_tags='alert')
return redirect('lancer')
else:
messages.warning(request, 'Verifiez les données saisies')
return render(request, "lancerOF.html",{'form':form})
Or another method is using Django's post_save signal.
Or you can override OF's save() method:
class OF(models.Model):
def save(self, *args, **kwargs):
super(OF, self).save(*args, **kwargs)
if self.Machine == "MPG1":
# your logic here.

Clearing ImageField in Django

My project has users which have a profile and can edit their profile, one of which is their profile picture. All the user information can be edited or cleared with no problem, except the profile picture. I can edit it, but I cannot clear it.
My models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=64,blank=True)
profilePic = models.ImageField(blank=True, null=True, upload_to= path_and_rename)
phoneNumber = models.CharField(max_length=12,blank=True)
streetAddress = models.CharField(max_length=64,blank=True)
My forms.py for editing the profile. I also crop the picture based on the user inputs.
class EditProfile(forms.ModelForm):
class Meta:
model = Profile
fields = ("name", "phoneNumber","streetAddress")
labels = {
'phoneNumber': _('Phone Number'),
'streetAddress': _('Street Address and/or Postal Code'),
}
class PhotoForm(forms.ModelForm):
x = forms.FloatField(widget=forms.HiddenInput())
y = forms.FloatField(widget=forms.HiddenInput())
width = forms.FloatField(widget=forms.HiddenInput())
height = forms.FloatField(widget=forms.HiddenInput())
class Meta:
model = Profile
fields = ('profilePic', 'x', 'y', 'width', 'height', )
def save(self):
photo = super(PhotoForm, self).save()
x = self.cleaned_data.get('x')
y = self.cleaned_data.get('y')
w = self.cleaned_data.get('width')
h = self.cleaned_data.get('height')
image = Image.open(photo.profilePic)
cropped_image = image.crop((x, y, w+x, h+y))
resized_image = cropped_image.resize((200, 200), Image.ANTIALIAS)
resized_image.save(photo.profilePic.path)
return photo
Finally, my views.py
def settings(request):
user= request.user
profile = Profile.objects.get(user=user)
if request.method == 'GET':
profile_form = EditProfile(instance=profile)
f1= UserProfile(user=request.user)
photo = PhotoForm(instance= profile)
return render(request, 'listings/settings.html', {'form': f1,'form2': profile_form, 'profilePic':photo})
elif request.method == 'POST':
profile_form = EditProfile(request.POST, request.FILES, instance=profile)
profile_form.save()
photo_form = PhotoForm(request.POST, request.FILES,instance=profile)
if photo_form.is_valid():
photo_form.save()
messages.success(request, 'Your profile has been updated!')
return redirect("/settings")
In my template, I click on clear image button, I even set id_profilePic to "", yet the image remains in the object.
I fixed it. The problem was whenever I try to clear, the x,y,width and height have no values. So it never enters the if statement in views.py
if photo_form.is_valid():
photo_form.save()
I fixed it by giving initial values to them

Django - How to work with multiple ModelForm's in the same form?

I've 4 models that I need to store data at once. For that I'm thinking using ModelForms.
I've tested with 2 ModelForm's at the same time but it is not working. Here is the code.
Model:
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']
Forms:
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')
View:
def submit_data_entry_view(request):
form_main = MainForm(request.POST)
form_bicyclead = BicycleAdForm(request.POST)
return render_to_response('app/submit_data_entry.html', {'form_main': form_main, 'form_bicyclead': form_bicyclead}, context_instance=RequestContext(request))
Template:
<form method="post" action="">
{{form_main}}
{{form_bicyclead}}
</form>
At the end I only get the"form_bicyclead" outputed in the browser? How can I get the two forms at once?
Best Regards,
are you using submit_data_entry_view to render forms too? shouldn't it be like -
def submit_data_entry_view(request):
if request.method == 'POST': #form submit
form_main = MainForm(request.POST)
form_bicyclead = BicycleAdForm(request.POST)
#now process and save the form
return <whatever_you_want>
elif request.method == 'GET': #first time rendering the form
form_main = MainForm()
form_bicyclead = BicycleAdForm()
return render_to_response('app/submit_data_entry.html', {'form_main': form_main, 'form_bicyclead': form_bicyclead}, context_instance=RequestContext(request))

django-selectable - trouble saving data from template

I am using django-selectable and having trouble saving the "id" ('autocomplete_1') which represents the id for the category --- from the template.
models.py
class Category(models.Model):
cat_no = models.IntegerField(null=True, blank=True)
cat_txt = models.CharField(max_length=45)
def __unicode__(self):
return self.cat_txt
class Cattest(models.Model):
category = models.ForeignKey(Category)
info = models.CharField(max_length=35, blank=True)
lookups.py
class CategoryLookup(ModelLookup):
model = Category
search_fields = ('cat_txt__icontains', )
forms.py
class CategoryForm(forms.Form):
autocomplete = forms.CharField(
label='Type the name of a category (AutoCompleteWidget)',
widget=selectable.AutoCompleteWidget(CategoryLookup),
required=False,
)
autocompleteselect = selectable.AutoCompleteSelectField(
lookup_class=CategoryLookup,
label='Select a category (AutoCompleteField)',
required=False,
)
class CattestForm(forms.Form):
#model = cattest
#fields = ('category', 'info')
autocomplete = forms.CharField(
label='Type the name of a category (AutoCompleteSelectWidget)',
widget=selectable.AutoCompleteSelectWidget(CategoryLookup),
required=False,
)
info = forms.CharField(max_length=35, label="Information")
views.py
def cattest(request):
if request.method == 'POST':
form = CattestForm(request.POST)
if form.is_valid():
cattest = Cattest.objects.create(
category=form.cleaned_data['autocomplete_1'],
info=form.cleaned_data['info'],
)
# Always redirect after a POST
return http.HttpResponseRedirect('/bsmain/login_customer')
else:
if request.GET:
form = CattestForm(initial=request.GET)
else:
form = CattestForm()
return render_to_response('bsmain/form.html', {'form': form}, context_instance=RequestContext(request))
Traceback:
KeyError at /bsmain/cattest/
'autocomplete_1'
Request Method: POST
Request URL: http://127.0.0.1:8000/bsmain/cattest/
Django Version: 1.3.1
Exception Type: KeyError
Exception Value:
'autocomplete_1'
Exception Location: /home/bill/workspace/boatsite/../boatsite/bsmain/views.py in cattest, line 64
Python Executable: /usr/bin/python
Python Version: 2.6.5
Request information
GET No GET data
POST Variable Value
info u'44# Bruce'
csrfmiddlewaretoken u'9ffe49bd68be04087521e71e86a5bec0'
autocomplete_1 u'10'
autocomplete_0 u'Anchors'
The form cleaned_data dictionary is populated based on the field names. You should access the data from form.cleaned_data['autocomplete'].
Edit:
This would probably be easier by using a ModelForm:
class CattestForm(forms.ModelForm):
class Meta:
model = Cattest
fields = ('category', 'info', )
widgets = {
'category': selectable.AutoCompleteSelectWidget(CategoryLookup)
}
def cattest(request):
if request.method == 'POST':
form = CattestForm(request.POST)
if form.is_valid():
cattest = form.save()
# Always redirect after a POST
return http.HttpResponseRedirect('/bsmain/login_customer')
else:
initial = request.GET or None
form = CattestForm(initial=initial)
return render_to_response('bsmain/form.html', {'form': form}, context_instance=RequestContext(request))

Categories