Blog matching query does not exist. (%3Fid=) - python

Used reverse() in the model's method get_absolute_url(), but django raises an error - DoesNotExist at /blog/detail/?id=23, becouse return not correct url - "/%3Fid=23" and urlpatterns haven't this in patterns, when I need the correct url - "/?id=23". Why this happens and how to fix it?
urls.py (blog app)
from django.conf.urls import url
from django.contrib.auth.decorators import permission_required
from blog.views import BlogListView, BlogDetailView, BlogCreate, BlogUpdate, BlogDelete
urlpatterns = [
url(r'^$', BlogListView.as_view(), name = "blog"),
url(r'^detail/(?:\?id=(?P<blog_id>\d+))?$', BlogDetailView.as_view(), name = "blog_detail"),
url(r'^add/(?:\?id=(?P<blog_id>\d+))?$', permission_required("blog.add_blog")(BlogCreate.as_view()), name = "blog_add"),
url(r'^edit/(?:\?id=(?P<blog_id>\d+))?$', permission_required("blog.change_blog")(BlogUpdate.as_view()), name = "blog_edit"),
url(r'^delete/(?:\?id=(?P<blog_id>\d+))?$', permission_required("blog.delete_blog")(BlogDelete.as_view()), name = "blog_delete"),
]
models.py (blog app)
from django.db import models
from datetime import datetime
from taggit.managers import TaggableManager
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django_comments.moderation import CommentModerator, moderator
from django.shortcuts import redirect
# Create your models here.
class Blog(models.Model):
title = models.CharField(max_length = 100, unique_for_date = "posted", verbose_name = "Title")
description = models.TextField(verbose_name = "Description")
content = models.TextField(verbose_name = "Content")
posted = models.DateTimeField(default = datetime.now(), db_index = True, verbose_name = "Posted")
is_commentable = models.BooleanField(default = True, verbose_name = "Comments are allowed")
tags = TaggableManager(blank = True, verbose_name = "Tags")
user = models.ForeignKey(User, editable = False)
def get_absolute_url(self):
return reverse("blog_detail", kwargs = {"blog_id": self.pk})
class Meta:
ordering = ["-posted"]
verbose_name = "blog article"
verbose_name_plural = "blog articles"
views.py (blog app/only BlogCreate, BlogDetailView + e.t.c)
...
class PageNumberView(View):
def get(self, request, *args, **kwargs):
try:
self.sort = request.GET.get("sort")
except KeyError:
self.sort = "0"
try:
self.order = request.GET.get("order")
except KeyError:
self.order = "A"
try:
self.search = self.request.GET.get("search")
except KeyError:
self.search = ""
try:
self.tag = self.request.GET.get("tag")
except KeyError:
self.tag = ""
return super(PageNumberView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
try:
pn = self.request.GET.get("page", default=None)
if pn == None:
pn = "1"
except KeyError:
pn = "1"
self.success_url = self.success_url + "?page=" + pn
try:
self.success_url = self.success_url + "&search=" + self.request.GET.get("search")
except KeyError:
pass
try:
self.success_url = self.success_url + "&tag=" + self.request.GET.get("tag")
except KeyError:
pass
return super(PageNumberView, self).post(request, *args, **kwargs)
class PageNumberMixin(CategoryListMixin):
def get_context_data(self, **kwargs):
context = super(PageNumberMixin, self).get_context_data(**kwargs)
try:
context["pn"] = self.request.GET.get("page", default=None)
if context["pn"] == None:
context["pn"] = "1"
except KeyError:
context["pn"] = "1"
return context
class BlogDetailView(PageNumberView, DetailView, SearchMixin, PageNumberMixin):
model = Blog
template_name = "blog_detail.html"
def get_object(self):
return self.model.objects.get(pk=self.request.GET.get('id'))
class CategoryListMixin(ContextMixin):
def get_context_data(self, **kwargs):
context = super(CategoryListMixin, self).get_context_data(**kwargs)
context["current_url"] = self.request.path
context["categories"] = Category.objects.all()
return context
class BlogCreate(SuccessMessageMixin, CreateView, CategoryListMixin):
model = Blog
template_name = "blog_add.html"
success_message = "Article successfully created"
fields = '__all__'
def form_valid(self, form):
form.instance.user = self.request.user
return super(BlogCreate, self).form_valid(form)
...

You just write url like this:
url(r'^detail/(?P<blog_id>\d+)/$', BlogDetailView.as_view(), name = "blog_detail"),

Your url pattern definition should be
url(r'^detail/$', BlogDetailView.as_view(), name="blog_detail"),
if you want to use GET parameters (query parameters) as in /blog/detail/?blog_id=123. The parameter can be accessed in the view with
blog_id = request.GET.get('blog_id')
blog = get_object_or_404(Blog, id=blog_id)
something like that.
Or if you want to make the blog_id part of your URL, the URL pattern must be
url(r'^detail/(?P<blog_id>\d+)/$', BlogDetailView.as_view(), name="blog_detail"),
In which case your URL will look like /blog/detail/123/ and the value is available for access as a keyword argument.

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.

I have an error msg trying to use a slug field that contains an unusual character

My DB (MariaDB) is set to utf8mb4, my model and my view are all defined to use unicode characters.
The creation of the record is ok and a slug is correctly created with a value as for example corée. The problem raise right after the creation with a NoReverse match error msg. I had a look to the documentation but I don't understand what I'm doing wrong. Thanks for your support.
NoReverseMatch at /masterdat/countrycode/
Reverse for 'countrycode_update' with keyword arguments '{'slug': 'corée'}' not found. 1 pattern(s) tried: ['masterdat/countrycode/(?P[-a-zA-Z0-9_]+)/$']
Request Method: GET
Request URL: http://127.0.0.1:8000/masterdat/countrycode/
Django Version: 3.2.5
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'countrycode_update' with keyword arguments '{'slug': 'corée'}' not found. 1 pattern(s) tried: ['masterdat/countrycode/(?P[-a-zA-Z0-9_]+)/$']
URL:
from django.urls import path
from masterdat import views
from masterdat.views import CountrycodeListView
from masterdat.views import CountrycodeCreateView, CountrycodeUpdateView
urlpatterns = [
path('masterdathome/', views.masterdathome, name='masterdathome'),
path('countrycode/', CountrycodeListView.as_view(),
name='countrycode_list'),
path('countrycode/add/', CountrycodeCreateView.as_view(),
name='countrycode_add'),
path('countrycode/<slug:slug>/', CountrycodeUpdateView.as_view(),
name='countrycode_update'),
]
Model:
class Countrycode(models.Model):
cou_code = models.CharField(
"Country name", max_length=40, primary_key=True)
cou_recblocked = models.BooleanField("Country record blocked")
cou_creator = models.ForeignKey(
User, on_delete=models.PROTECT, related_name='+',
verbose_name="Created by")
cou_creationdate = models.DateTimeField("Creation date",
auto_now=True)
cou_modifier = models.ForeignKey(
User, on_delete=models.PROTECT, related_name='+',
verbose_name="Last modification by")
cou_modified = models.DateTimeField(
"Last modification date", auto_now=True)
slug = models.SlugField(max_length=50, allow_unicode=True)
class Meta:
ordering = ["cou_code"]
def __str__(self):
return self.cou_code
def get_absolute_url(self):
return reverse('countrycode_update', kwargs={'slug': self.slug})
View:
from masterdat.models import Countrycode
#-----------------------
# List view Management
#-----------------------
class CountrycodeListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
permission_required = 'masterdat.view_countrycode'
model = Countrycode
paginate_by = 10
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
return context
# Search bar
def get_queryset(self):
result = super(CountrycodeListView, self).get_queryset()
query = self.request.GET.get('q')
if query:
query_list = query.split()
result = result.filter(
reduce(operator.and_,
(Q(cou_code__icontains=q) for q in query_list))
)
return result
#-----------------------------------
# Create and Update Views Management
#-----------------------------------
from masterdat.forms import CountrycodeForm
# Create View -----------
class CountrycodeCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
permission_required = 'masterdat.add_countrycode'
model = Countrycode
form_class = CountrycodeForm
success_url = reverse_lazy('countrycode_list')
def form_valid(self, form):
form.instance.slug = slugify(form.instance.cou_code, allow_unicode=True)
form.instance.cou_creator = self.request.user
form.instance.cou_modifier = self.request.user
form.save
return super().form_valid(form)
# Update View -----------
class CountrycodeUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
permission_required = 'masterdat.change_countrycode'
model = Countrycode
form_class = CountrycodeForm
success_url = reverse_lazy('countrycode_list')
def form_valid(self, form):
form.instance.cou_modifier = self.request.user
form.save
return super().form_valid(form)
The regular expression (?P[-a-zA-Z0-9_]+) will only match "cor" because "é" is not a member of the range "A-Z" or "a-z".
You could change it to (?P[-\w0-9_]+) to match non-ASCII characters.

Django - NOT NULL constraint failed

I'm currently working on a Django app that will parse the contents of an uploaded log file to the associated database in my Django project. I've managed to get it all running as expected except it won't associate my uploaded data with the model's ForeignKey. I can assign null=True which resolves the integrity error but then of course, it doesn't assign any of the uploaded data to that ForeignKey. Here's the code:
models.py
class Case(models.Model):
case_ref = models.CharField(max_length=8)
oic = models.CharField(max_length=50)
subject = models.CharField(max_length=100)
submitted_date = models.DateTimeField(default=datetime.now, blank=True)
def get_absolute_url(self):
return reverse('case_list', kwargs={'pk': self.pk})
def __str__(self):
return self.case_ref + " " + self.subject
class TeamviewerLogs(models.Model):
case = models.ForeignKey(Case, on_delete=models.DO_NOTHING)
teamviewer_id = models.IntegerField()
teamviewer_name = models.TextField()
connection_start = models.TextField()
connection_end = models.TextField()
local_user = models.TextField()
connection_type = models.TextField()
unique_id = models.TextField()
def get_absolute_url(self):
return reverse('case_list', kwargs={'pk': self.pk})
def __str__(self):
return str(self.teamviewer_id) + " - " + str(self.teamviewer_id)
forms.py
class UploadLog(forms.ModelForm):
file = forms.FileField()
class Meta:
model = TeamviewerLogs
fields = [
'file'
]
views.py
def add_logs(request, pk):
case = get_object_or_404(Case, pk=pk)
if request.method == 'POST':
form = UploadLog(request.POST, request.FILES)
if form.is_valid():
teamviewer = form.save(commit=False)
teamviewer.case = case
log_file = request.FILES['file']
log_file = filter(None, (line.rstrip() for line in log_file))
for lines in log_file:
split = lines.decode('utf-8').split('\t')
teamviewer_id = split[0]
teamviewer_name = split[1]
connection_start = split[2]
connection_end = split[3]
local_user = split[4]
connection_type = split[5]
unique_id = split[6]
teamviewer = TeamviewerLogs(teamviewer_id=teamviewer_id, teamviewer_name=teamviewer_name,
connection_start=connection_start, connection_end=connection_end,
local_user=local_user, connection_type=connection_type, unique_id=unique_id)
teamviewer.save()
return redirect('tv_log_details', pk=case.pk)
form.save()
else:
form = UploadLog()
return render(request, 'teamviewer/add_logs.html', {'form': form})
But when I click to upload the file I'm hit with:
When it tries to execute teamviewer.save().
I've been trying to resolve this issue for hours and have tried so many different variations of answers from Stackoverflow or previous code I've used that has worked for different models but I've hit a brick wall...hard!
Any help anyone can offer would be greatly appreciated.
Ok, so here's an example of the concept I've suggested in the comments.
I've got a view which passes some data to the a form;
class ListingDetailView(DetailView):
""" Listing detail page """
model = Listing
template_name = 'listing.html'
def get_form_kwargs(self):
"""Return the kwargs for the form"""
kwargs = {}
initial = {
'listing': self.object,
}
kwargs['initial'] = initial
return kwargs
def get_form(self):
form = ApplicationSignupForm(
**self.get_form_kwargs()
)
return form
def get_context_data(self, **kwargs):
""" Add our form to the context """
context = super().get_context_data(**kwargs)
context['form'] = self.get_form()
return context
The form then makes use of that initial data and sets the field it relates to as hidden. I don't validate this data, but I'll try to show how you might do that;
class ApplicationSignupForm(forms.ModelForm):
class Meta:
""" Setup the form """
fields = (
'listing',
...
)
model = Application
widgets = {
'listing': forms.HiddenInput()
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
initial_data = kwargs['initial']
self.listing = initial_data.get('listing')
def clean(self):
"""
Custom form cleaning
"""
cleaned_data = super().clean()
listing = cleaned_data.get('listing')
if listing != self.listing:
self.add_error('listing', "You can't modify this value")
return cleaned_data

UpdateView define primary key

I am trying to set my primary key in a class based view to a unique value from my models.
models.py
from django.db import models
from django.forms import model_to_dict
class Stuff(models.Model):
thing = models.CharField(max_length=100, verbose_name="Thing", unique=True)
item = models.CharField(max_length=100, verbose_name="Item")
def __str__(self):
return self.thing
def toJSON(self):
item = model_to_dict(self)
return item
views.py
from django.urls import reverse_lazy
from django.views.generic import CreateView, UpdateView
class NewStuff(CreateView):
model = Stuff
form_class = NewStuffForm
template_name = 'stuff.html'
success_url = reverse_lazy('search_stuff')
def post(self, request, *args, **kwargs):
data = {}
try:
action = request.POST['action']
if action == 'add':
form = self.get_form()
data = form.save()
else:
data['error'] = "No option has been selected"
except Exception as e:
data['error'] = str(e)
return JsonResponse(data)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'New Stuff'
context['stuff_url'] = reverse_lazy('search_stuff')
context['action'] = 'add'
return context
class EditStuff(UpdateView):
model = Stuff
form_class = NewStuffForm
template_name = 'stuff.html'
success_url = reverse_lazy('search_stuff')
def dispatch(self, request, *args, **kwargs):
self.object = self.get_object()
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
data = {}
try:
action = request.POST['action']
if action == 'edit':
form = self.get_form()
data = form.save()
else:
data['error'] = '"No option has been selected"
except Exception as e:
data['error'] = str(e)
return JsonResponse(data)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'New Stuff'
context['stuff_url'] = reverse_lazy('search_stuff')
context['action'] = 'edit'
return context
forms.py
from django import forms
from .models import Stuff
class NewStuffForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for form in self.visible_fields():
form.field.widget.attrs['class'] = 'form-control'
class Meta:
model = Stuff
fields = '__all__'
def save(self, commit=True):
data = {}
form = super()
try:
if form.is_valid():
form.save()
else:
data['error'] = form.errors
except Exception as e:
data['error'] = str(e)
return data
urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('stuff/add/', NewStuff.as_view(), name='new_stuff'),
path('stuff/edit/<str:pk>', EditStuff.as_view(), name='edit_stuff'),
]
How can I set the pk on the view "EditStuff" equal to thing from the "Stuff" model?
I understand that I can get the primary key with self.kwargs['pk']. However, I do not know how to set it equal to the primary key...
My best guess is that I should do it inside the dispatch method, nevertheless, I am not entirely sure about it.
First, set slug_field and slug_url_kwarg attributes in your view as
class EditStuff(UpdateView):
slug_field = "thing"
slug_url_kwarg = "thing"
# rest of your code
Then, update the URL as
urlpatterns = [
path('stuff/add/', NewStuff.as_view(), name='new_stuff'),
path('stuff/edit/<str:thing>', EditStuff.as_view(), name='edit_stuff'),
]

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

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))

Categories