Viewing: trunk/collection/views.py

View as text-only | View History | View diff
from django.views.generic.list import ListView
from collection.models import Movie, Genre, Watchlist, Director
from django.shortcuts import get_object_or_404, render, redirect
import random
from django.views.generic.edit import CreateView, UpdateView
from collection.forms import MovieForm, UserForm
from django.views.generic.detail import DetailView
import urllib
import json
import datetime
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.mail import mail_admins
import sys
from django.http.response import HttpResponseRedirect, Http404
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from django.template.loader import get_template
from django.template.context import Context

LENGTH_STAMP = datetime.datetime(1983, 05, 10)  # This is used to determine the length of a movie title. Trivia, what date is this from?

# Placing global flash messages here to keep everything consistent.
IMDB_SUCCESS = "This movie information has just been updated from IMDb.  Hopefully I found the right movie."
IMDB_FAIL = "This movie title was not found on IMDb...  Perhaps try renaming the movie title."

class OnlyNickMixin(object):
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_staff:
            messages.error(request, "Only Nick has the powers to use this feature!")
            try:
                return HttpResponseRedirect(request.META['HTTP_REFERER'])
            except KeyError:
                return redirect('/')
        return super(OnlyNickMixin, self).dispatch(request, *args, **kwargs)

class BrowseCollection(ListView):
    model = Movie
    paginate_by = 100
    def get_queryset(self):
        self.query = ''
        qs = super(BrowseCollection, self).get_queryset().select_related()
        if 'ordering' in self.request.GET:
            self.query = '&ordering=%s' % self.request.GET.get('ordering')
            return qs.order_by(self.request.GET.get('ordering'))
        if 'startswith' in self.request.GET:
            self.query = '&startswith=%s' % self.request.GET.get('startswith')
            return qs.filter(title__startswith=self.request.GET.get('startswith'))
        return qs
    def get_context_data(self, **kwargs):
        kwargs.update({'extra_query':self.query})
        return super(BrowseCollection, self).get_context_data(**kwargs)

class BrowseGenre(ListView):
    model = Movie
    paginate_by = 100
    template_name = 'collection/genre_detail.html'
    def get_queryset(self):
        self.query = ''
        self.genre = get_object_or_404(Genre, slug=self.kwargs['slug'])
        qs = super(BrowseGenre, self).get_queryset().select_related().filter(genre=self.genre)
        if 'ordering' in self.request.GET:
            self.query = '&ordering=%s' % self.request.GET.get('ordering')
            return qs.order_by(self.request.GET.get('ordering'))
        if 'startswith' in self.request.GET:
            self.query = '&startswith=%s' % self.request.GET.get('startswith')
            return qs.filter(title__startswith=self.request.GET.get('startswith'))
        return qs
    def get_context_data(self, **kwargs):
        kwargs.update({'genre': self.genre, 'extra_query':self.query})
        return super(BrowseGenre, self).get_context_data(**kwargs)

class GenreList(ListView):
    model = Genre

class BrowseFormat(ListView):
    model = Movie
    paginate_by = 100
    template_name = 'collection/format_detail.html'
    def get_queryset(self):
        self.query = ''
        self.format = int(self.kwargs['format_id'])
        qs = super(BrowseFormat, self).get_queryset().select_related().filter(format=self.format)
        if 'ordering' in self.request.GET:
            self.query = '&ordering=%s' % self.request.GET.get('ordering')
            return qs.order_by(self.request.GET.get('ordering'))
        if 'startswith' in self.request.GET:
            self.query = '&startswith=%s' % self.request.GET.get('startswith')
            return qs.filter(title__startswith=self.request.GET.get('startswith'))
        return qs
    def get_context_data(self, **kwargs):
        kwargs.update({'format': self.format, 'extra_query':self.query})
        return super(BrowseFormat, self).get_context_data(**kwargs)

class AddMovie(OnlyNickMixin, CreateView):
    model = Movie
    form_class = MovieForm
    def form_valid(self, form):
        self.object = form.save()
        for watchlist in self.object.genre.watchlist_set.all():
            body = get_template("collection/notifications/new_movie.txt").render(Context({'user':watchlist.owner, 'movie':self.object}))
            watchlist.owner.email_user('Nick added a new %s movie' % self.object.genre, body)
        return redirect(self.object)

class MovieDetail(DetailView):
    model = Movie
    def get_object(self):
        qs = self.get_queryset()
        slug = self.kwargs.get(self.slug_url_kwarg, None)
        qs=qs.filter(slug=slug)
        try:
            movie = qs.get()
        except Movie.DoesNotExist:
            raise Http404
        except Movie.MultipleObjectsReturned:
            messages.info(self.request, "Nick appears to have duplicates of this movie in his collection.")
            movie = qs[0]
        return movie
    def get_context_data(self, **kwargs):
        if self.object.imdb == None or self.object.imdb == '':
            movie_title = self.object.title
            movie_title=movie_title.replace(', The', '').replace('007: ', '').replace(' (Full Screen)', '').replace(' (Director\'s Cut)', '')
            movie_title=movie_title.replace(' (Special Edition)', '').replace(':', ' -').replace(' (2012)', '').replace(' (1966)', '')
            movie_title=movie_title.replace('Part 2', 'Part II').replace('Part 3', 'Part III').replace(', A', '')
            try:
                if self.object.year:
                    omdb = urllib.urlopen('http://www.omdbapi.com/?t=%s&y=%s' % (movie_title, self.object.year)).read()
                else:
                    omdb = urllib.urlopen('http://www.omdbapi.com/?t=%s' % movie_title).read()
            except:
                omdb = '{"Response":"False"}'
                value = sys.exc_info()[1]
                mail_admins('IMDb exception thrown: %s' % self.object.get_absolute_url(), value.__repr__())
            if self.object.import_imdb(json.loads(omdb)):
                messages.success(self.request, IMDB_SUCCESS)
            else:
                messages.error(self.request, IMDB_FAIL)
        kwargs.update({'length_stamp':LENGTH_STAMP})
        return super(MovieDetail, self).get_context_data(**kwargs)

