So I have the following files:
Views.py:
def home(request):
return render(request, 'home/index.html')
def add(request):
if request.method == 'POST': # If the form has been submitted...
# ContactForm was defined in the previous section
form1 = AddEventForm(request.POST) # A form bound to the POST data
#person = AddPersonForm(request.POST) # A form bound to the POST data
if form1.is_valid(): # All validation rules pass
form = form1.save()
request.session['event_data'] = request.POST
#request.session['event_data2'] = form
return HttpResponseRedirect('/add_person/')
#return HttpResponseRedirect(reverse('/add_person', kwargs={'PK':form.pk}))
else:
form1 = AddEventForm() # An unbound form
person = AddPersonForm() # A form bound to the POST data
return render(request, 'add/add.html', {
'form1': form1, 'person': person,
})
def add_person(request):
event_data = request.session.get('event_data')
if request.method == 'POST':
person = AddPersonForm(request.POST)
else:
person = AddPersonForm()
return render(request, 'add_person/add_person.html',{'event_data': event_data, 'person': person,})
models.py:
class event(models.Model):
event_name = models.CharField(max_length=200)
date = models.DateField('Date',default=date.today)
event_id = models.AutoField(primary_key=True)
admin_username = models.CharField(max_length=50)
def __unicode__(self):
return ('%s %s %d') % (self.date, self.event_name, self.event_id)
class Person(models.Model):
eventID = models.ForeignKey(event)
first_name = models.CharField(max_length=50)
second_name = models.CharField(max_length=50)
email = models.EmailField(max_length=50)
phone = models.CharField(max_length=25)
company = models.CharField(max_length=200)
favourite = models.BooleanField(default=False)
def __unicode__(self):
return eventID
This problem has been bugging me for hours. I have an initial page where the user enters some information about an event. If the checks pass the form saves and a primary key is generated. The user is then redirected to another page where they fill out a form about the people they have met there. The problem is I cannot find a way of passing the primary key to the second page (add_people). I need the primary key because it is my foreign key in my Person table and I need to use to pre-populate the eventID in the add_people page.
I initially thought the primary key would be in the request.POST after the form is saved but its not.
Query the table for the primary key using the form inputs as arguments. Once you get the key, pass it as a session variable in the request object.
Here's an answer to the same question but with class-based views instead of function-based views: How do I pass a parent id as an fk to child object's ModelForm using generic class-based views in Django?. In that example, the foreign key is passed from the parent page to the child page by being a parameter in the URL. The child page catches it as a form parameter (in the form's __init__ function), stores it in a hidden field for display (by the View class's get_context_data and html code in the form template), and then submits it as part of the form.
If your form is validated, then your have to set session value as eventID but not request.POST
if form1.is_valid(): # All validation rules pass
form1.save(commit=False)
request.session['event_data'] = form1.cleaned_data['eventID']
form1.save()
return HttpResponseRedirect('/add_person/')
Related
I have a ModelForm, and I want to only pass some of the fields into the template. I would like to save one particular field to define after the POST request has been sent. Here is the ModelForm:
class CreateListingForm(ModelForm):
class Meta:
model = models.ListingModel
fields = ['name', 'image', 'description', 'price', 'category']
widgets = {
'description': Textarea()
}
And here is the Model:
class ListingModel(models.Model):
name = models.CharField(max_length=30)
image = models.ImageField(upload_to='images')
description = models.CharField(max_length=1000)
price = models.PositiveIntegerField()
category = models.CharField(max_length=15)
objects = models.Manager()
owner = models.CharField(max_length=100)
In the next code block, I am attempting to define the owner field according to the current user logged in (request.user.username):
#login_required(redirect_field_name=login_view)
def create_listing(request):
if request.method == "GET":
return render(request, "auctions/createlisting.html", {
"CreateListingForm": forms.CreateListingForm()
})
elif request.method == "POST":
form = forms.CreateListingForm(request.POST, request.FILES)
if form.is_valid():
try:
form.owner = request.user.username
print(form.owner)
form.save(commit=True)
except Exception:
return HttpResponseRedirect(reverse("create_listing_error"))
return HttpResponseRedirect(reverse("index")) #TODO
Now, when I say print(form.owner), the result is correct. However when I save the ModelForm, the owner field is left blank. Am I not defining the value of the owner field correctly?
You should not confuse the ModelForm with the instance it is wrapping. The fact that it prints something for form.owner is not that strange, you first set an attribute named .owner, an attribute that did not exists before. You should set the .owner of the .instance of the form:
#login_required(redirect_field_name=login_view)
def create_listing(request):
if request.method == 'POST':
form = forms.CreateListingForm(request.POST, request.FILES)
if form.is_valid():
form.instance.owner = request.user.username
form.save()
return redirect('name-of-some-view')
else:
form = forms.CreateListingForm()
return render(request, 'auctions/createlisting.html', {
'CreateListingForm': form
})
Where 'name-of-some-view' should be replaced by the name of some view to which you redirect in case the form was valid.
You should however consider changing the CharField of owner to a ForeignKey [Django-doc]. Imagine that later the user changes their username, then your ListingModels do no longer refer to a real user.
I have a website contact form that generates a dropdown box of "names" that are defined in another model "Data". The contact form runs off the model "Quote". As such, I use a ForeignKey reference to populate the "Data" information within the "Quote"-driven form.
However, the next step is to move this data to more python code (i.e., for calculations and placement in an email). But, when I request.POST "name" in the quote views file, I receive an ID (i.e., 1) instead of the actual string value for "name." I have read this is how ForeignKey inherently transfers data.
Like how I returned the actual string version of "name" in the quote dropdown box, how do I get the actual string version of "name" in a data request.POST / data_dictionary assignment? I have seen similar questions, but I am not completely sure of the simplest answer.
models.py (Original one)
class Data(models.Model):
name = models.CharField(max_length=100, null=True)
def __str__(self):
return self.name
models.py (The one tied to the form)
class Quote(models.Model):
name = models.ForeignKey(Data, on_delete=models.CASCADE)
def __str__(self):
return str(self.name)
views.py
def quote_req(request):
submitted = False
if request.method == 'POST':
form = QuoteForm(request.POST, request.FILES)
name = request.POST['name']
if form.is_valid():
data_dict = {
'name_': str(name),
inputdictionary = data_dict
forms.py
class QuoteForm(ModelForm):
helper = FormHelper()
helper.form_show_labels = False
required_css_class = 'required'
class Meta:
model = Quote
fields = ['name',]
Variable Assignment
▼ Local vars
Variable Value
name '1'
Respective Error (I need the actual string value of "name")
IndexError at /quote/
list index out of range
The solution was in tandem with what #dirkgroten mentioned in the comments. I have to add the form.cleaned_data method after the if form.is_valid statement. No other files need to be modified.
views.py
def quote_req(request):
submitted = False
if request.method == 'POST':
form = QuoteForm(request.POST, request.FILES)
name = request.POST['name']
if form.is_valid():
name = form.cleaned_data['name']
data_dict = {
'name_': str(name),
inputdictionary = data_dict
I have created a form using python and django from 2 seperate modelForms in the one html template. Models:
class Action(models.Model):
name = models.CharField("Action name", max_length=50)
keywords = models.CharField("Keywords", max_length=50)
object = models.CharField("Object", max_length=50, blank=True, null=True)
uploadDate = models.DateField("Date", default=get_current_date)
UploadedBy = models.CharField("UploadedBy", max_length=50, default="")
class Image(models.Model):
image = models.FileField(upload_to=get_upload_file_name, default="")
action = models.ForeignKey(Action)
def get_upload_file_name(instance, filename):
return "uploaded_files/%s_%s" % (str(datetime.now().day).replace('.','_'), filename)
forms:
class ActionForm(ModelForm):
#bind form to Action model
class Meta:
model = Action
fields = ['name','keywords', 'object', 'UploadedBy', 'uploadDate']
class ImageForm(ModelForm):
class Meta:
model= Image
fields =['image']
The code which creates the form in views:
def actioncreate(request):
if request.method == "GET":
#create the object - Actionform
form = ActionForm;
form2 = ImageForm;
#pass into it
return render(request,'app/createForm.html', { 'form':form, 'form2':form2})
elif request.method == "POST":
# take all of the user data entered to create a new action instance in the table
form = ActionForm(request.POST, request.FILES)
form2 = ImageForm(request.POST, request.FILES)
if form.is_valid() and form2.is_valid():
act = form.save(commit=False)
img = form2.save(commit=False)
#set the action_id Foreignkey
act.id = img.action_id
act.save()
img.save()
return HttpResponseRedirect('/actions')
else:
form = ActionForm()
form2 = ImageForm;
return render(request,'app/createForm.html', { 'form':form, 'form2':form2 })
The form is created fine but when it is submitted, it trys to save image.id, image.image (filename) and returns null for image.action_id
I am getting the error:
null value in column "action_id" violates not-null constraint
DETAIL: Failing row contains (2, uploaded_files/29_personrunning_Hq8IAQi.jpg, null).
I obviously need to populate the third column with the action.id which django creates itself on submitting the first part 'form'. Is there a way I can get the action.id value and populate the action_id field in the image table in the one form submission?
image.action_id is declared initially as a foreignKey related to action in models.
The first problem is related to act = form.save(commit=False) because it will return an object that hasn’t yet been saved to the database, then act doesn't have an ID. You need to save (and commit) act first.
Also there is another error in following line:
act.id = img.action_id # It should be: img.action_id = act.id
You may want to assign act to img.action. Please note that you are doing it in the wrong way (you are assigning in img.action to act). The best way to do it is:
img.action = act # This is equivalent to img.action_id = act.id
Try swapping these lines:
act.save()
img.action = act
I have created a model Student which extends from the Django User and is a foreign key to another model while it has an integer field called year. What i'm trying to do is to save a form, which has 2 fields. The one is the course id and the another one is the the integer field year. When I'm clicking submit, i'm getting an error Cannot assign "u'2'": "Student.course" must be a "Course" instance.
models.py
class Student(models.Model):
user = models.OneToOneField(User)
course = models.ForeignKey(Course)
year = models.IntegerField(validators=[MinValueValidator(1),
MaxValueValidator(7)])
view.py
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
forms.py
class SelectCourseYear(forms.ModelForm):
course = forms.CharField()
year = forms.IntegerField(required=True)
class Meta:
model = Student
fields = ['user', 'course', 'year']
You dont need to redefine fields in the ModelForm if you've already mentioned them in the fields attribute. So your form should look like this -
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
fields = ['course', 'year'] # removing user. we'll handle that in view
And we can handle the form with ease in the view -
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
student = form.save(commit=False)
# commit=False tells Django that "Don't send this to database yet.
# I have more things I want to do with it."
student.user = request.user # Set the user object here
student.save() # Now you can send it to DB
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
course has to be an instance of a Course model, not just the primary key of the instance. You can still accept an id in the form as a text input, but you're going to need to retrieve the actual course instance and assign the value.
You'll need to verify that the course id is valid, so putting that code into the clean method isn't a bad idea. Notice also how the course field is excluded here? Otherwise the form will expect it to be present. You also don't need to re-define the year field, as the ModelForm will inherit that field from the Student model.
# forms.py
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
exclude = ['user', 'course']
course_id = forms.IntegerField()
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(SelectCourseYear, self).__init__(*args, **kwargs)
def clean_course_id(self):
course_id = self.cleaned_data.get('course_id')
try:
self.course = Course.objects.get(pk=course_id)
except Course.DoesNotExist:
raise forms.ValidationError('Sorry, that course id is not valid.')
return course_id
def save(self, commit=True):
instance = super(SelectCourseYear, self).save(commit=False)
instance.course = self.course
instance.user = self.user
if commit:
instance.save()
return instance
# views.py
def step3(request):
if request.method == 'POST':
form = SelectCourseYear(request.POST or None, user=request.user)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html",
RequestContext(request))
return render(request, 'registration/step3.html',)
Now, when you call .save() on the model, the course field will be assigned an instance of Course
So, I have a table called "order" that has a foreign key with the table "store". The order table has a boolean field set by default to false. When a new order is created, I need to loop through the boolean values associated with each individual store and set the other orders to false and the new order to true. Not sure how to create the for loop for that. First I tried to set it into the view, but maybe it can be put into the forms.py file? This my create code so far.
def create(request):
if request.POST:
form = OrderForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/liquors/all')
else:
form = OrderForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_order.html', args)
Models provided upon request, you shouldn't need anything except the order model:
class Order(models.Model):
OrderID = models.AutoField(primary_key=True)
storeID = models.ForeignKey(Store)
DateCreated = models.DateField('Date Created', auto_now_add=True)
OrderName = models.CharField('Order Name', max_length=25 )
Active = models.BooleanField()
you must return render_to_response('create_order.html', args) one indentation back. so that validation form will not affected. you don't need to use csrf request if you are using render. I think there is no need to use OrderId in Order model, since it is automattically created. ie id
from django.shortcuts import render
from <appname>.models import Order,Store
def create(request):
if request.POST:
form = OrderForm(request.POST)
if form.is_valid():
#i just assume the storeid variable is exist in request.POST and it is ID.
store_data=Store.objects.get(id=request.POST['storeid'])
#here you might need to update the other orderform to false
Order.objects.filter(storeID=store_data).update(Active=False)
fo=Order(storeID=store_data,Active=True)
frm_order=OrderForm(request.POST,instance=fo)
frm_order.save()
return HttpResponseRedirect('/liquors/all')
else:
form = OrderForm()
return render(request,'create_order.html', {'form':form})
You can use the order object's meta object to loop through the fields. Ex.
for field in order._meta.fields():
if type(field) = django.db.models.fields.BooleanField:
setattr(order, field.name, True)