D j a n g o app has not valid view function - python

I have an app for quiz. It shows registered quiz, but when I press submit button, It goes to /quiz/1/do/ to do function in views.py which should do this,
return HttpResponseRedirect(reverse('quiz.views.results', args=(q.id,)))
But it throws an error message,
NoReverseMatch at /quiz/1/do/
Reverse for 'quiz.views.results' not found. 'quiz.views.results' is not a valid view function or pattern name.
I wonder where could be a problem?
Code:
views.py:
from quiz.models import Quiz, Question, Score
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse
from django.template import RequestContext
from django.contrib.auth.decorators import login_required
#login_required()
def index(request):
latest_quiz = Quiz.objects.all().order_by('-created')[:5]
return render_to_response('quiz/index.html', {'latest_quiz': latest_quiz})
def detail(request, quiz_id):
q = get_object_or_404(Quiz, pk=quiz_id)
context = {'quiz': q}
return render(request, 'quiz/detail.html', context)
def results(request, quiz_id):
return HttpResponse("You're looking at the results of quiz %s." % quiz_id)
def do(request, quiz_id):
q = get_object_or_404(Quiz, pk=quiz_id)
try:
answer = ''
for question in q.question_set.all():
answer += request.POST['q%d' % question.id]
except (KeyError, Question.DoesNotExist):
# Redisplaying the form
return render_to_response('quiz/detail.html', {
'quiz': q,
'error_message': "You didn't do the quiz %r " %request.POST,
}, context_instance=RequestContext(request))
else:
s = q.score_set.create(student=request.user.username, submit_answer=answer, score=100)
s.save()
return HttpResponseRedirect(reverse('quiz.views.results', args=(q.id,))) # HERE !!!
def not_found(request, exception=None):
response = render(request, '404.html', {})
response.status_code = 404
return response
def server_error(request, exception=None):
response = render(request, '500.html', {})
response.status_code = 500
return response
urls.py:
from .models import Quiz, Question, Score
from django.urls import path
from . import views as quiz_view
from . views import detail, results, do
from django.contrib.auth.decorators import login_required
app_name = 'quiz'
handler404 = 'quiz.views.not_found'
handler500 = 'quiz.views.server_error'
urlpatterns = [
path('', quiz_view.index, name='detail'),
path('<int:quiz_id>/', quiz_view.detail, name='detail'),
path('<int:quiz_id>/results/', quiz_view.results, name='results'),
path('<int:quiz_id>/do/', quiz_view.do, name='do'),
]
models.py:
from django.db import models
#from django.contrib.auth.models import User
from random import shuffle
class Quiz(models.Model):
""" Quiz model. Every quiz has 10 questions. """
title = models.CharField(max_length=100)
category = models.CharField(max_length=100)
description = models.TextField()
slug = models.SlugField(unique=True)
# author = models.ForeignKey(User, related_name='author')
author = models.CharField(max_length=50)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = 'quizzes'
ordering = ('-modified', 'created')
def __unicode__(self):
return u"%s" % self.title
def options(self):
return list('abcde')
class Question(models.Model):
""" Question model. Each question attached to exact one quiz. """
quiz = models.ForeignKey(Quiz, on_delete=models.PROTECT)
question = models.TextField()
answer = models.TextField()
choice1 = models.TextField()
choice2 = models.TextField()
choice3 = models.TextField()
choice4 = models.TextField()
class Meta:
ordering = ('id', 'question',)
def __unicode__(self):
return u"%s" % self.question
def get_options(self):
return {'answer': self.answer, 'choice1': self.choice1, 'choice2': self.choice2, 'choice3':self.choice3, 'choice4': self.choice4, }
def randomize_options(self):
options = ['answer', 'choice1', 'choice2', 'choice3', 'choice4', ]
shuffle(options)
return options
class Score(models.Model):
""" Score model. Every quiz taken by students are recorded here. """
quiz = models.ForeignKey(Quiz, on_delete=models.PROTECT)
student = models.CharField(max_length=50)
submit_answer = models.CharField(max_length=50)
score = models.IntegerField(default=0)
quiz_taken = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('quiz_taken', 'student', 'score',)
def __unicode__(self):
return u"%s %d" % (student, score)
It return this,
answer
'a'
q
<Quiz: Quiz object (1)>
question
<Question: Question object (1)>
quiz_id
1
request
<WSGIRequest: POST '/quiz/1/do/'>
s
<Score: Score object (4)>

