Django - CreateView form on existing view and url - python

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.

Related

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

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

Control requests to view and template output in django

This is a view for get all the records in the EducationalRecord model:
def all_education_resume(request):
RESUME_INFO['view'] = 'education'
educations_resume = EducationalRecord.objects.all().order_by('-created_date')
template = 'resumes/all_resume.html'
context = {'educations_resume': educations_resume, 'resume_info': RESUME_INFO}
return render(request, template, context)
Now, if I want to write exactly this view for other models (like job resumes, research resumes , etc.),
I must another view one separately.
My question is:
How can I get a view for all these requests, so first check the URL of
the request and then do the relevant query? How can I control URL
requests in my views?
My other question is exactly the same as my first question,with this difference:
control view that must render in specific template.In other words,in
second question the ratio between the template and the view is instead
of the ratio of the view to the url or how to create a template for
multiple views (for example, for a variety of database resume
resumes, I have a template) and then, depending on which view render,
the template output is different.
I have implemented these two issues as follows:
I wrote a view for each of request!
In each view, I set the value of RESUME_INFO['view'], and then I've checked it in a template page and specified the corresponding template.
What is the best solution to these two questions?
How can I get a view for all these requests, so first check the URL of the request and then do the relevant query? How can I control URL requests in my views?
You can access request.path, or you can let the url(..)s pass a parameter with kwargs that holds a reference to the model for example, but this is usually bad design. Typically if you use different models, you will likely have to order these different as well, filter these differently, render these differently, etc. If not, then this typically indicates that something is wrong with the modeling.
You can however make use of class-based views [Django-doc], to remove as much boilerplate as posssible. Your view looks like a ListView [Django-doc], by using such view, and patching where necessary, we can omit most of the "boilerplate" code:
# app/views.py
from django.views.generic.list import ListView
class MyBaseListView(ListView):
resume_info = None
template = 'resumes/all_resume.html'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['resume_info'] = {'view': self.resume_info}
return context
In the individual listviews, you then only need to specify the resume_info and the model or queryset to render it with the 'all_resume.html' template, for example:
# app/views.py
# ...
class EducationalResumeView(MyBaseListView):
queryset = EducationalRecord.objects.order_by('-created_date')
resume_info = 'education'
class OtherModelView(MyBaseListView):
model = OtherModel
resume_info = 'other_info'
So we can here use inheritance to define common things only once, and use it in multiple views. In case we need to change something in a specific view, we can override it at that level.
In the urls.py, you define such view with the .as_view() method [Django-doc]. For example:
# app/urls.py
from django.urls import path
from app.views import EducationalResumeView, OtherModelView
urlpatterns = [
path('education/', EducationalResumeView.as_view()),
path('other/', OtherModelView.as_view()),
]

Saving a Form to a Database (Django Python)

In my Django app I have a form with an email and a text area that needs to go into the database but am struggeling to do so. At the moment I have 2 different solutions in my code:
OK, let me write this from the beginning. Maybe it is better if you do the below steps with me now for an exercise.
Now, the correct way to do the above task (I try to clear this subject a little more because I know that many other people will read this problem and they can learn from this too. And it is important to understand it for your future tasks.
If you want to create a Form and you know that you will want to save the submitted data from that Form to the database, then of course you should start the whole task with creating a Model, thus a table for that in the database.
So, first you create a Model (which you will call ie. “Questions” in this case, since you want to call your Form ie. QuestionForm, so it is better if your Model and table will be related to that with their names too).
So your Model will be in your models.py file:
from django.db import models
# Create your models here.
class Questions(models.Model):
contact_email = models.EmailField(max_length=60)
question = models.CharField(max_length=600)
Then you will create a ModelForm from this in your forms.py file the following way:
from django import forms
from django.forms import ModelForm, Textarea
from . import models
class QuestionForm(ModelForm):
class Meta:
model = models.Questions
fields = ['contact_email', 'question']
widgets = {
'question': Textarea(attrs={'cols': 40, 'rows': 20}),
}
Then you create your view function in your views.py file:
from django.shortcuts import render, redirect
from . import forms
from . import models
from django.http import HttpResponse
def get_question(request):
form = forms.QuestionForm()
if request.method == 'POST':
form = forms.QuestionForm(request.POST)
if form.is_valid():
form.save()
return redirect(‘success.html’) # or you redirect anywhere you want to
else:
form = forms.QuestionForm()
return render(request, 'contact.html', {'form':form})
And at this point you will create your urlpattern in your urls.py to call the get_question view function. It will look like the following:
from django.conf.urls import url
from basic_app import views
# app_name = 'basic_app' # Important for referencing urls in HTML pages(use your own app_name here). But for this example task this is not important.
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^questions/', views.get_question, name="questions_page"),
]
I hope I did not confuse you more. If you do the above steps, it should work for you. And you can create as many Forms as you want with the above steps and saving them easily in the Database.
The only other thing you have to have to run the above, is your 'contact.html' page which you already have and you already created.
(do not forget to run: python manage.py migrate)
So, I hope that you see, in the above example you do not mismatch fields and field names, and you do not get confused about what to save where. Since the Model and the Form is working together and created together with the same field names.

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.

Convert the Django direct_to_template function to use class based view

I am updating a Django project which used the direct_to_template as a function ie:
return direct_to_template(request, 'bprofile/init.html', targs)
As described a short way down this page
I have seen the SO question here and read the documentation on this page which decribe the migration of statements of the form
('^about/$', direct_to_template, {'template': 'about.html'})
to look like
('^about/$', TemplateView.as_view(template_name='about.html'))
Unfortunatelty I cannot seem to figure out how to change statements from the form that I have into a working new form.
How might one modify this code to work with the new Templateview form?
You shouldn't be using the generic views for this, that's not what they are for. If you want to render a template, you should use the render shortcut: it takes exactly the same arguments.
return render(request, 'bprofile/init.html', targs)
To use TemplateView you import TemplateView into your urls.py:
from django.views.generic.base import TemplateView
Then you just add the urlconf:
('^about/$', TemplateView.as_view(template_name='bprofile/init.html'))

Categories

Resources