When I enter info into my formset, the images gets erased and I'm not able to advance to the next page. No errors appear on the page. Essentially, the form data isn't passing "is_valid". I'm pretty certain that there is something wrong in my view.py.
Models.py
class Testimonial(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
image = VersatileImageField('image_testimonial', upload_to=upload_location, validators=[file_size], null=True, blank=True)
message = models.CharField(max_length=300, default='', null=True, blank=True)
name = models.CharField(max_length=100, default='', null=True, blank=True)
city = models.CharField(max_length=100, default='', null=True, blank=True)
state = models.CharField(max_length=100, default='', null=True, blank=True)
def __str__(self):
return self.author.username
forms.py
class TestimonialForm (forms.ModelForm):
class Meta:
model = Testimonial
fields = ('image', 'message', 'name', 'city', 'state',)
views.py
#login_required(login_url="/accounts/login/")
def testimonials(request):
TestimonialFormSet = modelformset_factory(Testimonial, form=TestimonialForm, extra=3)
if request.method == 'POST':
formset = TestimonialFormSet(request.POST or None, request.FILES or None)
if formset.is_valid():
instances = formset.save(commit=False)
for instance in instances: #for instance in instances.cleaned_data:
instance.author = request.user
fix_orientation(instance.image)
instance.save()
return redirect('/accounts/profile/')
else:
args = {'formset': formset}
return render(request, 'accounts/page6.html', args)
else:
formset = TestimonialFormSet(queryset=Testimonial.objects.filter(author=request.user))
return render(request, 'accounts/page6.html', {'formset': formset})
I had to
a) include {{formset.errors}} in my template to render the error that was preventing submission
b) include {{ form.id }} in the template even though id isn't part of my model. This seems to be an odd quirk of formset, but alas, I can now submit the form.
Shoutout to Daniel Roseman for helping me find the answer!
Related
i want to save an object to db and it worked one time but now it doesnt, i suspect that is something to do with the Glossary
Everything
views.py
#login_required
def product_form_view(request):
if request.method == 'POST':
form = Product_Form(request.POST, request.FILES)
if form.is_valid():
product_form = form.save()
product_form.save()
return redirect('product_management_view')
else:
form = Product_Form()
return render(request, 'product-form.html', {'form': form})
models.py
class Product (models.Model):
sub_chapter = models.ForeignKey(Sub_Chapter, on_delete=models.CASCADE)
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
glossary = models.ManyToManyField(Glossary, blank=True )
name = models.CharField(max_length=40, blank=False, null=False)
description = models.TextField(null=True)
product_image = models.ImageField(
upload_to='media/images/product_images', blank=False, null=False)
reference = models.CharField(max_length=40, blank=False, null=False)
width = models.PositiveIntegerField()
height = models.PositiveIntegerField()
length = models.PositiveIntegerField()
unit_price = models.DecimalField(
max_digits=15, decimal_places=4, null=True)
polution = models.DecimalField(decimal_places=8, max_digits=15, null=True, blank=True )
technical_implementation = models.TextField(null=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse_lazy("manufacter_product_view", kwargs={'id': self.pk})
forms.py
class Product_Form(forms.ModelForm):
sub_chapter = forms.ModelChoiceField(queryset=Sub_Chapter.objects.all(),
required=True, widget=forms.Select())
supplier = forms.ModelChoiceField(queryset=Supplier.objects.all(),
required=True, widget=forms.Select())
glossary = forms.ModelChoiceField(queryset=Glossary.objects.all(),
required=False, widget=forms.SelectMultiple())
product_image = forms.ImageField(
required=True, widget=forms.FileInput())
class Meta():
model = Product
fields =[ 'name', 'description', 'reference', 'width', 'height', 'length', 'polution', 'unit_price', 'technical_implementation', 'sub_chapter', 'supplier', 'glossary', 'product_image', ]
There is a bug in your product_form_view, you are calling the save method on product_form variable i.e product_form.save() but product_form will have None in it as form.save() will return None on successfully saving the object,so it will break the code there.And you don't need to again call the save method at all.Calling form.save() is enough for saving the object and you should move the code in else part out of it as it not currently handling the form invalid case.
Your code should be like this:
#login_required
def product_form_view(request):
if request.method == 'POST':
form = Product_Form(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('product_management_view')
form = Product_Form()
return render(request, 'product-form.html', {'form': form})
I have two models: Properties and Bedroom, which are connected through a foreign key "Property" on the Bedroom model.
#models.py
class Property(models.Model):
property_reference = models.CharField(db_column='Property_Reference', max_length=10, unique=True) # Field name made lowercase.
address = models.CharField(db_column='Address', max_length=250, blank=True, null=True) # Field name made lowercase.
post_code = models.CharField(db_column='Post_Code', max_length=15, blank=True, null=True) # Field name made lowercase.
type = models.CharField(db_column='Type', max_length=25, blank=True, null=True, choices=HOUSE_TYPE_CHOICES) # Field name made lowercase.
bedrooms = models.IntegerField(db_column='Bedrooms', blank=True, null=True) # Field name made lowercase.
bathrooms = models.IntegerField(db_column='Bathrooms', blank=True, null=True) # Field name made lowercase.
usual_cleaning_requirements = models.CharField(db_column='Usual_Cleaning_Requirements', max_length=250, blank=True, null=True) # Field name made lowercase.
notes = models.CharField(db_column='Notes', max_length=500, blank=True, null=True) # Field name made lowercase.
feature_image = models.ImageField(upload_to='properties',null=True)
class Meta:
db_table = 'Property'
def __str__(self):
return self.property_reference
def get_absolute_url(self):
return reverse("properties:property_detail",kwargs={'pk':self.pk})
class Bedroom(models.Model):
type = models.CharField(db_column='Type', choices=BEDROOM_TYPE_CHOICES, max_length=50)
bed_dimensions = models.CharField(db_column='Bed_Dimension', choices=BED_DIMENSION_CHOICES, max_length=30)
image = models.ImageField(null=True, blank=True)
ensuite = models.BooleanField(default=False)
notes = models.CharField(db_column='Notes', max_length=500, blank=True, null=True) # Field name made lowercase.
property = models.ForeignKey(Property, null=False, on_delete=models.CASCADE, related_name='bedroom')
I have a Property DetailView Class that shows all the details on my template at "property-detail.html". Also on my template I have a button like this:
<a class="btn btn-secondary float-right" href="{% url 'properties:add_bedroom' pk=object.pk %}"><i class="fas fa-plus-circle"></i> Add New</a>
This button takes me to the right place, to the form AddBedroom with this link:
http://127.0.0.1:8000/properties/1/bedrooms/add-bedroom/
My urls.py look like this:
url(r'^(?P<pk>\d+)$',views.PropertyDetailView.as_view(),name='property_detail'),
url(r'^(?P<pk>\d+)/edit$',views.PropertyUpdateView.as_view(),name='property_edit'),
url(r'^(?P<pk>\d+)/bedrooms/add-bedroom/',views.add_bedroom,name='add_bedroom'),
You can see here how I render the form:
#views.py
def add_bedroom(request, pk):
print(pk)
if request.method == 'POST':
form = AddBedroomForm(request.POST, request.FILES)
if form.is_valid():
add_bedroom = form.save()
add_bedroom.instance.property = Property.objects.get(pk = pk)
print('Sucesso')
add_bedroom.save()
return HttpResponseRedirect('/thanks/')
else:
print('Error')
form = AddBedroomForm()
context = {
'add_bedroom_form':form,
'title':"Add Bedroom",
}
return render(request, 'properties/add-bedroom.html', context)
I can get the "PK" printed, I also get the POST on console but it just refreshes the page and does not actually POSTS anything. I'm sure I'm doing something wrong because I'm fairly new to Django.
I've came up with a solution, I don't know if it's the best practice but it's working fine.
I've changed the views.py to this:
#views.py
def add_bedroom(request, pk):
get_property_id = pk
data = {'property':get_property_id}
property_reference = Property.objects.get(pk=get_property_id)
print(property_reference)
if request.method == 'POST':
form = AddBedroomForm(request.POST, request.FILES, initial=data)
print(get_property_id)
if form.is_valid():
add_bedroom = form.save()
add_bedroom.save()
return HttpResponseRedirect('/thanks/')
else:
print('Error')
form = AddBedroomForm(initial=data)
context = {
'add_bedroom_form':form,
'title':"Add Bedroom",
'reference':property_reference,
}
return render(request, 'properties/add-bedroom.html', context)
Let's get to the problem
I have a page where I want users to fill info about themselves, and i would like to save that data. But I'm getting this error.
IntegrityError at /accounts/profile/edit/1/change-profile/
UNIQUE constraint failed: accounts_user.username
this is my view.py
def change_profile(request, pk):
form = ChangeProfile(request.POST or None)
user_ = request.user
if request.method == "POST":
if form.is_valid():
form.save()
return redirect("/accounts/profile/edit/{}/".format(user_.pk))
args = {'form': form}
return render(request, 'change_profile.html', args)
my models.py
class GradeUser(models.Model):
grade = models.CharField(max_length=20, null=True)
class Country(models.Model):
country = models.CharField(max_length=30, null=True)
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name = 'email address',
max_length=255,
unique=True
)
real_name = models.CharField(max_length=20, blank=True)
username = models.CharField(max_length=40, unique=True, verbose_name='username')
grade = models.ForeignKey(GradeUser, on_delete=models.CASCADE, blank=True, null=True)
country = models.ForeignKey(Country, on_delete=models.CASCADE, blank=True, null=True)
reputation = models.IntegerField(default=0)
image = models.ImageField(upload_to='accounts/media', blank=True)
about_me = models.TextField()
USERNAME_FIELD= 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
forms.py
class ChangeProfile(forms.ModelForm):
class Meta:
model = User
fields = ('real_name', 'grade', 'country', 'about_me')
What does exactly go wrong?
Why would it need a user's username?
What should I do with it to save?
You aim to perform an update on your User (that already exists) but here you are creating a whole new user instance with no username attribute and that's what generates the error.
Try this code : it gets your current user and updates it with the info provided from the form.
PS : I did not modify anything about the returns because I dunno what you're doing there but note that you don't need to pass the user pk through the arguments, the user data is already stored in the request object.
def change_profile(request, pk):
form = ChangeProfile()
user_ = request.user
if request.method == "POST":
form = ChangeProfile(request.POST)
if form.is_valid():
user_new_info=form.save(commit=false)
user_.real_name = user_new_info.real_name
user_.grade = user_new_info.grade
user_.country = user_new_info.country
user_.about_me = user_new_info.about_me
user_.save()
return redirect("/accounts/profile/edit/{}/".format(user_.pk))
args = {'form': form}
return render(request, 'change_profile.html', args)
I have a form and a formset. Formset contains a column foreign key to form. However my forms are not saving and save() prohibited to prevent data loss due to unsaved related object error is being thrown. How could I save both these data together?
here's my view:
def purchaseOrderView(request):
if request.method == 'POST':
formset = POFormSet(request.POST)
form = POHeaderForm(request.POST)
print("POSTED")
if form.is_valid() and formset.is_valid():
form.save()
formset.save()
messages.success(request,"VALID SUBMISSION")
return render(request,'purchase_order.html',{'formset':formset, 'form':form})
else:
return render(request, 'purchase_order.html', {'formset': formset, 'form': form})
else:
formset = POFormSet()
form = POHeaderForm()
return render(request,'purchase_order.html',{'formset':formset, 'form':form})
here's my model structure:
class POHeaderModel(models.Model):
date = models.DateTimeField(blank=False, default=timezone.now)
reference = models.CharField(validators=[alphanumeric], max_length=25, blank=True, null=True)
supplier = models.ForeignKey(SuppliersModel, on_delete=models.PROTECT)
note = models.CharField(validators=[alphanumeric], max_length=300, blank=True, null=True)
total = models.DecimalField(decimal_places=2, max_digits=10, validators=[MinValueValidator(0)])
class POBodyModel(models.Model):
PO = models.ForeignKey(POHeaderModel, on_delete=models.PROTECT)
item_number = models.CharField(validators=[alphanumeric], max_length=25, blank=True, null=True)
description = models.CharField(validators=[alphanumeric], max_length=100, blank=True, null=True)
quantity = models.IntegerField(blank=True, null=True)
rate = models.DecimalField(decimal_places=2, max_digits=10)
discount = models.DecimalField(decimal_places=2, max_digits=10,blank=True, null=True)
total = models.DecimalField(decimal_places=2, max_digits=10, blank=False)
There are a lot of examples out there in various blogs and in here in questions using with transaction.atomic():. But none works or may be doesn't suit my scenario. Any advise?
You need to pass to formset the parent object, like this:
formset = POFormSet(request.POST,instance=POHeaderinstance)
this me again. I have some trouble with my code. I made a form from ModelForm which have a model with 8 attributes, but i want to user fill only one of them,and one from the system. The one that user fill is okay, but the one filled with system is not working.
models.py
class SeminarProposal(md.Model):
# diisi oleh mahasiswa
fileProposal = models.FileField()
# This is the one is filled with system
proposal = models.OneToOneField(Proposal,
on_delete=models.CASCADE,
related_name="propSid",
unique=True, blank=True, null=True)
masabimbingan = models.BooleanField(default=True)
# disi oleh admin
tanggal = models.DateField(default=timezone.now, blank=True,null=True)
tempat = models.CharField(max_length=30, blank=True, null=True)
# diisi oleh dosen pembimbing
dospemsetuju = models.BooleanField(default=False, blank=True)
# diisi oleh kaprodi
penguji1 = models.ForeignKey(Dosen,
on_delete=models.CASCADE,
related_name="penguji1",
blank=True, null=True)
penguji2 = models.ForeignKey(Dosen,
on_delete=models.CASCADE,
related_name="penguji2",
blank=True, null=True)
def __str__(self):
return "Sidang untuk " + self.proposal.judul
view.py
def daftarSeminar(request):
if request.method == 'POST':
form = FormSeminar(request.POST, request.FILES)
print(request.user)
if form.is_valid():
form.save(commit=False)
form.cleaned_data['proposal']
print(request.user)
prop = Proposal.objects.get(akun=request.user)
form.proposal = prop
print(form.proposal) #to confirm that this is not None
form.save()
return redirect('proposal:bimbingan')
else:
return render(request, 'sidprop.html' , {'oke': 'oke'})
return redirect('proposal:index')
form.py
class FormSeminar(forms.ModelForm):
class Meta:
model = SeminarProposal
fields = ['fileProposal','proposal']
Thanks in advance. Terimakasih.
Instead of changing the form data, get the object from form and change the object's data:
if form.is_valid():
obj = form.save(commit=False)
prop = Proposal.objects.get(akun=request.user)
obj.proposal = prop
obj.save()
return redirect('proposal:bimbingan')