provide the same instance of one form to the other - python

Updated
i have two tables(models) one for product name and features and the other for prices
i normalized to database tables
like this
class Model(models.Model):
name = models.CharField(max_length=23)
def __str__(self):
return self.name
class Feature(models.Model):
model = models.ForeignKey(Model,on_delete=models.CASCADE)
price = models.IntegerField()
company = models.CharField(max_length=33)
def __str__(self):
return self.model
my views.py
def create(request):
createmodel = ModelForms(prefix='createmodel')
createfeature = FeatureForm(prefix='createfeature')
if request.method == 'POST':
createmodel = ModelForms(request.POST,prefix='createmodel')
if createmodel.is_valid():
createmodel.save()
name = createmodel.cleaned_data['name']
if createfeature.is_valid():
createfeature = FeatureForm(request.POST,prefix='createfeature',model=name)
createfeature.save()
return redirect('/lists/')
return render(request,'forms/create.html',{'createmodel':createmodel,'createfeature':createfeature})
my forms.py
class ModelForms(forms.ModelForm):
class Meta:
model = Model
fields = [
'name'
]
class FeatureForm(forms.ModelForm):
read_only = ['model']
class Meta:
model = Feature
fields = [
'price','company'
]
but the form wont saved
how to submit both forms at the same time with providing the exact foreign key (as filled in ModelForm to FeatureForm)in one go
i know how to do it in updating two forms , but how to create submit two forms with providing the instance directly
much respect

