Lets say I have an incident loaded into the database, where there is information in the description and status fields, but action_taken is left NULL.
class Incident(models.Model):
description = models.TextField()
status = models.ForeignKey(Status, default="open")
action_taken = models.TextField()
How can I load information into the action_taken field using this form and view?
forms.py
class ResolveForm(forms.Form):
action_taken = forms.CharField(widget=forms.Textarea)
views.py
def detail(request, incident_id):
incident = get_object_or_404(Incident, pk=incident_id)
template = "incidents/detail.html"
if request.method == 'POST':
form = ResolveForm(request.POST or None)
if form.is_valid():
action_taken = (form.cleaned_data['action_taken'])
######### MY EFFORTS #########################
q = Incident(action_taken=action_taken)
q.save()
print(incident.id)
#new_incident, created = Incident.objects.get_or_create(action_taken)
##############################################
return render(request, template, {'form': form})
else:
form = ResolveForm()
context = { 'incident': incident,
'form': form}
return render(request, template, context)
errors
incident.action_taken = action_taken
error: name 'action_taken' is not defined
How can I load information into the action_taken field using this form and view?
I see you already have your model instance incident, so this should do it
incident = get_object_or_404(Incident, pk=incident_id)
incident.action_taken = action_taken
incident.save()
If in your update you don't want to touch the other fields:
incident = get_object_or_404(Incident, pk=incident_id)
incident.action_taken = action_taken
incident.save(update_fields=['action_taken'])
To critique what you tried:
q = Incident(action_taken=action_taken)
q.save()
This doesn't get the object you want to update, but instead it creates a new one and saves it (not what you want)
Related
I have a app where people can declare things, within a decla they can say who was present so they have to pay, only its not working. The edit function works but the fileDecla doesn't.
The part that doensn't work is the present people. When i print the people present (via print(request.POST))before i save the decla it gives all the people selected but then it doesnt save them, and when i print(decla.present) i get --> None.(it should be all the people present.
Does someone know a solution to this?
models.py
class Decla(models.Model):
owner = models.ForeignKey(Lid, on_delete=models.CASCADE)
event = models.ForeignKey(Event, on_delete=models.SET_NULL, null=True, blank=True)
content = models.TextField(max_length=50)
total = models.FloatField()
present = models.ManyToManyField(Lid, related_name="present_leden")
receipt = models.ImageField(
upload_to="declas/", null=True, blank=True
) ## this will need to be put back to nothing when it ends
verwerkt = models.BooleanField(default=False)
views.py
#login_required(login_url="login")
def fileDecla(request):
form = DeclaForm()
if request.method == "POST":
print(1, request.POST)
form = DeclaForm(request.POST, request.FILES)
if form.is_valid():
# print(form)
decla = form.save(commit=False)
decla.owner = request.user.lid
# i tried this line bellow but it didnt work
# decla.present.set(request.POST["present"])
decla.save()
messages.info(request, "Decla was created")
return redirect("agenda")
context = {
"form": form,
"stand": Stand.objects.get(owner_id=request.user.lid.id).amount,
}
return render(request, "finance/decla_form.html", context)
#login_required(login_url="login")
def editDecla(request, pk):
decla = Decla.objects.get(id=pk)
form = DeclaForm(instance=decla)
if request.method == "POST":
print(request.POST)
form = DeclaForm(request.POST, request.FILES, instance=decla)
if form.is_valid():
decla = form.save()
messages.info(request, "Decla was edited")
return redirect(request.GET["next"] if "next" in request.GET else "agenda")
context = {
"form": form,
"stand": Stand.objects.get(owner_id=request.user.lid.id).amount,
}
return render(request, "finance/decla_form.html", context)
forms.py
from django import forms
from django.forms import ModelForm
from django.forms.widgets import NumberInput, CheckboxSelectMultiple
from .models import Decla
class DeclaForm(ModelForm):
class Meta:
model = Decla
fields = "__all__"
exclude = ["owner", "id"]
widgets = {
"present": CheckboxSelectMultiple(),
}
def __init__(self, *args, **kwargs):
super(DeclaForm, self).__init__(*args, **kwargs)
for name, field in self.fields.items():
if not name in ["verwerkt", "present"]:
field.widget.attrs.update({"class": "input"})
# also tried this
# elif name == "present":
# field.widget.attrs.update({"class": "CheckboxSelectMultiple"})
else:
field.widget.attrs.update({"class": "checkbox"})
Here is something from the docs:
Another side effect of using commit=False is seen when your model has
a many-to-many relation with another model. If your model has a
many-to-many relation and you specify commit=False when you save a
form, Django cannot immediately save the form data for the
many-to-many relation. This is because it isn’t possible to save
many-to-many data for an instance until the instance exists in the
database.
To work around this problem, every time you save a form using
commit=False, Django adds a save_m2m() method to your ModelForm
subclass. After you’ve manually saved the instance produced by the
form, you can invoke save_m2m() to save the many-to-many form data.
According to this, adding save_m2m() after calling decla.save() would resolve your issue:
#login_required(login_url="login")
def fileDecla(request):
form = DeclaForm()
if request.method == "POST":
print(1, request.POST)
form = DeclaForm(request.POST, request.FILES)
if form.is_valid():
# print(form)
decla = form.save(commit=False)
decla.owner = request.user.lid
# i tried this line bellow but it didnt work
# decla.present.set(request.POST["present"])
decla.save()
form.save_m2m()
messages.info(request, "Decla was created")
return redirect("agenda")
context = {
"form": form,
"stand": Stand.objects.get(owner_id=request.user.lid.id).amount,
}
return render(request, "finance/decla_form.html", context)
However, this seems like a messy solution. See this antipattern for more info.
My suggestion is to do this:
#login_required(login_url="login")
def fileDecla(request):
form = DeclaForm()
if request.method == "POST":
print(1, request.POST)
form = DeclaForm(request.POST, request.FILES)
if form.is_valid():
# This seems like a much cleaner solution and it should resolve your problem
form.instance.owner = request.user.lid
decla = form.save()
messages.info(request, "Decla was created")
return redirect("agenda")
context = {
"form": form,
"stand": Stand.objects.get(owner_id=request.user.lid.id).amount,
}
return render(request, "finance/decla_form.html", context)
Disclaimer: the code is untested. Let me know if you have any bugs.
I'm building a small web service for inventory control. As part of this, I want to populate a detail view for any of the inventory items. This is what I have so far for that:
class Product_Update(forms.Form):
Product_Code = forms.CharField(
max_length=10,
attrs={"placeholder = <ID here> Readonly = True"
)
Name = forms.CharField(max_length=100)
Description = forms.Textarea(attrs={"Rows": 3})
price = forms.DecimalField()
mini = forms.IntegerField()
Max = forms.IntegerField()
How do I pass the form the parameters?
You should use a ModelForm instead:
class ProductUpdate(forms.Form):
class Meta:
model = Product
fields = ('product_code', 'name', 'description', 'price', 'mini', 'max')
Now you can easily pass a model instance to your form:
def some_view(request):
instance = Product.objects.first()
form = ProductUpdate(request.POST or None, instance=instance)
context = {'form':form}
return render(request, 'some_template.html', context)
If you want to show multiple products in the same form, you will need to use modelformset_factory:
from django import forms
ProductFormSet = forms.modelformset_factory(Product, form=ProductUpdate, extra=0)
Now in your views.py, you can pass a QuerySet to your form:
def some_view(request):
queryset = Product.objects.all()
form = ProductFormSet(request.POST or None, queryset=queryset)
if request.method == 'POST' and form.is_valid():
form.save()
context = {'form':form}
return render(request, 'some_template.html', context)
You can access the form's data in the view by accessing request.POST
def actionView(request, product_id):
product = Product.objects.get(id=product_id)
form = ProductUpdate(request.POST, instance=product_id)
form.save(commit=False) #Do this if you want to make changes to some value
form.price = 112233
updated_form = form.save()
It sound simple but I want my page to display the database of my model.
I use ModelForm for user to input and it would save into my model. Now I want to render the whole table, not just each separately.
forms.py
class My_Folio(forms.ModelForm):
class Meta:
model = my_data
fields = ['symbol','buy_price','quantity']
views.py
def blockfolio(request):
if request.method == 'POST':
my_folio = My_Folio(request.POST)
if my_folio.is_valid():
symbol = my_folio.cleaned_data['symbol']
buy_price = my_folio.cleaned_data['buy_price']
quantity = my_folio.cleaned_data['quantity']
instance = my_folio.save(commit=False)
instance.save()
return render(request, 'blockfolio/blockfolio.html', {'symbol':symbol, 'buy_price':buy_price, 'quantity':quantity, 'instance':instance})
template:
{{instance}} This give me the user input after submit, but I want to show all of the inputs saved in database.
Maybe your post is invalid. Try this code in views.py.
def blockfolio(request):
if request.method == 'POST':
my_folio = My_Folio(request.POST)
if my_folio.is_valid():
symbol = my_folio.cleaned_data['symbol']
buy_price = my_folio.cleaned_data['buy_price']
quantity = my_folio.cleaned_data['quantity']
instance = my_folio.save(commit=False)
instance.save()
return render(request, 'blockfolio/blockfolio.html', {'symbol':symbol, 'buy_price':buy_price, 'quantity':quantity, 'instance':instance})
else:
print("request is invalid: {}".format(request.POST))
return "bad request!", 500
I am trying to create a 'Label'. Basically, you click on 'label' button, and it will show title and content under. I am using POST method. But when I click on 'submit', it gave me this error:
IntegrityError at /project/1/issue/2/label/
NOT NULL constraint failed: issue_tracker_label.project_id
Btw, I am using crispy form and I did do makemigrations and migrate after I modified my model.py. Not sure why I still get this error.
view.py
#csrf_exempt
def label_create(request, project_id,issue_id):
issue = get_object_or_404(Issue, id=issue_id)
project = Project.objects.get(id=project_id)
if request.method == 'POST':
form = LabelForm(request.POST)
if form.is_valid():
label = form.save(commit=False)
label.issue = issue
label.save()
return redirect('project:issue_tracker:issue_detail', project_id=project.id, issue_id=issue.id)
else:
form = LabelForm()
template = 'issue_tracker/issue/label.html'
context = {'form': form, 'project': project}
return render(request, template, context)
model.py
class Label(models.Model):
issue = models.ForeignKey(Issue, related_name='issue_label', on_delete=models.CASCADE)
project = models.ForeignKey(Project, related_name='project_label', on_delete=models.CASCADE)
title=models.CharField(max_length=20,default='Debug')
color=models.CharField(max_length=20,default='red')
def __str__(self):
return self.title
form.py
class LabelForm(forms.ModelForm):
class Meta:
model = Label
fields = ('title','color',)
Try adding the project in your object save:
views.py
#csrf_exempt
def label_create(request, project_id,issue_id):
issue = get_object_or_404(Issue, id=issue_id)
project = Project.objects.get(id=project_id)
if request.method == 'POST':
form = LabelForm(request.POST)
if form.is_valid():
label = form.save(commit=False)
label.issue = issue
label.project = project
label.save()
return redirect('project:issue_tracker:issue_detail', project_id=project.id, issue_id=issue.id)
else:
form = LabelForm()
template = 'issue_tracker/issue/label.html'
context = {'form': form, 'project': project}
return render(request, template, context)
Notice the label.project = project
I'm doing a multi step form where everything is saved at the end. In my models I have a m2m checkbox field and I'm using django Sessions to grab the forms datas to show it on the final step.
The issue is that the m2m field (checkboxes) is not saved when I submit the final form.
Here is my views file :
views.py
def step1(request):
initial={'name': request.session.get('name', None), 'checkbox': request.session.get('checkbox', (False,))} #cookies
form = FormOneForm(request.POST or None, initial=initial)
if request.method == 'POST':
if form.is_valid():
request.session['name'] = form.cleaned_data['name']
request.session['checkbox'] = form.cleaned_data.get('checkbox')
return HttpResponseRedirect(reverse('step2'))
return render(request, 'step1.html', {'form': form})
def step2(request):
form = FormTwoForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
formtwo = form.save(commit=False)
formone2 = FormOne.objects.create(checkbox=request.session.get('checkbox')) #error is here
formone = FormOne.objects.create(name=request.session['name'])
formtwo.owner = formone
formtwo.save()
formone2.save_m2m()
return HttpResponseRedirect(reverse('step3'))
return render(request, 'step2.html', {'form': form})
models.py
class Font(models.Model):
font_name = models.CharField(max_length=100)
font_family = models.CharField(max_length=100)
font_link = models.CharField(max_length=100)
...
class FormOne(models.Model):
name = models.CharField(max_length=40)
checkbox = models.ManyToManyField(Font, blank=True)
...
class FormTwo(models.Model):
owner = models.ForeignKey(FormOne)
name = models.CharField(max_length=40)
...
this code gives me this error :
'checkbox' is an invalid keyword argument for this function
How can I achieve what I am trying to realise ?
Try to save object first:
formone2 = FormOne.objects.create(name=request.session['name'])
formone2.checkbox.add(request.session.get('checkbox')
The problem is that you need to save object before use Many-to-many relations. See docs:
You can’t associate it with a Publication until it’s been saved