How Do I Have Multiple ModelForms In Django in A SingleView? - python

I am trying to create A Project where I Have A model Form Which Takes A set of data as Input.
However that is not an issue, How Do I Have Multiple Forms of that One single Model Form .
I tried Using something like this
from .forms import BookForm
# Create your views here.
def home_page(request):
context = {}
form = BookForm(request.POST or None)
form1 = BookForm(request.POST or None)
if form.is_valid():
form.save()
if form1.is_valid():
form1.save()
context['form']= form
context['form1']= form1
return render(request, "home.html", context)
But What Happens is the Data passed in the last form is passed in all of the forms.
How Do I Implement this in Django Handling multiple forms in single view, which gets submitted on click of a button

You can use formsets in django.
Since you are using a model form, you can use something known as model formsets using something known as modelformset_factory.
Basically formsets help you in having a list of forms. Imagine your single form now turned into a list of forms.
Checkout this link for a tutorial
Let me know if you want more explanation

Related

in Django, how to implement CreateView's function with based-function views?

here is based-class views code:
# views.py
class ObjectCreate(CreateView):
model = ObjectModel
fields = "__all__"
its simple to create an object and save it use this class.
I wonder how?
what if I want to use based-function views to achieve it?
Using a function view you would need to implement everything, including creating a form for your model:
def create_object(request):
if request.method == 'GET':
form = ObjectForm()
if request.method == 'POST':
form = ObjectForm(request.POST)
if form.is_valid():
instance = form.save() # instance created
# now redirect user or render a success template
return redirect(...)
# if request method is GET or form is invalid return the form
return render(request, 'path/template_name.html', {'form': form})
If you want to learn how the CreateView works, look at its source code. Or for easier overview of the structure, look at this site which lists all the Django CBVs.
You'll find that CreateView inherits from 9 other classes, has about 20 attributes (of which model and fields) and 24 methods that you can override to customise its behaviour.

How to Redirect Form Submissions to Another View

I have the following django form, which will be used by users to input a query and select a model to search that particular query:
from django import forms
class search_forms(forms.Form):
search_query = forms.CharField(label='search_query')
path_choices = [('urlpath1/','model name 1'),
('urlpath2/','model name 2')...]
model_paths = forms.ChoiceField(label='model_paths',choices=path_choices)
This form is used to populate a template which consists of a input field of text for for users to submit queries, and a drop down field which identifies which model the query should be directed to (the path_choices variable in forms.py).
Thew views.py is as follows, which needs to change to the following somehow:
def search(request):
if request.method == 'GET':
form = search_forms(request.GET)
if form.is_valid():
return render(request, 'template_for_model_paths.html', {'form': form, 's_results': s_results})
else:
form = search_forms()
return render(request, 'search.html', {'form': form,})
Currently, the form template yields a GET result as follows: /search?search_query=QUERY&model_paths=model_path%2F
What I would like to accomplish is: model_path/Query as the result, which I can feed back to the view for the search form and use it to redirect the view relevant for model_path.
How should I accomplish this? Does this approach make sense? Or am I misapplying the intent of the form functionality?

merging a view with template view django

I want that the landing page of my homepage is a form with an input and the user puts in stuff. So I followed a couple of tutorials and now I have this:
views.py:
def create2(request):
if request.method =='POST':
form = LocationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('')
else:
form = LocationForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('location/index.html', args)
and in my urls.py:
url(r'^$', 'core.views.create2'),
which works perfectly fine, if I go to 127.0.0.1:8000 I get to index.html and when put in something in the input it gets saved in the database. However, the old part of my homepage looks like this
class LandingView(TemplateView):
model = Location
template_name="location/index.html"
def search
...
and the urls.py:
url(r'^$', core.views.LandingView.as_view(), name='index'),
which has a function search I So my question is, is there a way how I can merge the def create2 into my LandingView. I tried several things, but I am always ending up having the index.html without the input field. I also tried
def create2
...
def search
...
but didn't work.
Does anyone know how to merge that together?
EDIT
Thank you the working solution looks like this now
class Create(CreateView):
model = coremodels.Location
template_name = 'location/test.html'
fields = ['title']
def form_valid(self, form):
form.save()
return HttpResponseRedirect('')
return super(Create, self).form_valid(form)
Depending on the results you are looking for, there are multiple ways to solve this:
1. Use CreateView and UpdateView
Django already provides some classes that render a form for your model, submit it using POST, and re-render the form with errors if form validation was not successful.
Check the generic editing views documentation.
2. Override get_context_data
In LandingView, override TemplateView's get_context_data method, so that your context includes the form you are creating in create2.
3. Use FormView
If you still want to use your own defined form instead of the model form that CreateView and UpdateView generate for you, you can use FormView, which is pretty much the same as TemplateView except it also handles your form submission/errors automatically.
In any case, you can keep your search function inside the class-based view and call it from get_context_data to include its results in the template's context.