change the line
return HttpResponseRedirect(reverse('quiz.views.results', args=(q.id,)))
to
return HttpResponseRedirect(reverse('quiz:results', args=(q.id,)))

The first argument of reverse must be 'viewname' Django tutorial
If you need to use something similar to the url template tag in your code, Django provides the following function:
reverse(viewname, url conf=None, args=None, kwargs=None, current_app=None)
You must use view name from 'urlpattern':
return HttpResponseRedirect(reverse('quiz:results', args=(q.id,)))

I think you should try this:
return HttpResponseRedirect(reverse('do', args=q.id))

Related

How to check if URL is in Model/DB already on a URL Shortener? Django

i've been learning Django for these past days and i'm trying to develop an url shortener. It's functional and works great but it misses something: Check if the URL already exists so it can return the short URL stored in db. At this moments it's just checks if the short url is unique and does not exist already, so it always create a new and unique short url for the same URL.
I've tried to use queryset's exists() in if ShortenerForm.objects.filter(url = cleaned_info['url']).exists(): but it always gave me an error object has no attribute 'cleaned_data'
How can i do that?
These are my files:
views.py
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from utils.shorty.form import ShortenerForm
from shorty.models import Shortener
# Create your views here.
def home(request):
template = "shorty/pages/index.html"
context = {}
context["form"] = ShortenerForm()
if request.method == "GET":
return render(request, template, context)
elif request.method == "POST":
used_form = ShortenerForm(request.POST)
if used_form.is_valid():
shortened_object = used_form.save()
new_url = request.build_absolute_uri("/") + shortened_object.shortcode
long_url = shortened_object.url
context["new_url"] = new_url
context["long_url"] = long_url
return render(request, template, context)
context["errors"] = used_form.errors
return render(request, "shorty/pages/index.html")
def redirect_url_view(request, shortened_path):
try:
shortener = Shortener.objects.get(shortcode=shortened_path)
shortener.redirectCount += 1
shortener.save()
return HttpResponseRedirect(shortener.url)
except:
raise Http404("Sorry this link does not exist")
form.py
from django import forms
from shorty.models import Shortener
class ShortenerForm(forms.ModelForm):
url = forms.URLField(
widget=forms.URLInput(
attrs={"class": "form-control", "placeholder": "Enter URL"}
)
)
class Meta:
model = Shortener
fields = ("url",)
models.py
from django.db import models
from utils.shorty.factory import create_short_url
# Create your models here.
class Shortener(models.Model):
startDate = models.DateTimeField(auto_now_add=True)
lastSeenDate = models.DateTimeField(auto_now=True)
redirectCount = models.PositiveIntegerField(default=0)
url = models.URLField()
shortcode = models.CharField(max_length=6, unique=True, blank=True)
class Meta:
ordering = ["-startDate"]
def __str__(self):
return f"{self.url} to {self.shortcode}"
def save(self, *args, **kwargs):
if not self.shortcode:
self.shortcode = create_short_url(self)
super().save(*args, **kwargs)
Thanks for your patience and time.

Django API split data by unique ID

