Views are different but rendering same template - django

i want to use slug field in both url which is
path('<slug:title>/',views.news_read,name="news_read"),
path('<slug:title>/',views.movie_read,name="movie_read"),
but both the url picking same template instead of their template i am trying to create blog site
i don't understand both the url are uniques so why django is picking wrong template
my views for both the url
def movie_read(request, title):
movie = Movie.objects.filter(urltitle=title)
if request.method == 'POST':
form = Commentform(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Thank You For Your Comment')
else:
form = Commentform()
return render(request,'movie_read.html',{'movie':movie,'form':form})
def news_read(request, title):
news = News.objects.filter(urltitle=title)
if request.method == 'POST':
form = Commentform(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Thank You For Your Comment')
else:
form = Commentform()
return render(request,'news_read.html',{'news':news,'form':form})
but i when do some change like this it work
path('<slug:title>/news',views.news_read,name="news_read"),
path('<slug:title>/movie',views.movie_read,name="movie_read"),
but this doesn't look good any idea what to do solve the issue

Django will "fire" the first path that matches the URL. This thus means that for every slug you enter, news_read will fire.
You can solve this by trying to query both models, and then decide which to use, like:
def my_view(request, title):
is_movie = Movie.objects.filter(urltitle=title).exists()
if is_movie:
return movie_read(request, title)
else:
return news_read(request, title)
def movie_read(request, title):
# …
def news_read(request, title):
# …
and then thus trigger the my_view function if it is a slug:
path('<slug:title>/', views.my_view, name='news-movie-read'),
but a more elegant solution is to simply define two non-overlapping URL patterns:
path('news/<slug:title>/', views.news_read,name='news_read'),
path('movie/<slug:title>/', views.movie_read,name='movie_read'),
This also will prevent clashes where a Movie object and a News object have both the same url_title since in that case, it will always use the movie_read view.

I seems that tou url path is the same, that is why django picking wrong view.
Try to change urls to this:
path('news/slug:title/',views.news_read,name="news_read"),
path('movies/slug:title/',views.movie_read,name="movie_read"),

Related

Create Form and update using same view in django

I am trying to use same view for creating form and updating any object.
My code is as below, I tried in many ways nothing is working, since I am excluding the shof from form and adding it after form.is_valid() it makes lot of confusion. If I update it creates new object. I have two urls one without ql (create new) and one with ql (update existing), I have a class vdview which provides v.shof which needs to applied in the f.shop in form. please help fix this,
#csrf_protect
#login_required
def addmenu(request, qs, ql=None):
v = vdview(request, qs)
ctgobj = get_object_or_404(v.shopcategs, pk=ql) if ql else None # ctgobj = ShopCtg(shop=v.shof)
if ql:
form = ShopCtgForm(instance=ctgobj) # Tried ShopCtgForm(instance=ctgobj, data=request.POST)
else:
form = ShopCtgForm(data= request.POST)
if request.method == 'POST':
if form.is_valid():
f=form.save(commit=False)
f.shop = v.shof
f.save()
#form.save_m2m()
return redirect('vendor-shop', qs) #thing='%s added' %f.name)
else:
pass
#else:
# form = ShopCtgForm()
return render(request,'vendorshop.html', {'shop':v.shof, 'shopcategs':v.shopcategs, 'form': form,
'heading':'Create New Category', 'createcateg': 'createcateg', 'pkaddmenupk':'y' } )
Use try blocks to handle both scenarios. The simplified example below will look for a given model instance pk and if it doesn't find it, will assume you want to create it. try will prevent django from throwing an error if the model instance doesn't exist. Rather, it will just return the empty model form.
It does this first to render the correct form in the template (the first try block) then again in the second try block after request.method == 'POST': to submit new data or update existing data.
Views.py
from .models import Books
from .forms import BookForm
def create_and_update_book_view(request, pk):
books = Books.objects.get(id=pk)
try: # get pre-populated form with model instance data (for update)
form = BookForm(instance=books.id)
except: # If it doesn't exist, show an empty form (for create)
form = BookForm(request.POST or None)
if request.method == 'POST':
try: # Do the same as above
form = BookForm(instance=books.id)
except: # Same as above
form = BookForm(request.POST or None)
if form.is_valid():
form.save()
return render(request, "create_and_update_book_page.html", {'form':form})

How to use form.cleaned_data django

After form.is_valid(), we get form.cleaned_data. How can i use this cleaned data on the next page.
For example, after the form page is processed we redirect the customer to next page, where I want to use the cleaned_data's info like name, contact, address..etc fields to be shown in next page.
def ind(request):
if request.method == 'POST':
form = form_name(request.POST)
if form.is_valid():
print(form.cleaned_data)
return render(request, 'app_one/abc.html', {'data': form.cleaned_data})
# form.save(commit=True)
# return render(request,'app_one/index.html')
else:
form=form_name()
return render(request,'app_one/index.html',{'form':form)
We will have a validated data after calling the form.is_valid() method. Once we have a validated data then we can use as we like.
For your case
customer details which are filled on the first page need show those details on the second page as receipt.
You can create a model named Reciept and save the details in the model for future reference. If you want these details in the other page views then simply pass the model object in context to render the details.
You can use the cleaned data like below
def ind(request):
if request.method == 'POST':
form = form_name(request.POST)
if form.is_valid():
context = {}.update(form.cleaned_data)
return render(request, 'app_one/abc.html', context)
# form.save(commit=True)
# return render(request,'app_one/index.html')
else:
form=form_name()
return render(request,'app_one/index.html',{'form':form)
Example Form:
class MyForm(forms.Form):
reciept_num = forms.CharField()
consider above form as an example
You can access the reciept_num data in template using the name reciept_num.
You can assign the cleaned_data to variables as usual for forms
e.g. your_data=form.cleaned_data['your_data']
After that, pass those variables to context.
e.g. context = {
'your_data':your_data
}
Lastly return the template.
e.g. return(request,'template.html',context=context)
At the 'template.html', use the variables as {{your_data}}.

Django filtering based on data

I'm using django to develop a web app. Right now I am trying to make a page that will initially render a blank form and all data objects of a certain model, and then once the user submits the form, will then filter the objects displayed to show those that have the desired attributes.
My form class is as follows
class AreaForm(forms.Form):
seating = forms.IntegerField(label='Seating', default=False)
whiteboards = forms.BooleanField(label='Whiteboards', default=False)
outlets = forms.IntegerField(label='Outlets', default=False)
tables = forms.IntegerField(label='Tables', default=False)
And the view for this page thus far is
def search(request):
if request.method == 'GET':
form = NameForm(request.POST)
if form.is_valid():
# do filtering logic here somehow
return render(request, 'SpotMe/search.html', {'form': form}) # ????
else:
return render(request, 'SpotMe/search.html', {}) # ????
I'm as of yet unsure how to implement the templates page. Am I headed in completely the wrong direction?
To show the form empty and do some logic when user post data, you need to pass the form to the template and it'll render empty if there is not post data.
view.py
def search(request):
form = AreaForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
# do filtering logic here somehow
return render(request, 'SpotMe/search.html', {'form': form})
search.html
.....
{{ form.as_p }}
.....
Based on your reply to my question below your original post, this is an easy solution that will show all data object of a model, and then you can use an input and submit it from a template to filter the results on the same page.
Note: Substitute MODEL for your actually model name. You don't need a form if you are looking to filter results (it is an extra, unnecessary step).
def search(request):
if request.method == 'GET':
if request.GET.get('seating_no'):
seating_no = request.GET.get('seating_no')
queryset = MODEL.objects.filter(seating=seating_no)
else:
queryset = MODEL.objects.all()
return render(request, 'SpotMe/search.html', {'queryset': queryset})
and in your SpotMe/search.html you can have a <form><input name="seating_no" /></form> and submit button that will lead to the same URL, and make the input name(s) into whatever you want to capture via request.GET.get()

Editing the form in Django

I have created a form in my app where I can take details of a suer. Now I want to create a form which can allow me to edit a form.
My urls.py:
url(r'^home/editform/(?P<userpk>[^/]+)/$', 'lexuseditform', name='lexuseditform'),)
My view.py:
#login_required
def lexuseditform(request,userpk):
if int(userpk) != request.user.pk:
return HttpResponseForbidden()
else:
form = AdultForm()
if request.method == 'POST': # If the form has been submitted...
form = AdultForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
form.save()
redirect_url = reverse('lexus/lexusedited.html')
return HttpResponseRedirect(redirect_url) # Redirect after POST
else:
form = AdultForm() # An unbound form
return render('lexus/lexuseditform.html', {'form': form})
My models.py:
class AdultForm(ModelForm):
"""
Edit Profile Information
"""
class Meta:
model = Adult
fields = ('user', 'email','fullname','created')
But i am getting an error msg:
No ReverseMatch: Reverse for 'lexuseditform' with arguments '()' and keyword arguments '{}' not found
Can't seem to solve this error. Need some help...
In you POST handling, reverse should be passed URL name not the pattern. So correct it whatever name you have given to that url.
redirect_url = reverse('lexus/lexusedited.html') <----- Incorrect.
If your urlname is 'lexusedited'
redirect_url = reverse('lexusedited')
Tip: you can directly do:
return HttpResponseRedirect(reverse('lexusedited'))

What URL patterns should I have for a multi-page signup form (using Django)?

First Post, so forgive any noob-iness -- I'm trying to create a multi-page product sign-up form. I can get the form to display and the submit button, but I can't find any examples of URL patterns for my urls.py file. I found another similar question with the following suggestions:
"You need to write a view to handle your request.(did that) You need to edit urls.py to map your quiz url to the function in views.py (trying, but failing). So when a request with that quiz url comes Django applies that view function.
When I Redirect the user to the new url is the problem. I can't seem to find an example of what the next pattern should be. Here's my urls.py code (index.html and details.html are my templates so far):
url(r'^signup/$', 'signup.views.select_product', name='select_product'),
url(r'^signup/(?P<product_id>\d+)/$', 'signup.views.subscriber_signup', name='subscriber_signup'),
#...
Here's my view code:
def select_product(request):
title = "get yourself an e-edition. wurd."
pform = ProductForm(request.POST)
if request.method == 'POST': # If the form has been submitted...
pform = ProductForm(request.POST) # A form bound to the POST data
if pform.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('signup/index.html') # Redirect after POST
else:
form = ProductForm() # An unbound form
return render_to_response('signup/index.html', {'title': title, 'pform': pform}, context_instance=RequestContext(request))
def subscriber_signup(request, product_id):
signup = Product.objects.get(id=product_id)
title = "get yourself an e-edition. wurd."
sform = SubscriberForm(request.POST)
if request.method == 'POST': # If the form has been submitted...
sform = SubscriberForm(request.POST) # A form bound to the POST data
if sform.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('signup/detail.html') # Redirect after POST
else:
sform = SubscriberForm() # An unbound form
return render_to_response('signup/detail.html', {'title': title, 'sform': sform, 'signup': signup,}, context_instance=RequestContext(request))
Or use Django's form wizard which was designed for this.
so part of the problem was I was using the (User) model in my Subscriber class, which the SubscriberForm was based. I ditched that and made a form based on a normal class with the objects defined individually.
Here's the URL patterns that eventually worked.
url(r'^signup/$', 'signup.views.select_product', name='select_product'),
url(r'^signup/(?P<product_id>\d+)/$', 'signup.views.subscriber_signup', name='subscriber_signup'),
url(r'^signup/(?P<product_id>\d+)/thankyou/$', 'signup.views.thankyou', name='thankyou'),
thanks for the responses.
Anthony