I'm going to receive data and save it using form and save it. But I can't get any result. Let me know what I'm doing wrong.
I set up a model. And I wrote a form to get the input. Forms.Form was used. At first, I used modelform, but I wrote it like this because there seemed to be no difference.
Is label important in the form? You can't get the data value because you can't connect the label?
heeelp!
models.py
class PayHistory(models.Model):
branch = models.ForeignKey(Branch, on_delete=models.CASCADE, null=True)
package_recommandation_date = models.DateField(null=True)
package_payment_date = models.DateField(null=True)
forms.py
class PackageForm(forms.Form):
package_recommandation_date = forms.CharField(label='package_recommandation_date')
package_payment_date = forms.CharField(label='package_payment_date')
...
## i changed like this(1)
class PackageForm(forms.ModelForm):
class Meta:
model = PayHistory
fields = ['package_recommandation_date', 'package_payment_date']
views.py
class PackageView(FormView):
model = PayHistory
template_name = 'branches/package-create.html'
success_url = reverse_lazy('/')
form_class = PackageForm
def form_valid(self, form):
form = form.save(commit=False)
form.save()
return super().form_valid(form)
### I realize what you mean. I changed it like this(2) and it was saved in DB.
def form_valid(self, form):
data = PayHistory()
data.package_recommandation_date = form.cleaned_data['package_recommandation_date']
data.package_payment_date = form.cleaned_data['package_payment_date']
data.save()
return super().form_valid(form)
# HTML
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="table-content">
<!-- 검색 -->
<table border="0">
<tr class="input-tr">
<td><input type="date" class="input1" name="package_recommandation_date"
value="{{ form.package_recommandation_date.value|default_if_none:'' }}" required>
</td>
<td><input type="date" class="input2" name="package_payment_date"
value="{{ form.package_payment_date.value|default_if_none:'' }}">
</td>
...
<td><button type="submit" class="input-button input16">적용</button></td>
# static/js
const package_recommandation_date = document.querySelector("package_recommandation_date");
const package_payment_date = document.querySelector("package_payment_date");
console.info(package_recommandation_date, package_payment_date)
#output
-> null null
Related
This is in my template:
<form hx-post="{% url 'orders:create' %}">
{% csrf_token %}
{% for service in venue.services.all %}
<input type="checkbox" name="services" value="{{ service.id }}"> {{ service.name }}<br>
{% endfor %}
<button
hx-include="[name='id']"
type="submit"
class="btn btn-primary btn-lg ">
<input type="hidden" value="{{ venue.id }}" name="id">
Submit
</button>
</form>
And this is the view:
class OrderCreateView(CreateView):
model = Order
form_class = OrderForm
template_name = "orders/order_page.html"
success_url = reverse_lazy("orders:success")
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["venues"] = Venue.objects.all()
return context
def form_valid(self, form):
if self.request.htmx:
# Get the IDs of the chosen services
service_ids = self.request.POST.getlist('services')
# Set the venue field of the form
form.instance.venue = Venue.objects.get(id=self.request.POST.get("id"))
# Save the form
self.object = form.save()
# Add the chosen services to the Order object
for service_id in service_ids:
service = Service.objects.get(id=service_id)
self.object.chosen_services.add(service)
return super().form_valid(form)
The problem is that the object is being created but only the line with form.instance.venue works, the part where the chosen_services are being added doesn't work, the object is created without any of them.
The service_ids variable is populated with the information from the front end, it has the ids that i need, it just doesn't add them to the object.
This is models.py:
class Order(models.Model):
venue = models.ForeignKey(Venue, on_delete=models.SET_NULL, null=True)
chosen_services = models.ManyToManyField(Service, null=True, blank=True)
Try this code
Here m2m field is already handled by form, you need to just set the value of the venue field with save() method of form
def form_valid(self, form):
if self.request.htmx:
# Get the IDs of the chosen services
service_ids = self.request.POST.getlist('services')
fm = form.save()
# Set the venue field of the form
fm.venue = Venue.objects.get(id=self.request.POST.get("id"))
fm.save()
return super().form_valid(form)
The problem was that in forms.py i had this:
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ["chosen_services"]
I deleted that and now it works!
I have an issue with my Django forms and combining it with data from my database.
I need to get data about tickets to generate the form via {% for ticket in tickets %}
Once the user chose the ticket(s) and quantity, the form will check this request. I wanted to use Form.is_valid() and cleaned_data, however, I couldn't manage to combine this with step 1.
Do you guys have any tips or input how I can make my code more "safe"? Currently, I am skipping all the provided security Django provides with cleaned_data and is_valid(). The reason why is that I don't know how to do it.
views.py
from django.shortcuts import render
from .models import Ticket
from tickets.models import Order, Entry
# Create your views here.
def choose_ticket_and_quantity(request):
tickets = Ticket.objects.all()
if request.POST:
o = Order.objects.create()
request.session['order_id'] = o.order_id
ticket_id = request.POST.getlist('ticket_id')
ticket_quantity = request.POST.getlist('ticket_quantity')
for x in range(len(ticket_id)):
if int(ticket_quantity[x]) > 0:
e = Entry(
order=Order.objects.get(order_id = o.order_id),
ticket=Ticket.objects.get(id = ticket_id[x]),
quantity=ticket_quantity[x]
).save()
return render(request, "tickets/choose_ticket_and_quantity.html", {"tickets": tickets})
models.py
class Ticket(models.Model):
description = models.TextField()
name = models.CharField(max_length=120)
price_gross = models.DecimalField(max_digits=19, decimal_places=2)
quantity = models.IntegerField()
choose_ticket_and_quantity.html
<form action="" method="post">
{% csrf_token %}
{% for ticket in tickets %}
<input type="hidden" name="ticket_id" value="{{ ticket.id }}">
{{ ticket.name }}
<select name="ticket_quantity" >
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
{% endfor %}
<p><input type="submit" value="Checkout"></p>
</form>
Here what I currently tried/started within forms.py
But I don't know how to render the *.html while getting the ticket data from its model.
from django import forms
#Currently not used
INT_CHOICES = [tuple([x,x]) for x in range(0,11)]
class TicketForm(forms.Form):
ticket_quantity = forms.IntegerField(widget=forms.Select(choices=INT_CHOICES))
You can create a EntryModelForm for your Entry model and then create a FormSet of EntryModelForm.
Django Formset documentation
Here is sample view function:
from django.forms import formset_factory
def choose_ticket_and_quantity(request):
tickets = []
for ticket in Ticket.objects.all():
tickets.append({'ticket': ticket})
EntryFormSet = formset_factory(EntryModelForm, extra=0)
formset = EntryFormSet(initial=tickets)
if request.POST:
o = Order.objects.create()
formset = EntryFormSet(request.POST, initial=tickets)
for form in formset:
if form.is_valid():
entry = form.save(commit=False)
entry.order = o
entry.save()
return render(request, "tickets/choose_ticket_and_quantity.html",
{'formset': formset})
I guess your entry model class might be something like the following:
class Entry(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
quantity = models.IntegerField(choices=INT_CHOICES)
Here is the form class:
class EntryModelForm(forms.ModelForm):
class Meta:
model=Entry
exclude = ('order',)
Here is the HTML template:
<form action="" method="post">
{% csrf_token %}
{{ formset }}
<p><input type="submit" value="Checkout"></p>
</form>
Fields I have added in django forms are not visible on webpage.
Attached model, view and html for the reference below.
This is an additional filed which I intent to add to the forms, I am new to Django and learning by enhancing the current project.
"estimated_headcount" is the new filed I have added in the forms.
Thanks
Model
class EstimatedHeadcount(models.Model):
count = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class Meta:
default_permissions = []
#staticmethod
def __gotoadmin__():
return True
forms.py
class ClientProfileForm(forms.ModelForm):
class Meta:
model = ClientProfile
fields = ('full_name', 'short_name', 'account_payable',
'require_job_number', 'currency', 'segment', 'market', 'estimated_headcount', 'is_technicolor',
'address')
views.py
def client_profile(request):
all_profiles = ClientProfile.objects.filter(status='active')
profile = None
pid = request.GET.get('pid')
client_profile_form = ClientProfileForm()
if pid:
profile = ClientProfile.objects.get(id=pid)
client_profile_form = ClientProfileForm(instance=profile)
if request.method == 'POST':
client_profile_form = ClientProfileForm(request.POST, instance=profile)
if client_profile_form.is_valid():
profile = client_profile_form.save()
profile.csv_mapping = profile.full_name
profile.save()
if profile:
for task_type in TaskType.objects.all():
if not profile.task_costs.filter(task_type=task_type):
task_cost = TaskCost(task_type=task_type)
task_cost.save()
profile.task_costs.add(task_cost)
return render(request, "prod/client_profile.html", {'all_profiles': all_profiles,
'profile': profile,
'client_profile_form': client_profile_form})
clientprofile.html
<div class="content">
<form id='add_new_client_form' method="post" action="">
{% csrf_token %}
<table class="table">
<tbody>
{{ client_profile_form.as_table }}
</tbody>
<tfoot>
<tr>
<td></td>
<td>
<button class="lock" type="button"
onclick="unlock(this, '#add_new_client_form')">Unlock
</button>
<button type="submit">SAVE</button>
</td>
</tr>
</tfoot>
</table>
</form>
</div>
As far as I can tell from your code, there is no relation between the ClientProfile model and the EstimatedHeadcount model.
estimated_headcount should be a field on the ClientProfile model.
class ClientProfile(models.Model):
...
estimated_headcount = models.CharField(max_length=100)
Side note: I would expect the estimated headcount to be a numeric value, so an IntegerField or PositiveIntegerField might be a better choice.
New to Django and Python and I need a little help with a foreign key drop down. Basically, I have a category model and a image model and I want users to be able to choose which category to put the image in. How do I create a drop down for the category in the image form? Are my views and html correct too? I have had a look online but I can't seem to do it myself. I keep getting errors.
Here are my models:
class Images(models.Model):
image = models.ImageField(upload_to='images', blank=False)
img_name = models.CharField(max_length=120, blank=True)
img_date = models.DateTimeField(default=now())
img_user = models.ForeignKey(User)
img_cat_id = models.ForeignKey(Categories)
def __unicode__(self):
return self.img_name
class Categories(models.Model):
cat_descr = models.CharField(max_length =120, blank=False)
def __unicode__(self):
return self.cat_descr
VIEWS:
#login_required
def upload_images(request):
context = RequestContext(request)
context_dict={}
if request.method == 'POST': # render the form, and throw it back.
# take the form data and process it!
form = UploadImagesForm(request.POST, request.FILES)
if form.is_valid():
print 'form is_valid'
upload_image = form.save(commit=False)
upload_image.img_user = request.user
if 'image' in request.FILES:
upload_image.image =request.FILES['image']
upload_image.save()
return render(request, 'rmb/upload.html', {'upload_image': form})
else:
print form.errors
# Not a HTTP POST, so we render our form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
form = UploadImagesForm()
context_dict = {'upload_image': form}
all_categories = Categories.objects.order_by('-id')
context_dict['all_categories'] = all_categories
print context_dict
return render_to_response('rmb/upload.html', context_dict, context)
FORMS:
class UploadImagesForm(forms.ModelForm):
#cat_list = ModelChoiceField(queryset=Categories.objects.all())
class Meta:
model = Images
fields=('image','img_name')
HTML:
{% block body_block %}
<form id="upload_form" method="post" action="/rmb/upload/"
enctype="multipart/form-data">
{% csrf_token %}
{{ upload_image.as_table }}
<input type="submit" name="submit" value="Upload" />
{% for categories in all_categories %}
<div> {{ categories.id }} </div>
{{ categories.cat_descr }}
<input type="submit" name="submit" value="Upload" />
{% endfor %}
</form>
{% endblock %}
You don't need to insert the HTML for the form manually, just use {{form}} in the template.
{% block body_block %}
<form id="upload_form" method="post" action="/rmb/upload/"
enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
</form>
{% endblock %}
By default a ForeignKey will be a select field so you shouldn't need to do much else.
As an aside, give your models and fields more appropriate names. We know these are all image fields, because they are on the image and make sure, unless your model is a collection of things, you give it a singular name. Lastly, when using a Foreign Key and item gets an extra field of fieldname_id that is just the ID, whereas fieldname is the property that gives the related item as well.
So instead of:
class Images(models.Model):
image = models.ImageField(upload_to='images', blank=False)
img_name = models.CharField(max_length=120, blank=True)
img_date = models.DateTimeField(default=now())
img_user = models.ForeignKey(User)
img_cat_id = models.ForeignKey(Categories)
Use:
class Image(models.Model):
image = models.ImageField(upload_to='images', blank=False)
name = models.CharField(max_length=120, blank=True)
date = models.DateTimeField(default=now())
user = models.ForeignKey(User)
category = models.ForeignKey(Categories)
The Quetion
Hello. I'm trying to figure out the best way to use one form to create one parent object and then create 0-n sub objects. I'm assuming ModelForms are what I need to do, but I'm having a hard time understanding how to structure the template and view. Would someone be willing to explain how to create n number of sub objects?
The Research
I've read several other articles and posts relating to this:
django model/modelForm - How to get dynamic choices in choiceField?
https://stackoverflow.com/questions/5575560/how-do-i-create-a-drop-down-menu-in-django-using-a-modelform-with-dynamic-values
http://collingrady.wordpress.com/2008/02/18/editing-multiple-objects-in-django-with-newforms/
Overriding the save method in Django ModelForm
To name a few.
The Details
I have two models like so:
// models.py
class DataItem(models.Model):
name = models.CharField(max_length=255)
date_created = models.DateTimeField(auto_now_add=True)
date_last_updated = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, blank=False)
def __unicode__(self):
return self.name
class DataItemSet(models.Model):
item = models.ForeignKey(DataItem, blank=False)
type_ind = models.IntegerField()
And I've created two ModelForms to correspond:
// forms.py
class CreateDataItemForm(forms.ModelForm):
class Meta:
model = DataItem
exclude = ('owner',)
def save(self, user, commit=True):
item = super(CreateDataItemForm,self).save(commit=False)
item.owner = user
if commit:
item.save()
return item
class CreateDataItemSetForm(forms.ModelForm):
class Meta:
model = DataItemSet
exclude = ('item',)
def save(self, parent, commit=True):
set = super(CreateDataItemSetForm,self).save(commit=False)
set.item = parent
if commit:
set.save()
return set
And in my view, I'm trying to have one form submit the creation of a new DataItem and 1-n DataItemSets which are owned by the DataItem. Here is an example of the output of the form:
And the template:
<form action="." method="post">
{% csrf_token %}
<table>
{{ create_form.as_table }}
</table>
<table>
<tr>
<th>What to track:</th>
<td>
<select>
<option value="1">Number</option>
<option value="2">Currency ($)</option>
<option value="3">Date</option>
<option value="4">Day</option>
<option value="5">Time</option>
</select>
</td>
<td>
</td>
</tr>
<tr>
<th>What to track:</th>
<td>
<select>
<option value="1">Number</option>
<option value="2">Currency ($)</option>
<option value="3">Date</option>
<option value="4">Day</option>
<option value="5">Time</option>
</select>
</td>
<td>
<button type="button">+</button>
</td>
</tr>
</table>
<p>
<button type="submit">Create</button>
</p>
</form>
And lastly, the view:
// views.py
#login_required
#csrf_protect
def create_data_item(request):
create_form = CreateDataItemForm()
c = {'create_form':create_form}
c.update(csrf(request))
if request.method == 'POST':
data = request.POST.copy()
form = CreateDataItemForm(data, instance=DataItem())
item_sets = [CreateDataItemSetForm(request.POST, prefix=str(x), instance=DataItemSet()) for x in range(0,9)]
if form.is_valid():
# create new data item
new_item = form.save(request.user)
#create new set of stuff to track
for item_set in item_sets:
new_item_set = item_set.save(new_item)
# return to the add entry page
return redirect('/add')
else:
return render_to_response('internal/create_data_item.html',c)
I'm missing how to allow for dynamic extraction of 0-n DataItemSets from the form. I can't figure it out with ModelForm.
Thanks for any help!
This is what model formsets - specifically, inline formsets - are for.