I am making Django API.
I collected place and review data using crwaling program.
I want to split review data by building name(unique key), but it seems all reviews are saved together and is spread to all URL.
models.py
from django.db import models
import uuid
# Create your models here.
from django.utils.text import slugify
def generate_unique_slug(klass, field):
origin_slug = slugify(field, allow_unicode=True)
unique_slug = origin_slug
numb = 1
while klass.objects.filter(slug=unique_slug).exists():
unique_slug = '%s-%d' % (origin_slug, numb)
numb += 1
return unique_slug
class BuildingData(models.Model):
building_name = models.CharField(max_length=50, unique=True)
slug = models.SlugField(max_length=50, unique=True, allow_unicode=True, default=uuid.uuid1)
building_loc = models.CharField(max_length=50)
building_call = models.CharField(max_length=20)
#building_time = models.CharField(max_length=50)
def save(self, *args, **kwargs):
if self.slug: # edit
if slugify(self.building_name, allow_unicode=True) != self.slug:
self.slug = generate_unique_slug(BuildingData, self.building_name)
else: # create
self.slug = generate_unique_slug(BuildingData, self.building_name)
super(BuildingData, self).save(*args, **kwargs)
class ReviewData(models.Model):
building_name = models.CharField(max_length=50)
review_content = models.TextField()
star_num = models.FloatField()
urls.py
from django.contrib import admin
from django.urls import path
from crawling_data.views import ReviewListAPI
from crawling_data.views import BuildingInfoAPI
urlpatterns = [
path('admin/', admin.site.urls),
path('api/buildingdata/', BuildingInfoAPI.as_view()),
path('api/buildingdata/<str:slug>/', ReviewListAPI.as_view())
]
models.py
# Create your views here.
from django.shortcuts import render
from rest_framework.response import Response
from .models import ReviewData
from .models import BuildingData
from rest_framework.views import APIView
from rest_framework import generics
from rest_framework import permissions
from .serializers import ReviewSerializer
from .serializers import BuildingSerializer
from django.shortcuts import render, get_object_or_404
class BuildingInfoAPI(APIView):
def get(self, request):
queryset = BuildingData.objects.all()
serializer = BuildingSerializer(queryset, many=True)
return Response(serializer.data)
class ReviewListAPI(APIView):
def get(self, request, slug):
queryset = ReviewData.objects.all()
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
A part of crwaling program
if __name__=='__main__':
for item in building_dict:
BuildingData(building_name = item['place'], building_loc = item['location'], building_call = item['call']).save()
#BuildingData(building_name = item['place'], building_loc = item['location'], building_call = item['call'], building_time = item['time']).save()
for item in review_dict:
ReviewData(building_name = item['place'], review_content = item['review'], star_num = item['rate']).save()
Saving code above runs when program crawled all pages.
But this code saves all reviews on the same DB.
So what I want is this
URL : api/buildingdata/A/
A building - a review
A building - b review
URL : api/buildingdata/B/
B building - a review
B building - b review
But my API looks like this
URL : api/buildingdata/A/
A building - a review
A building - b review
B building - a review
B building - b review
URL : api/buildingdata/B/
A building - a review
A building - b review
B building - a review
B building - b review
Where should I fix to split review data by building name?
There looks to be two problems here. There is no explicit relationship defined between your two models and your ReviewListAPI View is accepting a slug, but doing nothing with it.
You should create a foreign key relationship between buildings and their reviews and then you can use a building's slug it to filter for reviews relevant only to that building:
You could update your ReviewData model like so:
class ReviewData(models.Model):
building = models.ForeignKey(BuildingData, on_delete=models.CASCADE)
...
class ReviewListAPI(APIView):
def get(self, request, slug):
queryset = ReviewData.objects.filter(building__slug=slug)
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
Retrieving Objects
Foreign Keys
This may also necessetate that you update your serializers to reflect the relation between the objects:
If you dont want to make the Foreign Key relationship you could try this in your views:
class ReviewListAPI(APIView):
def get(self, request, slug):
building_name = BuildingData.objects.filter(slug=slug).values_list('building_name',flat=True)[0]
queryset = ReviewData.objects.filter(building_name=building_name)
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
Here you filter the BuildingData by the slug, and return the single building name value against which you want to filter your ReviewData

NoReverse Match in Mezzanine - I am using get_absolute_url for slug field

I am currently developing a mezzanine project. I always get "NoReverseMatch":
Reverse for 'download' with arguments '()' and keyword arguments '{u'slug': u'read-metxt-1-2-3-4-5-6-7-8-9-10'}' not found. 0 pattern(s) tried: []
In my previous app before I used Mezzanine, there was no error. I just copy-pasted the code and modify it accordingly.
Sorry for asking the same question. I know there are other similar questions as mine, but none of them is working.
models.py
from __future__ import unicode_literals
from django.db import models
from django.core.urlresolvers import reverse
from django.db.models.signals import pre_save
from django.utils.text import slugify
import os
# Create your models here.
class ReportOutline_File(models.Model):
slug = models.SlugField(unique=True, max_length=100)
report_outline = models.FileField()
def get_absolute_url(self):
return reverse('txttoppt: download', kwargs={"slug": self.slug})
def create_slug(instance, new_slug=None):
slug = slugify(instance.report_outline.name) #slugifying the title
if new_slug is not None:
slug = new_slug
qs = ReportOutline_File.objects.filter(slug=slug).order_by("-id")
exists = qs.exists()
if exists:
new_slug = "%s-%s" %(slug, qs.first().id)
return create_slug(instance, new_slug=new_slug)
return slug
def pre_save_post_receiver(sender, instance, *args, **kwargs):
if not instance.slug:
instance.slug = create_slug(instance)
print instance.slug
pre_save.connect(pre_save_post_receiver, sender=ReportOutline_File)
urls.py (main: mezzanine)
urlpatterns += [
url("^$", direct_to_template, {"template": "index.html"}, name="home"),
url("^convert-to-ppt/", include("toppt.urls", namespace="txttoppt")),]
urls.py (app)
from .views import (
converttexttoppt_func,
download
)
urlpatterns = [
url(r"^", converttexttoppt_func, name="converttexttoppt"),
url(r"^download/(?P<slug>[\w-]+)/$", download, name='download')]
views.py
def converttexttoppt_func(request):
form = ReportOutlineForm(request.POST or None, request.FILES or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form
}
return render(request, "texttoppt.html", context)
def download(request, slug):
instance = get_object_or_404(ReportOutline_File, slug=slug)
#more codes in between....
return render(request, "download.html", context)
Please help! Thank you. I've been looking for solution for this error for two days now! Tsk!
The slug you're providing includes numbers, but the url doesn't match numbers
u'read-metxt-1-2-3-4-5-6-7-8-9-10'
so you need to update your url accordingly
url(r"^download/(?P<slug>[\w\d-]+)/$", download, name='download')

