ImageField() not saving images in ModelForm - Django/Python - python

When I try to upload a picture from my form, everything processes, but the image is not being saved.
Does anyone know why this is happening?
Thanks ahead of time!
models.py:
class Photo(models.Model):
user = models.ForeignKey(MyUser, null=False, blank=False)
category = models.ForeignKey("Category", default=1, null=True, blank=True)
title = models.CharField(max_length=30, null=True, blank=True)
description = models.TextField(max_length=120, null=True, blank=True)
image = models.ImageField(upload_to='user/photos/', null=True, blank=True)
slug = models.SlugField(null=True, blank=True)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False, null=True)
updated = models.DateTimeField(auto_now_add=False, auto_now=True, null=True)
class Meta:
unique_together = ('slug', 'category')
ordering = ['-timestamp']
def __unicode__(self):
return "%s" %(self.user)
views.py:
def photo_upload_view(request, username):
u = MyUser.objects.get(username=username)
if request.method == 'POST':
form = PhotoUploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request, "Thank you! You have successfully posted your picture!")
return HttpResponseRedirect('/')
else:
form = PhotoUploadForm()
submit_btn = "Upload Post"
context = {
"form": form,
"submit_btn": submit_btn
}
return render(request, "photos/photo_upload.html", context)
forms.py:
class PhotoUploadForm(forms.ModelForm):
class Meta:
model = Photo
fields = ('user', 'category', 'title', 'description', 'image')
.html:
<form method='POST' action='{{ action_url }}'>{% csrf_token %}
{{ form|crispy }}
<input class='btn btn-default {{ submit_btn_class }}' type='submit' value='{{ submit_btn }}'/>
</form>

You should add the enctype=multipart/form-data attribute to the <form> tag:
<form method='POST' action='{{ action_url }}' enctype='multipart/form-data'>

except for adding enctype=multipart/form-data, another possible reason that your image is not saving in modelform can be adding request.FILES in your POST condition:
if request.method == 'POST':
form = forms.ProjectCreateForm(request.POST, instance=project)
should be:
if request.method == 'POST':
form = forms.ProjectCreateForm(request.POST, request.FILES, instance=project)

data.profile_pic = request.FILES['profile_pic']
use request.FILES

Related

How to save foreign key data using forms.py?

