Django: How to save data to ManyToManyField - django

Your help will be nice for me. Here are that codes:
models.py:
from django.db import models
class TagModel(models.Model):
tag = models.CharField(max_length=50)
def __str__(self):
return self.tag
class MyModel(models.Model):
title = models.CharField(max_length=50)
tag = models.ManyToManyField(TagModel)
forms.py:
from django import forms
from .models import *
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
fields = '__all__'
views.py:
from django.shortcuts import render, get_object_or_404, redirect
from .models import *
from .forms import *
def MyWriteView(request):
if request.method == "POST":
mywriteform = MyForm(request.POST)
if mywriteform.is_valid():
confirmform = mywriteform.save(commit=False)
confirmform.save()
return redirect('MyDetail', pk=confirmform.pk)
else:
mywriteform = MyForm()
return render(request, 'form.html', {'mywriteform': mywriteform})
form.html(1st trial):
<form method="post">
{% csrf_token %}
{{ mywriteform }}
<button type="submit">Save</button>
</form>
form.html(2nd trial):
<form method="post">
{% csrf_token %}
{{ mywriteform.title }}
<select name="tags" required="" id="id_tags" multiple="">
{% for taglist in mywriteform.tags %}
<option value="{{taglist.id}}">{{taglist}}</option>
{% endfor %}
</select>
<button type="submit">Save</button>
</form>
I am trying to add tags on my post. I made a simple manytomany tagging blog but it does not work. I submitted a post by clicking the save button, and the title was saved, but the tag was not. In the admin, it worked well.
Thank you in advance.

update the code like this
if mywriteform.is_valid():
confirmform = mywriteform.save(commit=False)
confirmform.save()
mywriteform.save_m2m()
return redirect('MyDetail', pk=confirmform.pk)
for more details Refer here

Related

I have created a django ModelForm that is not showing up in my html template, I am trying to determine why that code is not rendering my form?

models.py
from django.db import models
# Create your models here.
class Subscriber(models.Model):
"""A subscriber Model"""
email = models.CharField(max_length=255, blank=False, null=False, help_text="Subscriber Email Address", unique=True)
full_name = models.CharField(max_length=100, blank=False, null=False, help_text="First and Last Name")
class Meta:
verbose_name = "Subscriber"
verbose_name_plural = "Subscribers"
forms.py
from django.forms import ModelForm
from .models import Subscriber
class SubscriberForm(ModelForm):
class Meta:
model = Subscriber
fields = ["email", "full_name"]
views.py
from django.shortcuts import render
from .forms import SubscriberForm
from django.http import HttpResponseRedirect
from django.contrib import messages
# Create your views here.
def subscriber(request):
if request.method == "POST":
subscriber_form = SubscriberForm(request.POST or None)
if subscriber_form.is_valid():
subscriber_form.save()
messages.success(request, "")
return HttpResponseRedirect("/")
else:
subscriber_form = SubscriberForm()
context = {
"form_subscriber": subscriber_form
}
return render(request, "subscriber/subscriber_form.html", context)
subscriber_form.html
{% block content %}
<div>
<form method="POST">
{% csrf_token %}
{{ subscriber_form.as_ul }}
<input type="submit" value="Submit">
</form>
</div>
{% endblock %}
Only my submit button is publishing, however the form is never showing up for me.
I have followed the django docs exactly and still am not getting any good results.
It should be form_subscriber not subscriber_form so:
{% block content %}
<div>
<form method="POST">
{% csrf_token %}
{{ form_subscriber.as_ul }}
<input type="submit" value="Submit">
</form>
</div>
{% endblock %}
Additionally, I'd recommend you to only use SubscriberForm(request.POST) in views without using None for GET request as it is already being handled in else condition so:
views.py:
def subscriber(request):
if request.method == "POST":
subscriber_form = SubscriberForm(request.POST)
...

Model Form not displaying