class EditMovie(OnlyNickMixin, UpdateView):
    model = Movie
    form_class = MovieForm

class SignUp(CreateView):
    model = User
    form_class = UserForm
    template_name = 'registration/signup.html'
    def form_valid(self, form):
        self.object = form.save()
        self.object.set_password(self.object.password)
        self.object.save()
        user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password'])
        login(self.request, user)
        messages.success(self.request, "Your account has been created, and you have been logged in.")
        return redirect('browse_collection')

class WatchlistView(DetailView):
    model = Watchlist
    def get_object(self, queryset=None):
        username = self.kwargs.get('username', None)
        if username:
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                raise Http404
            return self.get_queryset().get(owner=user)
        try:
            return self.get_queryset().get(owner=self.request.user)
        except Watchlist.DoesNotExist:
            return Watchlist.objects.create(owner=self.request.user)

class BrowseDirector(ListView):
    model = Movie
    paginate_by = 100
    template_name = 'collection/director_detail.html'
    def get_queryset(self):
        self.director = get_object_or_404(Director, slug=self.kwargs['slug'])
        qs = super(BrowseDirector, self).get_queryset().select_related().filter(director=self.director)
        if 'ordering' in self.request.GET:
            return qs.order_by(self.request.GET.get('ordering'))
        if 'startswith' in self.request.GET:
            return qs.filter(title__startswith=self.request.GET.get('startswith'))
        return qs
    def get_context_data(self, **kwargs):
        kwargs.update({'director': self.director})
        return super(BrowseDirector, self).get_context_data(**kwargs)

class DirectorList(ListView):
    model = Director
    paginate_by = 100

def format_list(req):
    formats = []
    for fmt in Movie.FORMAT_CHOICES:
        formats.append({'name':fmt[1], 'id':fmt[0], 'title_count': Movie.objects.filter(format=fmt[0]).count()})
    return render(req, 'collection/format_list.html', {'format_list':formats})

def random_list(req):
    try:
        genre = int(req.GET.get('genre', 0))
        fmt = int(req.GET.get('format', 0))
    except:
        genre = fmt = 0
    qs = Movie.objects.select_related().all()
    if genre > 0:
        g = get_object_or_404(Genre, pk=genre)
        qs=qs.filter(genre=g)
    if fmt > 0:
        qs=qs.filter(format=fmt)
    movie_list = []
    try:
        for i in range(10):
            movie_list.append(random.choice(qs))
    except IndexError:
        pass
    ctx = {'movie_list':movie_list, 'genre':genre, 'format':fmt}
    if 'thumbnails' in req.GET:
        ctx.update({'thumbnails':True})
    return render(req, 'collection/random_list.html', ctx)

@login_required
def update_from_imdb(req, slug):
    movie = get_object_or_404(Movie, slug=slug)
    if not req.user.is_staff:
        messages.error(req, "You do not have access to update the info from IMDb.")
        return redirect(movie)
    try:
        omdb = urllib.urlopen('http://www.omdbapi.com/?i=%s' % movie.imdb).read()
    except:
        omdb = '{"Response":"False"}'
        value = sys.exc_info()[1]
        mail_admins('IMDb exception thrown: %s' % movie.get_absolute_url(), value.__repr__())
    if movie.import_imdb(json.loads(omdb)):
        messages.success(req, IMDB_SUCCESS)
    else:
        messages.error(req, IMDB_FAIL)
    return redirect(movie)

@login_required
def just_watched(req, slug):
    movie = get_object_or_404(Movie, slug=slug)
    if not req.user.is_staff:
        messages.error(req, "Only Nick can say if he watched a movie or not.")
        return redirect(movie)
    movie.watched +=1
    movie.last_watched = datetime.date.today()
    movie.save()
    return redirect(movie)

@login_required
def add_to_watchlist(req, slug):
    movie = get_object_or_404(Movie, slug=slug)
    watchlist, created = Watchlist.objects.get_or_create(owner=req.user)
    watchlist.movies.add(movie)
    messages.success(req, "Movie has been added to your watchlist.")
    return redirect(movie)

@login_required
def add_to_genres(req, slug):
    genre = get_object_or_404(Genre, slug=slug)
    watchlist, created = Watchlist.objects.get_or_create(owner=req.user)
    watchlist.genres.add(genre)
    messages.success(req, "Genre has been added to your watchlist.")
    return redirect(genre)

@login_required
def remove_from_watchlist(req, slug):
    movie = get_object_or_404(Movie, slug=slug)
    watchlist, created = Watchlist.objects.get_or_create(owner=req.user)
    watchlist.movies.remove(movie)
    messages.success(req, "Movie has been removed from your watchlist.")
    return redirect('my_watchlist')

def search(req):
    ctx = {}
    query = req.GET.get('q', None)
    if query:
        ctx.update({'query':query})
        if len(query) > 3:
            ctx.update({'results':Movie.objects.filter(title__icontains=query)})
        else:
            messages.info(req, "Please enter in a Query larger than 3 characters.")
    return render(req, "search.html", ctx)