Doing it is simple, since you did not provide views.py and .html I had to give you my example.
views.py
def (request):
if request.method == 'POST':
# PROCESS POST METHOD FORM
user_form = UserEditForm(instance=request.user, data=request.POST)
profile_form = ProfileEditForm(instance=request.user.profile_user, data=request.POST, files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
else:
# HERE WE ADD TWO FORMS IN CONTEXT
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile_user)
return render(request, 'accounts/edit.html', {'user_form': user_form, 'profile_form': profile_form})
edit.html
<!-- Above Code -->
<form action="." method="post" enctype="multipart/form-data">
{{ user_form.as_p }}
{{ profile_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Save changes"></p>
</form>
<!-- Below Code -->
You can make two separate forms for two models.
Its better to use form prefix in such cases, in my case it will become:
def (request):
if request.method == 'POST':
# PROCESS POST METHOD FORM
user_form = UserEditForm(request.POST, prefix="user_form")
profile_form = ProfileEditForm(request.POST, prefix="profile_form", files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
else:
# HERE WE ADD TWO FORMS IN CONTEXT
user_form = UserEditForm(prefix="user_form")
profile_form = ProfileEditForm(prefix="profile_form")
return render(request, 'accounts/edit.html', {'user_form': user_form, 'profile_form': profile_form})

Related

Django - 'This field is required on form' load

I have a Django view that shows two create forms.
Whenever the page loads all of the input fields display - 'This field is required".
enter image description here
Template code
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ listing_create_form.as_p }}
{{ listing_media_form.as_p }}
<button type="submit">Submit Form</button>
</form>
{% endblock %}
views.py
#login_required
def createListing(request):
listing_create_form = ListingCreateForm(request.POST or None, request.FILES)
listing_media_form = ListingMediaForm(request.POST or None, request.FILES)
if request.method == 'POST':
if listing_create_form.is_valid() and listing_media_form.is_valid():
listing_create_form.instance.created_by = request.user
form = listing_create_form.save()
form.save()
new_listing_id = form.pk
# loop over images to upload multiple
for image_uploaded in request.FILES.getlist('image'):
image_instance = ListingMedia.objects.create(listing=form, image=image_uploaded)
image_instance.save()
return redirect('boat_listings')
context = {'listing_create_form': listing_create_form, 'listing_media_form': listing_media_form}
return render(request, 'listings/listing_create_form.html', context)
forms.py
class ListingCreateForm(forms.ModelForm):
class Meta:
model = Listings
widgets = {
"featured_image": forms.FileInput(
attrs={
"enctype": "multipart/form-data"
}
),
}
fields = "__all__"
exclude = ("created_by", "created_on", "last_modified",)
class ListingMediaForm(forms.ModelForm):
class Meta:
# image = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
widgets = {
"image": forms.ClearableFileInput(
attrs={
"multiple": True
}
),
}
model = ListingMedia
fields = ['image']
Django template should render without field required message before user has inputted invalid inputs.
it looks like when you initialise form instances, it gets data and tries to validate so that's what you are receiving error messages.
change your view:
#login_required
def createListing(request):
if request.method == 'POST':
listing_create_form = ListingCreateForm(request.POST, request.FILES)
listing_media_form = ListingMediaForm(request.POST, request.FILES)
if listing_create_form.is_valid() and listing_media_form.is_valid():
listing_create_form.instance.created_by = request.user
form = listing_create_form.save()
form.save()
new_listing_id = form.pk
# loop over images to upload multiple
for image_uploaded in request.FILES.getlist('image'):
image_instance = ListingMedia.objects.create(listing=form, image=image_uploaded)
image_instance.save()
return redirect('boat_listings')
else:
listing_create_form = ListingCreateForm()
listing_media_form = ListingMediaForm()
context = {'listing_create_form': listing_create_form, 'listing_media_form': listing_media_form}
return render(request, 'listings/listing_create_form.html', context)

How to pre-populate form with data received from a previous HTML form submission in Django?

I'm trying to populate my ModelForm with some of data that I have submitted to previous HTML page which is also ModelForm.
I just want to pass it to another form so it doesn't have to be written twice.
I've tried couple solutions from stackoverflow but they are 6+ years old, kinda outdated and also couldnt come up with solution from django docs https://docs.djangoproject.com/en/2.2/topics/forms/
I have two models, which have same fields which are name and boxid
I need to pass it from first input to second(to populate it).
forms.py
class NewCashierForm(forms.ModelForm):
class Meta:
model = Cashier
fields = ("cashier_company", "cashier_dealer", "cashier_name", "cashier_boxid", "cashier_type", "cashier_package", "cashier_otheritem", "cashier_otheritemserial", "cashier_length", "cashier_promotion", "cashier_amount", "cashier_paymenttype")
labels = {"cashier_company":('Firma'), "cashier_dealer": ('Diler'), "cashier_name":('Ime i prezime'), "cashier_boxid":('Box ID'), "cashier_type":('Tip'), "cashier_package":('Paket'), "cashier_otheritem":('Drugi uredjaj'), "cashier_otheritemserial":('SBU'), "cashier_length":('Dužina'), "cashier_promotion":('Promocija'), "cashier_amount":('Iznos'), "cashier_paymenttype":('Nacin uplate')}
exclude = ['cashier_published']
def save(self, commit=True):
cashier = super(NewCashierForm, self).save(commit=False)
if commit:
cashier.save()
return cashier
class NewPersonForm(forms.ModelForm):
class Meta:
model = Person
fields = {"person_name", "person_adress", "person_phone", "person_boxid"}
labels = {"person_name":('Ime i prezime'), "person_adress":('Adresa'), "person_phone":('Telefon'), "person_boxid":('Box ID')}
def save(self, commit=True):
person = super(NewPersonForm, self).save(commit=False)
if commit:
person.save()
return person
views.py
def addcashier(request):
if request.method == 'GET':
form = NewCashierForm()
else:
form = NewCashierForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
return redirect('/byauthor')
return render (request, 'main/addcashier.html', {'form':form})
def addperson(request):
if request.method == 'GET':
form = NewPersonForm()
else:
form = NewPersonForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
return redirect('/addcashier')
return render (request, 'main/addperson.html', {'form':form})
addperson.html and addcashier.html
{% extends "main/base.html" %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button class="btn" type="submit">Unos i dodavanje pretplate</button>
</form>
<input type="button" value="Otkazi unos" onclick="window.history.back()" />
{% endblock %}
Any help and/or hint is appreciated.
To prepopulate the form, you need to pass an argument initial={} when initializing your form for the GET call. Since you are passing data from one view to another, you should use sessions.
def addperson(request):
if request.method == 'GET':
form = NewPersonForm()
else:
form = NewPersonForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
request.session["person_form"] = request.POST.dict() #save the form as a dict in request.sessions
return redirect('/addcashier')
return render (request, 'main/addperson.html', {'form':form})
Then in your second view, use this data from sessions to initialize the form.
def addcashier(request):
if request.method == 'GET':
# get the form data from the request.session
form_data = request.session.pop('person_form', {})
box_id = form_data.get("person_boxid")
name = form_data.get("person_name")
form = NewCashierForm(initial={"cashier_name":name, "cashier_boxid":box_id}) # initialize the form with the data
else:
form = NewCashierForm(request.POST)
if form.is_valid():
fs = form.save(commit=False)
fs.user = request.user
fs.save()
return redirect('/byauthor')
return render (request, 'main/addcashier.html', {'form':form})

Passing query string to ModelForm hidden field - Django

I want to pass a query string e.g., ?refcode='A1234' to a hidden field called inbound_referral_code in a ModelForm.
My model is as follows:
class User(models.Model):
email = models.EmailField(max_length=255, blank=False, unique=True)
inbound_referral_code = models.CharField(max_length=255)
My ModelForm is currently as follows:
class UserForm(forms.ModelForm):
model = User
fields = ['email', 'inbound_referral_code']
widgets = {'inbound_referral_code': forms.HiddenInput()}
My View is:
def register(request):
if request.method == 'POST':
form = UserForm(request.POST)
[...]
else:
form = UserForm()
return render(request, 'register.html', {'form': form})
And my template is currently:
<form action="{% url 'register' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit"/>
</form>
Two questions:
How do I assign ?refcode parameter to inbound_referral_code field?
What happens if ?refcode isn't provided?
Combining the different answers, the following solution worked:
Set the "initial" value of the form parameter, and ensure the template renders with the bound form if validation fails. The correct view function is:
def register(request):
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
return redirect([...])
else:
refcode = request.GET.get('refcode')
form = UserForm(intial={'inbound_referral_code': refcode)
return render(request, 'register.html', {'form': form})
Note that the bottom return render(...) needed to be moved so that it is also called with the form from the POST request if it contains validation errors...
To assign the refcode, you need to pass it into the form, so you pass in something other than request.POST that contains it, change it before
dict = request.POST.copy()
dict["inbound_referral_code"] = request.POST.get("refcode")
form = UserForm(dict)
# ...
or after validating:
if form.is_valid():
form.cleaned_data["inbound_referral_code"] = request.POST.get("refcode")
If it isn't provided, you can check for that and pass a custom value, or set a default when defining the form/model.
To set it in the template, you can pass an initial value
else:
form = UserForm(initial={"inbound_referral_code": "ref-value-here"})
return render(request, 'register.html', {'form': form})

ModelForm won't create instance of model

I am trying to create a frontend form in my Django site that will allow users to add entries to my SQL database.
But when I use the form nothing happens in my database. What am I doing wrong?
I thought the right way would be to use the ModelForm technique.
My models looks like this:
class Actor(models.Model):
name = models.CharField(max_length=200)
wage = models.IntegerField(default=3100)
def __str__(self):
return self.name
So I wrote this in my forms.py:
from django import forms
from .models import Actor
class ActorForm(forms.ModelForm):
class Meta:
model = Actor
fields = ['name', 'wage']
form = ActorForm()
I then added this to my views.py:
def get_actor(request):
if request.method == 'POST':
form = ActorForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/scenes/thanks/')
else:
form = ActorForm()
return render(request, 'scenes/actor.html', {'form': form})
def thanks(request):
return render(request, 'scenes/thanks.html',)
And this in a template called actors.html
<form action="/scenes/actor/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
You have to call the model form's save() method after checking that it's valid:
def get_actor(request):
if request.method == 'POST':
form = ActorForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/scenes/thanks/')
else:
form = ActorForm()
return render(request, 'scenes/actor.html', {'form': form})

ValueError at /profile/ in Django: didn't return an HttpResponse object

I have this line of code in models.py
#login_required
def user_profile(request):
if request.method == 'POST':
form = UserProfileForm(request.POST, instance=request.user.profile)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/loggedin')
else:
user = request.user
profile = user.profile
form = UserProfileForm(instance=profile)
args = {}
args.update(csrf(request))
args['form'] = form
return render(request, 'profile.tml', args)
and in forms.py
from django import forms
from models import UserProfile
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('address', 'contactnos')
in my loggedin.html
{% extends 'base.html' %}
{% block content %}
<h2> Hi {{ full_name }} you are logged in!</h2>
<p>click here to logout. </p>
<p>Click here to edit your profile info </p>
{% endblock %}
The error is says:
ValueError at /profile/
The view userprofile.views.user_profile didn't return an HttpResponse object.
You haven't accounted for a GET scenario; what happens when the view is not accessed via POST? You return nothing, therefore you get this error.
Return an http.HttpResponse when request.method != 'POST'
Perhaps you meant to un-indent the bottom half else statement.
You haven't accounted for a GET scenario; what happens when the view is not accessed via POST? You return nothing, therefore you get this error.
Return an http.HttpResponse when request.method != 'POST'
Perhaps you meant to un-indent the bottom half else statement.
#login_required
def user_profile(request):
if request.method == 'POST':
form = UserProfileForm(request.POST, instance=request.user.profile)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/loggedin')
else:
user = request.user
profile = user.profile
form = UserProfileForm(instance=profile)
args = {}
args.update(csrf(request))
args['form'] = form
return render(request, 'profile.tml', args)

Categories