So I created a model form but it's not showing in the page but it's registered on the django admin site.views.py[forms.py
(https://i.stack.imgur.com/Z3qud.png)models.py
the error I keep getting
I tried creating the models using django shell
views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import AttendeeForm
# Create your views here.
def attendees_reg(request):
form = AttendeeForm()
if request.method == 'POST':
form = AttendeeForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Data Has been Saved')
return redirect('/attendees')
return render(request, "templates/attendees_reg.html", {'form':form})
forms.py
from django.forms import ModelForm
from .models import Attendee
class AttendeeForm(ModelForm):
class Meta:
model = Attendee
fields = "all"
template
</h1> <hr>
{% for message in messages %}
<p>{{message}}</p>
{% endfor %}
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
You need to be correct "__all__" instead of "all"
class AttendeeForm(ModelForm):
class Meta:
model = Attendee
fields = "__all__"

Bootstrap 4 select form field isn't working with django

I am new to django and using bootstrap4 form with django. When I use input field text and date it works fine and save data into django admin but if I add Select for categories, it doesn't work and returns following error:
ValueError at /
The view app_budgetlist.views.home didn't return an HttpResponse object. It returned None instead.
I worked for 2 straight days and couldn't figure out what's wrong! Can you help please?
[N.B. Updated the code as #Caleb Goodman told still no luck]
Here is my code:
models.py
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class MonthlyBudget(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
budget_amount = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
forms.py
from django import forms
from .models import MonthlyBudget
class MonthlyBudgetForm(forms.ModelForm):
class Meta:
model = MonthlyBudget
fields = ['category', 'budget_amount']
view.py
from django.shortcuts import render, redirect
from .models import Category, MonthlyBudget
from .forms import MonthlyBudgetForm
def home(request):
project = MonthlyBudget.objects.all()
categories = Category.objects.all()
if request.method == "POST":
form = MonthlyBudgetForm(request.POST or None)
if form.is_valid():
form.save()
return render(request, 'home.html', {'project':project, 'categories':categories})
else:
return render(request, 'home.html', {'project':project, 'categories':categories})
home.html
<form class="form-inline" method="POST">
{% csrf_token %}
<input type="text" name="budget_amount" class="form-control mb-2 mr-sm-2" id="budget-amount" placeholder="Amount">
<div class="form-group">
<label for="category">Select Category</label>
<select id="category" class="taskCategory" name="category">
<option class="disabled" value="">Choose a category</option>
{% for category in categories %}
<option class="" value="{{ category.name }}" name="{{ category.name }}">{{ category.name }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-primary mb-2">Add Project</button>
</form>
admin.py
from django.contrib import admin
from .models import MonthlyBudget, Category
admin.site.register(MonthlyBudget)
admin.site.register(Category)
You forgot to return a response after you save the form:
def home(request):
project = MonthlyBudget.objects.all()
categories = Category.objects.all()
if request.method == "POST":
form = MonthlyBudgetForm(request.POST or None)
if form.is_valid():
form.save()
return render(request, 'home.html', {'project':project, 'categories':categories})
else:
return render(request, 'home.html', {'project':project, 'categories':categories})

forms field not loading

I have designed a model in Django and a form according to it. The below are the both files.
models.py
from django.db import models
class TotalEvent(models.Model):
CustomerID = models.CharField(max_length=30)
eventID = models.CharField(max_length=100)
eventPlace = models.CharField(max_length=100)
eventStartTime = models.TimeField(auto_now=False)
eventDate = models.DateField(auto_now=False)
forms.py
from django import forms
from django.forms import ModelForm
from catering.models import TotalEvent
class TotalEventForm(ModelForm):
class Meta:
model = TotalEvent
fields = '__all__'
Now, When in my html file I tried this:
{% extends "base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}
<h1>Detail page</h1>
<p>Enter your schedule details here</p>
<form method="post">{% csrf_token %}
{% for field in forms %}
{{field}}
<input type="submit" value="Submit"/>
{% endfor %}
</form>
{% endblock %}
views.py
from django.shortcuts import render
from catering.forms import TotalEvent
def add(request):
if request.method == 'POST':
form = TotalEvent(request.POST)
if form.is_valid():
form.save()
return render(request, 'index.html', { 'form': TotalEvent()
})
In the output it shows no input fields except the following output
Enter your schedule details here
Please have a look and let me know where is the error.
Use TotalEventForm instead TotalEvent as TotalEvent is model class not form class, update your views.py
def add(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = TotalEventForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = TotalEventForm()
return render(request, 'index.html', {'form': form})
and you can use form directly in your html file.
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit"/>
</form>
type
{% for field in form %}
instead of
{% for field in forms %}

Django - how to transfer user input from views.py to models.py?

I am trying to create a Django app that allows a user to select a file name from a drop down menu and upload the file. Regardless of what the user has named their file, I will receive that file saved as whatever they selected on the drop down plus the date. I cannot seem to get my drop downs to show. Hours of reading the documentation, multiple stack overflow posts, and trial and error have not helped. * Does anyone know how to get the user-selected drop down value from views.py to models.py to be inserted into the uploaded file's path? *
On another note, I am sure there are other issues with my code, being a Django newb, so please point them out if you see them.
models.py
from django.db import models
from datetime import datetime
import os
def update_filename(instance, filename):
path = "documents/"
format = '{0}_{1}.csv'.format(vc, datetime.today().strftime('%Y%m%d'))
#note that vc is defined in views.py but I am not sure how to transfer this to models.py
#*************************************************************
return os.path.join(path, format)
class Document(models.Model):
docfile = models.FileField(upload_to= update_filename) #/%Y/%m/%d')
#value_chains = (('coffee', 'coffee'),('tea', 'tea'),)
dropdown = models.CharField(max_length=20, choices=(('coffee', 'coffee'),('tea', 'tea'),))
forms.py
from django import forms
from .models import Document
def validate_file_extension(value):
if not value.name.endswith('.csv'):
raise forms.ValidationError("Only CSV file is accepted")
class DocumentForm(forms.ModelForm):
docfile = forms.FileField(label='Select a file', validators=[validate_file_extension])
value_chains = (('coffee', 'coffee'),('tea', 'tea'),)
dropdown = forms.ChoiceField(choices=value_chains, required=True)
class Meta:
model = Document
fields = ['dropdown']
views.py
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views.generic.edit import CreateView
from .models import Document
from .forms import DocumentForm
def list(request):
# Handle file upload
if request.method == 'POST':
#bind the data to the form
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
#**** vc is defined here ************************************
vc = form.cleaned_data['dropdown']
newdoc = Document(docfile = request.FILES['docfile'])
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('file_upload_app.views.list'))
# if a GET (or any other method) we'll create a blank form:
else:
form = DocumentForm() # A empty, unbound form. This is what we can expect to happen the first time we visit the URL.
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render_to_response(
'file_upload_app/list.html',
{'documents': documents, 'form': form},
context_instance=RequestContext(request)
)
list.html
<form action="{% url "list" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.dropdown }}
<p>
<h6>
Note: the uploaded file must be in
<b>.CSV</b>
format and contain a column labeled "A" which contains
<em>only</em>
numbers.
</h6>
</p>
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile.errors }}
{{ form.docfile }}
</p>
<p><input type="submit" value="Upload"/></p>
</form>
<!-- List of uploaded documents -->
<p>
{% if documents %}
<div class="col-sm-12" align="center" >
<ul>
<p>Files on server:</p>
{% for document in documents %}
<li>{{ document.docfile.name }}</li>
{% endfor %}
</ul>
</div>
{% else %}
<div class="col-sm-12" align="center" >
<p>No documents.</p>
</div>
I recommend you use Djano's CreateView for your view. In your case you would have
Class UploadDocumentView(CreateView):
model = Document
When you click submit on your form, and you have the action pointing to the correct view, it will create a new Document with the fields you provided.
Your template should have this in it, the url should be the name you gave your url. I recommend against using "list" as your url because that is a special name in python and Django has it's own concept of ListView.
<form id="upload_document" method="POST" action="{% url 'document:upload' %}">
{{ form }}
<input class="btn btn-primary" id="upload_document_button" type="submit" value="Upload Document"/>
</form>
Sometimes seeing a working example is useful. The one below uses Django's UpdateView. The UpdateView will use the get_object method to determine which object in the database to modify. It knows what model to look at because it is set to model = UserProfile, and it knows what values to save because you set them in your form.
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
primary_key=True)
company_identifier = models.CharField(max_length=5, blank=False)
employee_id = models.CharField(max_length=20, null=True, blank=False)
forms.py
def get_company_choices():
company_list = [('','-------')]
companies = models.Company.objects.values_list('id', 'name').order_by('name')
company_list = list(chain(company_list, companies))
return company_list
class EmployerForm(forms.ModelForm):
employee_id_confirm = forms.CharField(label="Confirm Employee ID", required=True)
company_identifier = forms.ChoiceField(choices=get_company_choices, label="Company")
class Meta:
model = models.UserProfile
fields = ('company_identifier', 'employee_id')
labels = {
'employee_id': "Employee ID",
}
views.py
#method_decorator(login_required, name='dispatch')
class EmploymentUpdate(SuccessMessageMixin, UpdateView):
model = UserProfile
template_name = 'employee/update_employment.html'
form_class = forms.EmployerForm
success_url = reverse_lazy('employee:home')
success_message = "Employment Updated."
def get_object(self):
return self.model.objects.get(pk=self.request.user.userprofile.pk)
I found the solution, denoted by the **** below:
models.py:
from django.db import models
from datetime import datetime
import os
value_chains = (
('coffee', 'coffee'),
('tea', 'tea'),
)
def update_filename(instance, filename):
path = "documents/"
#*************************************************************
#use instance to access the instance of Document's CharField function, which is defined below
format = '{0}_{1}.csv'.format(instance.dropdown, datetime.today().strftime('%Y%m%d'))
#*************************************************************
return os.path.join(path, format)
class Document(models.Model):
docfile = models.FileField(upload_to= update_filename)
dropdown = models.CharField(max_length=20, choices=value_chains)
class Meta:
permissions = (("access_file_upload_app", "Access file upload tool."),)
views.py:
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from django.conf import settings
from .models import Document
from .forms import DocumentForm
#login_required
def doc_upload_view(request):
if request.user.has_perm('file_upload_app.access_file_upload_app') and settings.VC_ENABLED == 'Y':
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
#********************************************************
# make sure to pass the dropdown value to the Document call:
newdoc = Document(docfile = request.FILES['docfile'], dropdown = form.cleaned_data['dropdown'])
#********************************************************
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('file_upload_app.views.doc_upload_view'))
else:
form = DocumentForm() # An empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render_to_response(
'file_upload_app/doc_upload_view.html',
{'documents': documents, 'form': form},
context_instance=RequestContext(request)
)
else:
return redirect('/home/')
forms.py:
from django import forms
from .models import Document
def validate_file_extension(value):
if not value.name.endswith('.csv'):
raise forms.ValidationError("Only CSV file is accepted")
class DocumentForm(forms.ModelForm):
value_chains = (('coffee', 'coffee'),('tea', 'tea'),)
docfile = forms.FileField(label='Select a file', validators=[validate_file_extension])
dropdown = forms.ChoiceField(choices=value_chains, required=True )
class Meta:
model = Document
fields = ('dropdown',)
doc_upload_view.html:
<!-- Upload form. Note enctype attribute! -->
<form action="{% url "doc_upload_view" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.dropdown }}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile.errors }}
{{ form.docfile }}
</p>
<p><input type="submit" value="Upload"/></p>
</form>
<!-- List of uploaded documents -->
<p class="top-space">
{% if documents %}
<div class="col-sm-12" align="center" >
<ul>
<p>Files on server:</p>
{% for document in documents %}
<li>{{ document.docfile.name }}</li>
{% endfor %}
</ul>
</div>
{% else %}
<div class="col-sm-12" align="center" >
<p>No documents.</p>
</div>
{% endif %}
</p>