I have a simple site project in Django and I have movies lists in man page and movies details in the second page.
I want to add a delete button on movies details tab where user can delete the movies object.
views.py
def movies_list(request):
return render(request, 'movies.html',{'movies':movies.objects.all()})
def movies_details(request,slug):
movies_details=MyModel.objects.all()
det=get_object_or_404(movies_details, slug_name=slug)
return render(request, 'movies_details.html',{'movies_details':movies_details,'det':det})
what is the better method to do that ?
something like this using new view :
def delete(request, id):
note = get_object_or_404(Note, pk=id).delete()
return HttpResponseRedirect(reverse('movies_details.views.movies_details'))
urls.py
url(r'^delete/(?P<id>\d+)/$','project.app.views.delete'),
or some like this ?
if request.POST.get('delete'):
obj.delete()
or use some Django form ?
You can use DeleteView functionality of django. I think that will be the better one.
from django.views.generic.edit import DeleteView
from django.urls import reverse_lazy
class DeleteTaskView(DeleteView):
template_name = 'template/delete.html'
model = Task
pk_url_kwarg = 'id'
def get_success_url(self):
return reverse_lazy('movies_details.views.movies_details')
Related
Im trying to create a extra view in django admin, on the left navbar. This view will be responsible for uploading a file, which will be parsed in some function (in future i would like to render result of this parsing in admin page). This file wont be saved in database, so there wont be a model. Is there any possibility to add a view to django admin (left navbar) which dont have a model? I was reading a lot, and could find a solution. What i have done for now:
Created a class which inherits from AdminSite. I tried to implement get_app_list method, but variable self._build_app_dict(request) was empty array, and this means, method couldn't find a installed aps. I wanted to add new object to app_list variable, to render it on website.
Tried to override a admin templates, but couldnt render it. I tried to override app_index.html which i put on folder: app_name/templates/admin/app_index.html
Here is my code, which ofc doesnt work:
class MyCustomAdmin(AdminSite):
def get_app_list(self, request):
"""
Return a sorted list of all the installed apps that have been
registered in this site.
"""
app_dict = self._build_app_dict(request)
breakpoint()
app_list = sorted(app_dict.values(), key=lambda x: x['name'].lower())
for app in app_list:
app['models'].sort(key=lambda x: x['name'])
return app_list
def get_urls(self):
from django.conf.urls import url
urls = super(MyCustomAdmin, self).get_urls()
urls += [
url(r'^my_custom_view/$', self.admin_view(MyCustomView.as_view()))
]
return urls
class MyCustomView(View):
template_name = 'admin/app_index.html'
def get(self, request):
print('fefef')
return render(request, self.template_name, {})
def post(self, request):
pass
admin_site = MyCustomAdmin()
admin_site.get_app_list(AdminSite.get_app_list)
Here is my code that I believe pertains to this situation. I'm sorry, I'm new to django.
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import SearchForm
def result_one(request):
return render(request, "testresult.html", {})
def get_results(request):
if request.method == 'POST':
form = SearchForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/result/')
else:
form = SearchForm()
return render(request, 'index.html', {'form': form})
urls.py
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^search/$', "search.views.get_results"),
url(r'^result/$', "search.views.result_one"),
]
forms.py
from django import forms
class SearchForm(forms.Form):
client_group_number=forms.IntegerField(label='Group Number', widget=forms.TextInput(attrs={'placeholder': 'Group Number'}))
From my understanding, what I believe should happen is that an input will be put into a html page. When the user hits submit, the input gets saved into forms.py as data. This data gets manipulated in views.py which gets displayed in a different html page. (I hope this is correct)
What I want it to do is take in an input for client_group_number(in forms.py) from index.html(for example: 123), that can be accessed in views.py and displayed in another html template that I have called testresult.html, which would display Group Number = 123 (the 123 coming from either the forms.py or views.py).
This might be a very simple thing to accomplish and I apologize if it is, but I can't seem to find what I need on the internet.
Django validate the form input data in the cleaned_data dictionary. You would need to pass this to the new template either as arguments in the redirect or using session. Here is one simple example to give you an idea, there are probably better ways.
if form.is_valid():
group_number = form.cleaned_data["client_group_number"]
HttpResponseRedirect("/result/?group_number=" + group_number)
I am asking user to fill extra fields with custom form. And in one of the fields, I have to let user choose multiple hierarchical tags. For this, I need to pass the tags from a view to the template signup.html
from classes.Tags import Tags
from django.shortcuts import render_to_response
from allauth.socialaccount import views as signup_views
def signup_view(request):
tags = Tags()
parameters={}
all_tags = tags.get_tags()
parameters['all_tags'] = all_tags
response = signup_views.signup(request)
return response
And in urls.py, I added this line before the allauth urls include line.
url(r'^accounts/social/signup/', 'mainapp.signup_views.signup_view', name = 'account_signup'),
url(r'^accounts/', include('allauth.urls')),
What I need is that I need to add all_tags to the response so that I can access it from the template. How do I do that?
This link has some details on using your own signup form. IMO, you can define your own form (eventually with a custom widget for the tags) and use it directly, without having to mess with the view.
Otherwise, #PauloAlmeida is correct. You could inherit a new class off SignupView with something like:
class MySignupView(SignupView):
def get_context_data(self, **kwargs):
ret = super(MySignupView, self).get_context_data(**kwargs)
ret['all_tags'] = Tags.get_tags()
return ret
I'd rather use the custom form approach as it won't mess up the urls.py.
I am fairly new to Django and class based forms, and I am having trouble understanding how these interact with each other. Following from the django project example, I have tried to build a "search form", which would sit on all pages of my project:
# forms.py
from django import forms
class SearchForm(forms.Form):
myquery = forms.CharField(max_length=255,label="", help_text="sq")
def __unicode__(self):
return self.myquery
# views.py
from searchapp.forms import SearchForm
from django.views.generic.edit import FormView
from django.views.generic import TemplateView
class SearchView(FormView):
template_name = 'index.html'
form_class = SearchForm
success_url = '/searchres/'
def form_valid(self, form):
thequery=form.cleaned_data.get('myquery')
return super(SearchView, self).form_valid(form)
class Meta:
abstract = True
class SearchResView(SearchView):
template_name = 'searchres.html'
#urls.py
from django.conf.urls import patterns, include, url
from django.conf import settings
from deals.views import IndexView
from searchapp.views import SearchView, SearchResView
urlpatterns = patterns('',
url(r'^index/', SearchView.as_view(),name="home"),
url(r'^searchres/', SearchResView.as_view(),name="searchresx"),
)
The plan is the start off with a simple form for user to enter the search query, and also show the input form on the results page. I have the following questions here (sorry - I am a Django newbie esp. to Class Based Views):
How does one pass data ("thequery") to the success_url? i.e I would like success_url to have access to "thequery" so that I can use something like {{thequery}} on my template tags.
Upon submitting the form(name="home"), I see POST data from the form on my firebug, but I am able to see just "myquery" rather than "thequery". How does one use get_context_data() here to add/post "thequery" variable aswell?
Finally, I was wondering if it would be possible to construct the success_url based on "thequery" string i.e something like success_url = '/searchres/?q=' + thequery
Thank you in advance - I am hoping to learn more.
I would suggest using function based views for this. If you choose to subclass a generic view you will need to dig through a lot of documentation and possibly source code, to find the right methods to override. (If you're really keen then look at the ListView class along with the get_queryset(), get() and post() methods)
A single django view will normally handle both rendering the empty form AND processing the submitted form.
So the search page (both the form and the results), live at http://your-site.com/search. Your url conf is -
urlpatterns = patterns('',
#...
(r'^search/$', 'searchapp.views.search'),
)
And your view looks something like this -
def search(request):
if request.method == 'POST':
form = SearchForm(request.POST)
if form.is_valid():
my_query = form.cleaned_data['myquery']
object_list = YourModel.objects.filter(# some operation involving my_query)
return render_to_response('search_results.html', {'object_list': object_list})
else:
form = SearchForm()
render_to_response('search_form.html', {'form': form})
(Note I've assumed your form method is post rather than get - I know this isn't great http but it's a common pattern with django)
To respond to your questions -
Don't use your own method for cleaning data. Add a clean_myquery method to your form and access it with form.fields['myquery'].clean() (or if you've called is_valid() on your form, it's accessible with just form.cleaned_data['myquery']).
You want to try and avoid passing data for processing to the template. Do as much processing as you can in the view, then render the template. However if you want to pass myquery as a string for the template to render, then add it in to the context dictionary (the second non-key-word argument) in render_to_response -
return render_to_response('search.html', {'object_list': object_list, 'myquery': my query})
The post data is constructed from the form fields. You don't have a form field thequery. The view is processing the POST data - it's not creating it that's done by the html (which in turn is constructed by the Form class). Your variable thequery is declared in the view.
Django's URL dispatcher ignores query strings in the URL so http://your_site.com/ssearch will be processed by the same view as http://your_site.com/search?myquery=findstuff. Simply change the html in the template from <form method='post'> to and access the data in django with request.GET. (You'll need to change the code from the view I described above to include a new check to see whether you're dealing with a form submission or just rendering a blank form)
Have a good read of the docs on views, forms and the url dispatcher.
I'm running Django 1.2.1 for my personal website with a blog. It's all fine and dandy, but I've found that all the browsers I've tried (Firefox, Chromium, Opera) are caching webpages, which of course is a problem for other users viewing my blog (being that it won't load new posts up unless they empty their cache or force refresh the page). I didn't have this problem when my site ran on PHP, so how would I go about fixing this seemingly Django-related problem?
I've only been working with Django for about a week or so, so I don't really know where abouts I should be looking to fix something like this. Thanks in advance!
The way I do each page (and each blog post) is as a Page/Post object respectively so I can use the admin interface without having to write my own. Although the issue is happening for both situations, I'll just give the Post class for now:
class Post(models.Model):
author = models.ForeignKey(User, default=User.objects.get(username='nathan'))
status = models.ForeignKey(Status, default=Status.objects.get(text='Draft'))
date = models.DateTimeField(default=datetime.datetime.now())
title = models.CharField(max_length=100)
post = models.TextField()
categories = models.ManyToManyField(Category)
def __unicode__(self):
return u'%s' % self.title
def link(self):
return u'/blog/post/%s' % self.title
class Meta:
ordering = ['-date']
And here's my urls.py:
from django.conf.urls.defaults import *
from django.views.generic import list_detail
from feeds import PostFeed
from models import Post
blog_posts = {
'queryset': Post.objects.filter(status__text__exact='Published'),
}
urlpatterns = patterns('getoffmalawn.blog.views',
(r'^$', list_detail.object_list, blog_posts),
(r'^archive/(\d{4})$', 'archive'),
(r'^rss/$', PostFeed()),
(r'^search/$', 'search'),
(r'^tag/(.+)/$', 'tag'),
(r'^post/(.+)/$', 'post'),
)
If you guys would like to see the code from views.py, just ask and I'll throw that up too.
Edit:
Here's the views.
view.py for the blog App:
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, redirect
from django.core.context_processors import csrf
from django.db.models import Q
from models import Post, Category
def post(request, title):
post = Post.objects.get(title=title)
c = locals()
c.update(csrf(request))
return render_to_response('blog/post_detail.html', c)
def blog_detail(request, blog_id):
post = get_object_or_404(Post, pk=blog_id)
return list_detail.object_detail(request, queryset=Post.objects.all(), object_id=blog_id)
def archive(request, month, year):
pass
def search(request):
if request.method == 'GET':
query = request.GET['q']
object_list = Post.objects.filter(Q(post__icontains=query) | Q(title__icontains=query), status__text__exact='Published')
return render_to_response('blog/post_list_sparse.html', locals())
def tag(request, tag):
object_list = Post.objects.filter(categories__text__exact=tag, status__text__exact='Published')
return render_to_response('blog/post_list.html', locals())
The problem was that it really was browser-based caching, as I was told by a member on the Django-users mailing list. The reason I didn't see this problem in PHP is that it was sending cache suppression headers.
The solution was to add the #never_cache decorator to the relevant views.
Here is the documentation for caching in django.
https://docs.djangoproject.com/en/1.2/topics/cache/
Not ideal, but you can make all of the pages tell the browsers not to cache anything, to see if that helps.
https://docs.djangoproject.com/en/1.2/topics/cache/#controlling-cache-using-other-headers