Add ManyToManyField relationship on save, and create objects if they not exist

I want to 'attach' a manytomany relationship on form submit.
The example is the classic blog tags-post relation: a post can have multiple tags related
In django-admin it works, but i can't figure how to do in views...
my code:
def add_post(request):
if request.method == 'POST':
form = PostForm(data=request.POST)
if form.is_valid():
model_instance = form.save(commit=False)
model_instance.author = request.user
newentry = model_instance.save()
#some magic needed here, this will never works
for tag in model_instance.tags.all():
t = Tag.objects.get_or_create(author=request.user, title=tag.title, slug=slugify(tag.title))
model_instance.tags.add(t)
#end of magic
return HttpResponseRedirect("/blog/")
else:
form = PostForm()
return render_to_response(
'blog/add_post.html',
{'form' : form },
context_instance=RequestContext(request))
I'm using the automatic tokenization from select2.js in the template, so i can to add tags "on the fly", but i'm not sure how to handle it with django...
newentry = model_instance.save()
The save() method on a model instance will not return anything, unlike the same method on a form. You should reuse model_instance instead of using newentry.
I'd also take a look at get_or_create() to create the tag if it doesn't exist already.
I have a blog where I have a ManyToManyField between posts and projects, and I select the projects to create a relationship to in the post form.
When you use commit=False on form.save(), you need to use form.save_m2m() after the form is saved using post.save().
This is what part of my view function looks like:
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
# This saves the project relation
form.save_m2m()
For your usage, I would try moving the model_instance.save() and form.save_m2m() after your magic.
Another thing about get_or_create() is that it returns a tuple with the object that was gotten or created, and a boolean in regards to whether it created the object. So you need to only pass model_instance.tags.add() the created object.
form = PostForm(data=request.POST)
if form.is_valid():
model_instance = form.save(commit=False)
model_instance.author = request.user
#some magic needed here, this will never works
for tag in model_instance.tags.all():
t, created = Tag.objects.get_or_create(author=request.user, title=tag.title, slug=slugify(tag.title))
model_instance.tags.add(t)
#end of magic
model_instance.save()
form.save_m2m()
As a database programmer (with a little django experience) I would argue that you should normalize your models. IE, add a third table (call it something like Post Tags) and set it up as an intermediary between posts and tags. So the relationship from Post to Post Tags would be 1:M and the relationship from Tags to Post Tags would be 1:M

Django - CreateView form on existing view and url

I'm using django generic views in my project CRUD. The CreateView class uses the following url to work:
urls.py
url(r'^create', BookCreate.as_view(model=Books, template_name='Myproj/book_create.html'), name='book_create'),
If I go the www.mywebsite.com/create the form appears just how I wanted it.
My problem is that I want to incorporate the form on another page, that already has a url, a view and a template. The url is like the one bellow:
urls.py
url(r'^author/(?P<id>[0-9]{1,})/$', author_view_handler, name='author_view'),
How can I resolve this?
The CreateView uses a ModelForm. If you want to use it also, you need to create a a Book model form yourself, something like this:
from django.forms import ModelForm
class BookModelForm(ModelForm):
pass
And then instantiate it form=BookModelForm() and pass it to the context of your author_view_handler view.
However I am not really sure why you would want to do something like that...
Update: To pass it to your view, use
from django.shortcuts import render
def author_view_handler(request):
form = BookModelForm()
return render(request, 'author_view_handler.html', {"form": form},
The above just passes the form to the author_view_handler view and does not contain any form handling code.

Categories

Resources