how to get the login username while using django-registration-redux

I want to collect the login user's data while using Django. But i don't know how to locate the unique login username when i use django-registration-redux
I have tried to do this, here's my views.py:
from django.shortcuts import render
from yigu.models import Gw, user_data
from django.contrib.auth.models import User
def index(request):
Gw_list = Gw.objects.all()
context_dict = {'cyshici': Gw_list}
return render(request, 'yigu/base.html', context_dict)
def search(request):
if 'gw' in request.GET:
words_1 = request.GET['gw']
result_list = Gw.objects.filter(field_1=words_1)
result_list2 = user_data.objects.filter(word=words_1)
result_list3 = user_data.objects.filter(user=User.username)
# For basic search match and display content
if result_list:
context_dict = {'result_list': result_list}
words = Gw.objects.get(field_1=words_1)
words.views = words.views + 1
words.save()
# For words_information Model
if result_list2 & result_list3:
words2 = user_data.objects.get(word=words_1)
words2.click_times = words2.click_times + 1
words2.save()
else:
words2 = user_data(user=User.username, word=words_1, click_times=words.views)
words2.save()
return render(request, 'yigu/search.html', context_dict)
here's my models.py:
class user_data(models.Model):
user = models.CharField(max_length=255)
word = models.CharField(max_length=255)
click_times = models.IntegerField(default=0)
class Meta:
ordering = ('click_times',)
def __unicode__(self):
return self.user
But the all the username is something like this <class 'django.contrib.auth.models.User'>
Could anyone give me some tips?
User models of using Redux:
from django.contrib.auth.models import User
And add an OneToOneField to user_data:
class UserData(models.Model):
user = models.OneToOneField(User)
clicks = models.IntegerField(default = 0)
def __str__(self):
return self.user.username

Database query in django

I am creating a simple quiz app using django. When a user submits the answer for a question, the answer is checked using the correct answer present in database.
views.py
from django.shortcuts import render,get_object_or_404
from .models import question
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
def detail(request, question_id):
ques = get_object_or_404(question, pk=question_id)
return render(request, 'detail.html', {'ques': ques})
def index(request):
questions = question.objects.all()
return render(request,"question.html",{"questions":questions})
def vote(request,question_id):
p = get_object_or_404(question, pk=question_id)
selected_choice = p.choice_set.get(pk = request.POST['choice'])
print selected_choice,p.answer_text
if(selected_choice == p.answer_text):
print "yes"
x = int(question_id) + 1
return HttpResponseRedirect(reverse('detail', args=(str(x))))
The vote function is called after user clicks the submit button. The check is performed here. When I print selected_choice and p.answer_text, they show correct values. But when I compare them using equal operator, it doesn't return true even when both are same.
models.py
from django.db import models
class question(models.Model):
question_text = models.CharField(max_length = 400)
answer_text = models.CharField(max_length = 400,default = "name")
def __unicode__(self):
return self.question_text,self.answer_text
class choice(models.Model):
question = models.ForeignKey(question)
choice_text = models.CharField(max_length = 200)
def __unicode__(self):
return self.choice_text

Categories