Django URL appending hash - python

Hi All i have a small test app that has a basic model with a form based on this model:
class PublicNotesPost(models.Model):
noteName = models.CharField(max_length=255)
termsAgreed = models.BooleanField(default=False)
noteData = models.TextField()
def __str__(self):
return self.pk
class Meta:
verbose_name_plural = "Test Note Post Data"
My aim is when i post a note it redirects to a viewer with a dynamic url, at the moment i have not setup the viewer just an empty html file with a H1 tag just to test redirection. However what happens is a Hash is appended to the end of the url and i cant for the life of me figure out why this is and wanted to post here in case anyone has experienced this and has an understanding of how to rectify it?
http://127.0.0.1:8000/note/ryXVe7tAhC/#
My Url patterns are as follows:
from django.urls import path
from .import views
urlpatterns = [
path('note/composer/', views.NoteComposer.as_view() ,name="note_composer"),
path('note/<str:shorturl>/', views.ViewNote ,name="noteviewer")
]
View functions:
from django.shortcuts import render, redirect
from .forms import PostComposerForm
from django.urls import reverse
from django.views import View
import string
import random
# Create your views here.
def short_random_string(N:int) -> str:
return ''.join(random.SystemRandom().choice(string.ascii_uppercase +string.ascii_lowercase+ string.digits) for i in range(N))
class NoteComposer(View):
def get(self, request):
try:
formdata = {
'form': PostComposerForm(),
'navbar_active': 'composer',
'agreedTerms': False
}
return render(request, 'main/composer.html', formdata)
except Exception as ex:
print(ex)
return redirect('/')
def post(self, request):
try:
form = PublicComposerForm(self.request.POST)
if form.is_valid():
shortUrl = short_random_string(10)
return redirect(reverse('noteviewer', kwargs={"shorturl": shortUrl}))
pass
except Exception as ex:
print(ex)
return redirect('/')
def ViewNote(request, shorturl):
try:
return render(request,'main/view_note.html')
except:
return redirect('/')

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.

error with 'str' object has no attribute 'save' for my django project

I take an error as 'str' object has no attribute 'save'. I couldn't find where is the problem.
How can I fix it? [enter image description here][1]
error screenshot: [1]: https://i.stack.imgur.com/87joO.png
my model code:
from django.http import HttpResponse
from django.shortcuts import render, HttpResponse, HttpResponseRedirect
from .models import yazi
from .forms import CreateForm
from django.utils.text import slugify
# Create your views here.
def postliste_view(request):
yazilar = yazi.objects.all()
return render(request, "liste.html", {"yazilar": yazilar})
def postdetail_view(request, id):
yaziNesne = yazi.objects.get(id=id)
return render(request, "detail.html", {"yazi" : yaziNesne})
def postcreate_view(request):
form = CreateForm()
return render(request, "create.html", {"form" : form} )
def formdoldur_view(request):
form = CreateForm(request.POST or None, request.FILES or None)
if form.is_valid():
yaziNesne = form.save(commit=False)
yaziNesne = slug = slugify(yaziNesne.başlık)
yaziNesne.save()
return render(request, "gonderildi.html", {})
def postupdate_view(request, id):
if request.GET:
baslik = request.GET.get("baslik")
metin = request.GET.get("metin")
yaziNesne = yazi.objects.get(id=id)
yaziNesne.başlık = baslik
yaziNesne.metin = metin
yaziNesne.save()
else:
yaziNesne = yazi.objects.get(id=id)
return render(request, "update.html", {"yazi" : yaziNesne})
def postdelete_view(request, id):
yaziNesne = yazi.objects.get(id=id)
yaziNesne.delete()
return HttpResponseRedirect("/post")
# database api --> veritabanı işlemlerini yapan fonksiyonlar
#
django shell --> djangonun python kabuğu

How to place search query on url on django?