urls.py
...
path('restaurant/menu/', r_view.Menu, name='menu'),
...
menu.html
<form method="POST" id="menuForm" autocomplete="off" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-inline">
<div class="form-group mb-4">
{{ form.item|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.itemImage|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.price|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.category|as_crispy_field }}
</div>
</div>
<button type="submit" class="col-md-12 myBtn">Submit</button>
</form>
views.py
def Menu(request, restaurantID):
restaurant = get_object_or_404(Restaurant_Account, restaurantID=restaurantID)
form = MenuForm()
if request.method == 'POST':
form = MenuForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.restaurant = restaurant
instance.save()
messages.success(request, "Saved successfully!")
return redirect('r_index')
context = {'form':form}
return render(request, 'restaurant/menu.html', context)
forms.py
class MenuForm(forms.ModelForm):
restaurantID = Restaurant_Account.objects.filter(restaurantID='restaurantID')
item = forms.CharField(required=True)
itemImage = forms.ImageField(required=False, label='Item image')
price = forms.DecimalField(required=True)
category = forms.ChoiceField(choices=CATEGORY)
class Meta:
model = Menu
fields = ('item', 'itemImage', 'price', 'category')
models.py
class Restaurant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_restaurant = models.BooleanField(default=True)
restaurantID = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
isActive = models.BooleanField(default=True)
image = models.ImageField(upload_to='images/', blank=True)
website = models.URLField(blank=True, unique=False)
country = models.CharField(max_length=50)
def __str__(self):
return self.user.username
class Menu(models.Model):
menuID = models.AutoField(primary_key=True)
restaurantID = models.ForeignKey(Restaurant_Account, on_delete=models.CASCADE, default=None)
item = models.CharField(max_length=100)
itemImage = models.ImageField(upload_to='images/', blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
category = models.CharField(
max_length=20,
choices=[('', 'Choose category'),('Appetizer', 'Appetizer'),('Entree', 'Entree'),('Drink', 'Drink'),('Dessert', 'Dessert'), ('Side', 'Side')])
def __str__(self):
return self.item
I'm new to Django.
I made a form for saving menu data. If the user fills the form and click the submit button every data should be saved in the Menu table. I have no idea how to save restaurantID, which is a foreign key that refers to the Restaurant table, automatically. (By automatically I mean without the user entering input) Can somebody help me with this?
You haven't need to do all these things, if you have made restaurantID a foreign key while defining the model that is Menu, django itself handles it.
Below code might work for you:
forms.py
class MenuForm(forms.ModelForm):
item = forms.CharField(required=True)
itemImage = forms.ImageField(required=False, label='Item image')
price = forms.DecimalField(required=True)
category = forms.ChoiceField(choices=CATEGORY)
class Meta:
model = Menu
fields = ('item', 'itemImage', 'price', 'category')
views.py
def menu(request):
if request.method == 'POST':
form = MenuForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request, "Saved successfully!")
return redirect('r_index')
else:
form=MenuForm()
return render(request, 'restaurant/menu.html', {'form':form})
optional: You also don't need to write this line menuID = models.AutoField(primary_key=True) in Menu model, as django makes id column by default for AutoField.
Update:
Make your models.py in this way:
MY_CHOICES=[
('', 'Choose category'),
('Appetizer', 'Appetizer'),
('Entree', 'Entree'),
('Drink', 'Drink'),
('Dessert', 'Dessert'),
('Side', 'Side')
]
class Restaurant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_restaurant = models.BooleanField(default=True)
name = models.CharField(max_length=200)
isActive = models.BooleanField(default=True)
image = models.ImageField(upload_to='images/', blank=True)
website = models.URLField(blank=True, unique=False)
country = models.CharField(max_length=50)
def __str__(self):
return self.user.username
class Menu(models.Model):
restaurant= models.ForeignKey(Restaurant, on_delete=models.CASCADE, default=None)
item = models.CharField(max_length=100)
itemImage = models.ImageField(upload_to='images/', blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
category = models.CharField(
max_length=20,
choices=MY_CHOICES)
def __str__(self):
return self.item
Remove your AutoField, django by default make id which is primary key.
Don't forget to run makemigrations and migrate, after doing this, if it still gives error, so comment your all models and then run.

Form is not saving in database when submitted

I am working on a project on Django, where user can input values on form and submit using POST request. When form is submitted, datas are not saved in database. How do I implement save data when form is submitted.
Models:
class DataInfo(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
beneficiary_name = models.CharField(max_length=250, blank=True)
beneficiary_bank_name = models.CharField(max_length=250, blank=True)
beneficiary_account_no = models.CharField(max_length=250, blank=True)
beneficiary_iban = models.CharField(max_length=250, blank=True)
beneficiary_routing_no = models.CharField(max_length=250, blank=True)
amount = models.IntegerField(blank=True)
date = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'DataInfo'
verbose_name_plural = 'DataInfo'
ordering = ['-date']
'''Method to filter database results'''
def __str__(self):
return self.user.username
Views:
#login_required
def TransferView(request):
form = DataForm(request.POST)
if request.method == "POST":
if form.is_valid():
pp = form.save(commit=False)
pp.user = request.user
pp.save()
return redirect('site:transfer_cot')
else:
form = DataForm()
context = {
'form':form
}
return render(request, 'transfer.html', context)
Forms:
class DataForm(forms.ModelForm):
class Meta:
model = DataInfo
fields = ('beneficiary_name', 'beneficiary_bank_name', 'beneficiary_account_no', 'beneficiary_iban', 'beneficiary_routing_no', 'amount')
Template:
<form method="POST" action="{% url 'site:transfer_cot' %}">
{% csrf_token %}
{{ form }}
<button type="submit" class="btn btn-secondary">Submit</button>
</form>

Drop down field shows values of all users

I have a form field in Django called Label. My problem is that the field shows the Labels of all users while I only want to show self created labels.
models
class Label(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
tag = models.CharField(max_length=25)
def __str__(self):
return self.tag
class Birthday(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=25, default="")
day = models.DateField()
label = models.ForeignKey(Label, on_delete=models.SET_NULL, default=0, null=True, blank=True)
def __str__(self):
return self.name
forms
class BirthdayForm(forms.ModelForm):
class Meta:
model = Birthday
fields = ('name', 'day', 'label')
class LabelForm(forms.ModelForm):
class Meta:
model = Label
fields = ('tag',)
template
<form method="POST">{% csrf_token %}
<table border="0">
{{ form }}
</table>
<button class="submitButton" type="submit">Submit</button>
</form>
This is the view for this template
view
#login_required
def index(request):
if request.method == "POST":
form = BirthdayForm(request.POST)
if form.is_valid():
birthday = form.save(commit=False)
birthday.user = request.user
birthday.save()
return redirect('index')
else:
#default_labels("Friend", request)
#default_labels("Family", request)
form = BirthdayForm()
birthday = Birthday.objects.filter(user=request.user)
username = request.user
return render(request, 'bd_calendar/index.html', {'form': form, 'birthday': birthday, 'username': username })

Update form input with django form value

I am trying to pass legacy db entries to django form.
I created the model by using django inspectdb method.
Similar to:
class Form(models.Model):
date_entered = models.DateField(blank=True, null=True)
date_needed = models.DateField(blank=True, null=True)
client = models.CharField(max_length=50, blank=True, null=True)
project_no = models.CharField(max_length=50, blank=True, null=True)
map_no = models.CharField(max_length=10, blank=True, null=True)
contact = models.CharField(max_length=50, blank=True, null=True)
I have create the corresponding view in views.py.
def post_edit(request, pk):
post = get_object_or_404(Form, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
In my post_edit.html.
<input type="text" class="form-control" name="client" value= '{{ form.client.value }}' required/>
<input type="text" name="projectno" class="form-control" value= '{{ form.project_no.value }}' required/>
..
<input type="text" name="jobcontact" class="form-control" value='{{ form.contact.value }}' required/>
Client and project_no work (produce values on the form) while contact does not. I have verified the name in model and also the existance of a value for this in the db table.
Should I pass something else for these input values. I am new to django. Help please.
EDIT: Adding class PostForm(). As identified in the accepted answer only 2 fields had been added to class PostForm(). After adding the remainig classes the form populated the values.
class PostForm(forms.ModelForm):
class Meta:
model = Form
fields = ('project_no', 'client',)

Additional help text to form in Django

When I create or edit model CV, I need to input some data in birth_date field. It's working, but I want to add some additional text to define some date format like (yyyy-mm-dd). I'm using cripsy forms for better look of forms. How can I add this help text ?
my code:
template.html
{% block profile %}
<div class="jumbotron">
<h2>Edit your basic informations</h2>
<hr>
<form method="POST" class="post-form" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</div>
{% endblock %}
models.py
class Cv(models.Model):
author = models.ForeignKey('auth.User')
name = models.CharField(max_length=25, null = True)
surname = models.CharField(max_length=25, null = True)
city = models.CharField(max_length=100, blank=True)
birth_date = models.DateField(blank=True, null=True)
email = models.EmailField(max_length=50, null=True)
main_programming_language = models.CharField(max_length=15, null = True)
specialization = models.CharField(max_length=30, blank=True, null=True)
interests = models.TextField(blank=True, null=True)
summary = models.TextField(blank=True, null=True)
#thumbnail = models.FileField(upload_to=get_upload_file_name, blank=True)
#property
def age(self):
return int((datetime.datetime.now().date() - self.birth_date).days / 365.25 )
def zapisz(self):
self.save()
def __str__(self):
return self.surname.encode('utf-8')
forms.py
class CvForm(forms.ModelForm):
class Meta:
model = Cv
fields = ('name', 'surname', 'city', 'birth_date', 'email', 'main_programming_language', 'specialization', 'interests', 'summary',)
views.py
#login_required
def new_cv(request):
if request.method == "POST":
form = CvForm(request.POST, request.FILES)
if form.is_valid():
cv = form.save(commit=False)
cv.author = request.user
cv.save()
return redirect('proj.views.cv_detail', pk=cv.pk)
else:
form = CvForm()
return render(request, 'new_cv.html', {'form': form})
Can add help_text to your model fields:
birth_date = models.DateField(blank=True, null=True, help_text="format (yyyy-mm-dd)")
see more Django Model and Form docs.
You can also use external library JQuery Tooltip too.

Categories