I am creating a search application with Django.
I made an article model and a Feedback model that records the rating of articles.
After entering search box and displaying the search results, click one of the results then goes to the detail screen.
After selecting feedback on the detail screen and pressing the submit button, I want to save a search query to the feedback model.
I think that solution is to add a query in the URL like portal/search/?=query and read it, but I don't know how to code it. Also, could you teach me if there is an implementation method other than reading query in the URL?
Also, when I go back from the detail screen, I want to display the previous search results too.
Please comment if you have any questions.
Forgive for my poor English.
models.py
from django.db import models
from django.urls import reverse
from taggit.managers import TaggableManager
class KnowHow(models.Model):
BASIC_TAGS =(
('1','one'),
('2','two'),
('3','three'),
('4','four'),
('5','five'),
('6','six'),
)
CATEGORY =(
('1','Type2'),
('2','Type1'),
)
author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
category = models.CharField(max_length=1,choices=CATEGORY,default='1')
title = models.CharField(max_length=200)
text = models.TextField(blank=True,default=' ')
# delault=' ':import system will give a error if text column is null
file = models.FileField(blank=True,upload_to='explicit_knowhows')
basic_tag = models.CharField(max_length=1,choices=BASIC_TAGS,default='1')
free_tags = TaggableManager(blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('portal:index')
class Feedback(models.Model):
EFFECT =(
('1','great'),
('2','maybe good'),
('3','bad'),
)
NOVEL =(
('1','I didn't know that'),
('2','I know, but I forgot'),
('3','I know this.'),
)
kh = models.ForeignKey(KnowHow, on_delete=models.PROTECT)
user = models.ForeignKey('auth.User',on_delete=models.CASCADE)
query = models.TextField(blank=True)
time = models.DateTimeField(auto_now_add=True)
efficacy = models.CharField(max_length=1,choices=EFFECT,default='1')
novelty = models.CharField(max_length=1,choices=NOVEL,default='1')
def __str__(self):
return self.time.strftime("%Y/%m/%d %H:%M:%S")
views.py
from django.urls import reverse, reverse_lazy
from django.http import HttpResponse
from django.views import generic
from django.views.generic.edit import ModelFormMixin
from django.shortcuts import redirect,get_object_or_404
from django.core.exceptions import PermissionDenied
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from .models import KnowHow
from taggit.models import Tag
from .forms import SearchForm,FeedbackForm
from django.db.models import Q
"""
Django Auth
The LoginRequired mixin
https://docs.djangoproject.com/en/2.0/topics/auth/default/#the-loginrequired-mixin
The login_required decorator
https://docs.djangoproject.com/en/2.0/topics/auth/default/#the-login-required-decorator
#login_required
"""
class IndexView(LoginRequiredMixin,generic.list.ListView):
model = KnowHow
#paginate_by = 5
ordering = ['-title']
# template_name = 'portal/KnowHow_list.html'
class DetailView(ModelFormMixin,LoginRequiredMixin,generic.detail.DetailView):
# from https://torina.top/detail/337/
model = KnowHow
form_class = FeedbackForm
template_name = 'portal/KnowHow_detail.html'
def form_valid(self, form):
kh_pk = self.kwargs['pk']
Feedback = form.save(commit=False)
Feedback.kh = get_object_or_404(KnowHow, pk=kh_pk)
Feedback.query=""
Feedback.user=self.request.user
Feedback.save()
return redirect('portal:search')
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
self.object = self.get_object()
return self.form_invalid(form)
class CreateView(LoginRequiredMixin, generic.edit.CreateView): # The LoginRequired mixin
model = KnowHow
fields = ['category','title','text','file','basic_tag','free_tags']
#template_name = 'portal/KnowHow_form.html'
def form_valid(self, form):
# This method is called when valid form data has been posted.
# It should return an HttpResponse.
# https://docs.djangoproject.com/en/2.0/topics/class-based-views/generic-editing/#models-and-request-user
form.instance.author = self.request.user
return super(CreateView, self).form_valid(form)
class UpdateView(LoginRequiredMixin, generic.edit.UpdateView): # The LoginRequired mixin
model = KnowHow
fields = ['category','title','text','file','basic_tag','free_tags']
#template_name = 'portal/KnowHow_form.html'
class DeleteView(LoginRequiredMixin, generic.edit.DeleteView): # The LoginRequired mixin
model = KnowHow
success_url = reverse_lazy('portal:index')
def delete(self, request, *args, **kwargs):
result = super().delete(request, *args, **kwargs)
Tag.objects.filter(knowhow=None).delete()
return result
#template_name = 'portal/KnowHow_confirm_delete.html'
class SearchIndexView(LoginRequiredMixin, generic.ListView):
template_name="search/search_index.html"
model = KnowHow
def post(self, request, *args, **kwargs):
form_value = [
self.request.POST.get('basic_tag', None),
self.request.POST.get('free_tags', None),
]
request.session['form_value'] = form_value
self.request.GET = self.request.GET.copy()
self.request.GET.clear()
return self.get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
basic_tag = ''
free_tags = ''
if 'form_value' in self.request.session:
form_value = self.request.session['form_value']
basic_tag = form_value[0]
free_tags = form_value[1]
default_data = {'basic_tag': basic_tag,
'free_tags': free_tags,
}
test_form = SearchForm(initial=default_data)
context['test_form'] = test_form
return context
def get_queryset(self):
if 'form_value' in self.request.session:
form_value = self.request.session['form_value']
basic_tag = form_value[0]
free_tags = form_value[1]
condition_basic_tag = Q()
condition_free_tags = Q()
if len(basic_tag) != 0 and basic_tag[0]:
condition_basic_tag = Q(basic_tag=basic_tag)
if len(free_tags) != 0 and free_tags[0]:
condition_free_tags = Q(free_tags__name__in=free_tags)
return KnowHow.objects.filter(condition_basic_tag & condition_free_tags).distinct()
else:
return KnowHow.objects.none()
#login_required
def help(request):
return HttpResponse("Member Only Help Page")
urls.py
from django.urls import path
from . import views
# set the application namespace
# https://docs.djangoproject.com/en/2.0/intro/tutorial03/
app_name = 'portal'
urlpatterns = [
# ex: /
path('', views.IndexView.as_view(), name='index'),
# ex: /KnowHow/create/
path('KnowHow/create/', views.CreateView.as_view(), name='create'),
# ex: /KnowHow/1/
path('KnowHow/<int:pk>/detail/', views.DetailView.as_view(), name='detail'),
# ex: /KnowHow/1/update/
path('KnowHow/<int:pk>/update/', views.UpdateView.as_view(), name='update'),
# ex: /KnowHow/1/delete
path('KnowHow/<int:pk>/delete/', views.DeleteView.as_view(), name='delete'),
# ex: /KnowHow/help/
path('KnowHow/help/', views.help, name='help'),
path('search/',views.SearchIndexView.as_view(), name='search')
]
There are several solutions for your problem.
First one is the exact solution you mentioned yourself. using a query string parameter like ?q= for KnowHow details view.
Using a SearchLog model and using that model's identifier. When someone hits the /search/ endpoint, you create a new SearchLog and pass the pk for this record to your front. Basically it would be just like ?q= option. instead you can use ?search_id= to bind the feedback to an specific SearchLog
Use user sessions. Bind the searched query to user's session and when they want to create a new Feedback use the query in their session.
For the first two options, you just need to create your urls for the detail links properly (in your search result page). In your template, do something like below:
# You are probably doing something like this
{% for r in results %}
{{r.name}}
{% endfor %}
# You should do this instead
{% for r in results %}
{{r.name}}
{% endfor %}
You can either pass the current_query in your context when rendering the template, or use javascript to get that value from browser's location / query string.
I changed get_context_data function in SearchIndexView to this:
in the last line before return add these two lines
context['basic_tag'] = basic_tag
context['free_tags'] = free_tags
And I changed html too.
{{ KnowHow.title }}
Thanks, #n1ma

Couldn't load admin interface due the error below

I've got following code and got two issues.
1. I couldn't get joins added up and not showing up on the page.
2. Admin interface is not loading.
I've re-created the DB checked the code thoroughly and really need help.
Views.py.
from django.conf import settings
from django.shortcuts import render, HttpResponseRedirect, Http404
from.models import Join
from .forms import EmailForm, JoinForm
def get_ip(request):
try:
x_forwarded = request.META.get("HTTP_X_FORWARDED_FOR")
if x_forwarded:
ip = x_forwarded.split(",")[0]
else:
ip = request.META.get("REMOTE_ADDR")
except:
ip = ""
return ip
import uuid
def get_ref_id():
ref_id = str(uuid.uuid4())[:11].replace('-', '').lower()
try:
id_exists = Join.objects.get(ref_id=ref_id)
get_ref_id()
except:
return ref_id
def home(request):
try:
join_id = request.session['join_id_ref']
obj = Join.objects.get(id=join_id)
except:
obj = None
form = JoinForm(request.POST or None)
if form.is_valid():
new_join = form.save(commit=False)
email = form.cleaned_data['email']
new_join_old, created = Join.objects.get_or_create(email=email)
if created:
new_join_old.ref_id = get_ref_id()
if not obj == None:
new_join_old.friend = obj
new_join_old.ip_address = get_ip(request)
new_join_old.save()
return HttpResponseRedirect("/%s" %(new_join_old.ref_id))
context = {"form": form}
template = 'home.html'
return render(request, template, context)
def share(request, ref_id):
#try:
join_obj = Join.objects.get(ref_id=ref_id)
friends_referred = Join.objects.filter(friend=join_obj)
count = join_obj.referral.all().count()
ref_url = settings.SHARE_URL + str(join_obj.ref_id)
context = {"ref_id": join_obj.ref_id, "count": count, "ref_url": ref_url}
template = "share.html"
return render(request, template, context)
#except:
#raise Http404
Error message I am getting after commenting out exception is:
DoesNotExist at /admin
Join matching query does not exist. Lookup parameters were {'ref_id': u'admin'}
Urls.py includes following.
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^$', 'joins.views.home', name='home'),
url(r'^(?P<ref_id>.*)$', 'joins.views.share', name='share'),
)
Your regular expression in line
url(r'^(?P<ref_id>.*)$', 'joins.views.share', name='share'),
matches admin/ as well you should use something less "greedy".

name 'snippets' is not defined [Django Rest]

I am following the tutorial of Django REST Framework and when I try to curl http://127.0.0.1:8000/snippets, I get that error. I am new to Python/the Framework and Django, so I don't have a clue where to look at.
The code seems to be pretty fine, since I have double checked on github. Where do you think the error should be?
Snippet/serializers.py
from rest_framework import serializers
from snippets.models import Snippet
class SnippetSerializer(serializers.Serializer):
class Meta:
model = Snippet
fields = ('id', 'title','code','linenos','language','style')
class SnippetSerializer(serializers.Serializer):
pk = serializers.Field() # Note: `Field` is an untyped read-only field.
title = serializers.CharField(required=False,
max_length=100)
code = serializers.CharField(widget=widgets.Textarea,
max_length=100000)
linenos = serializers.BooleanField(required=False)
language = serializers.ChoiceField(choices=LANGUAGE_CHOICES,
default='python')
style = serializers.ChoiceField(choices=STYLE_CHOICES,
default='friendly')
def restore_object(self, attrs, instance=None):
"""
Create or update a new snippet instance, given a dictionary
of deserialized field values.
Note that if we don't define this method, then deserializing
data will simply return a dictionary of items.
"""
if instance:
# Update existing instance
instance.title = attrs.get('title', instance.title)
instance.code = attrs.get('code', instance.code)
instance.linenos = attrs.get('linenos', instance.linenos)
instance.language = attrs.get('language', instance.language)
instance.style = attrs.get('style', instance.style)
return instance
# Create new instance
return Snippet(**attrs)
snippet/urls.py
from django.conf.urls import patterns, url
urlpatterns = patterns('snippets.views',
url(r'^snippets/$', 'snippet_list'),
url(r'^snippets/(?P<pk>[0-9]+)/$', 'snippet_detail'),
)
snippet/views.py
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
class JSONResponse(HttpResponse):
"""
An HttpResponse that renders its content into JSON.
"""
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
#csrf_exempt
def snippet_list(request):
"""
List all code snippets, or create a new snippet.
"""
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return JSONResponse(serializer.data)
elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = SnippetSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JSONResponse(serializer.data, status=201)
return JSONResponse(serializer.errors, status=400)
#csrf_exempt
def snippet_detail(request, pk):
"""
Retrieve, update or delete a code snippet.
"""
try:
snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'GET':
serializer = SnippetSerializer(snippet)
return JSONResponse(serializer.data)
elif request.method == 'PUT':
data = JSONParser().parse(request)
serializer = SnippetSerializer(snippet, data=data)
if serializer.is_valid():
serializer.save()
return JSONResponse(serializer.data)
return JSONResponse(serializer.errors, status=400)
elif request.method == 'DELETE':
snippet.delete()
return HttpResponse(status=204)
In your file urls.py, put quotes around snippets.urls.
Like this:
url(r'^',include('snippets.urls'))
Use serializers.ModelSerializer:
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ('id', 'title','code','linenos','language','style')
This lets DRF know to extract the fields and their types from the specified model class Snippet as parameters for the serializer. Your current version is using only serializers.Serializer. With the base Serializer class you need to define field variables for it to work. like this example:
class SnippetSerializer(serializers.Serializer):
pk = serializers.Field() # Note: `Field` is an untyped read-only field.
title = serializers.CharField(required=False,
max_length=100)
code = serializers.CharField(widget=widgets.Textarea,
max_length=100000)
linenos = serializers.BooleanField(required=False)
language = serializers.ChoiceField(choices=LANGUAGE_CHOICES,
default='python')
style = serializers.ChoiceField(choices=STYLE_CHOICES,
default='friendly')
Additionally, its probably a better practice for you to import your views from views.py like so:
from django.conf.urls import patterns, url
import views
urlpatterns = patterns('',
url(r'^snippets/$', views.snippet_list, name='snippet-list'),
url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail, name='snippet-detail'),
)
for me, what solved the problem is the file name.
make sure that the file serializers itself have no spelling issues and his name is the same as in the code.

Categories