Django Encrypt the URL (PK and ID) - django

I am trying to find best solution for encrypting my URL, I have found some old versions, for python 2.2.
I need to set my URLs, not to display like this:
.com/AddPost/1/ and .com/PostDetail/40.
But something like this:.com/AddPost/DMQRzZWMDdGQtbndzBHNsawN0aXRsZQR0ZXN0AzcwMQR3b2UDMjQwMjEwNQ
That you can not guess what PK is and access that page:
URLs:
urlpatterns = [
path('PostDetail/<int:pk>', PostDetail.as_view(), name ='post_detail'), ]
view.py:
class PostDetail(DetailView):
model = Post
template_name = 'post_detail.html'
def get_context_data(self, *args,**kwargs):
post = Post.objects.all()
context = super(PostDetail,self).get_context_data(*args,**kwargs)
stuff = get_object_or_404(Post,id=self.kwargs['pk'])
total_likes=stuff.total_likes()
context['total_likes'] = total_likes
return context

Related

How can use slug for all urls in django without anything before or after?

I want all djaango urls use slug field without any parameter before or after, by default
just one url can use this metod
Views.py
class ArticleDetail(DetailView):
def get_object(self):
slug = self.kwargs.get('slug')
article = get_object_or_404(Article.objects.published(), slug=slug)
ip_address = self.request.user.ip_address
if ip_address not in article.hits.all():
article.hits.add(ip_address)
return article
class CategoryList(ListView):
paginate_by = 5
template_name = 'blog/category_list.html'
def get_queryset(self):
global category
slug = self.kwargs.get('slug')
category = get_object_or_404(Category.objects.active(), slug=slug)
return category.articles.published()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['category'] = category
return context
urls.py
urlpatterns = [
path('<slug:slug>', ArticleDetail.as_view(), name="detail"),
path('<slug:slug>', CategoryList.as_view(), name="category"),
]
This is my django blog codes,
I don't want write article or category & ... in urls, just slug
mysite .com/article-slug
...
mysite .com/category-slug
It will always trigger the Article view, regardless if there is an Article for that slug. You thus should make the URL patterns non-overlapping such that the other views can be triggered, for example with:
path('article/<slug:slug>/', Article.as_View(), name="articledetail"),
path('category/<slug:slug>/', Category.as_View(), name="category"),
path('product/<slug:slug>/', Product.as_View(), name="productdetail"),
If you want a path that accepts a single slug, you should define a view that looks if there is an Article with that slug, if that is not the case a Category and if that is not the case a Product you thus implement that logic in the view, not in the URL patterns.
#WillemVanOlsem is right, you will have to write a view like this:
from django.http import HttpResponseNotFound
def slug_router(request, slug):
if Category.objects.filter(slug=slug).exists():
return CategoryList.as_view()(request, slug=slug)
elif Article.objects.filter(slug=slug).exists():
return ArticleDetail.as_view()(request, slug=slug)
else:
return HttpResponseNotFound('404 Page not found')
And then
urlpatterns = [
path('<slug:slug>', slug_router, name="slug"),
]
... if I'm not mistaken. This should be the jist of it.
I didn't test this code, just typed it in here, so let me know if it doesn't work, I'll help to fix it.
Note that you'll have a preference if there are Articles with the same slug as some Categories.

Can you pass an argument to ListView in Django?

I am creating a Fixture webapp with Django. I have written the class below, which displays a list of first team fixtures. Can I rewrite it as TeamView, then pass the team_id?
class FirstView(generic.ListView):
template_name = 'fixtureapp/team.html'
context_object_name = 'fixtures'
def get_queryset(self):
"""return all first team matches"""
return Match.objects.filter(team_id=1).order_by('date')
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
data['page_title'] = '1st Team Fixtures'
return data
I have the following urls, how would I rewrite these to match?
urlpatterns = [
path('', views.HomeView.as_view(), name='home'),
path('first', views.FirstView.as_view(), name='first'),
path('second', views.SecondView.as_view(), name='second'),
as you can see I have currently created a second class called SecondView this is almost a carbon copy of FirstView, not very DRY
I can give you a brief of how it works, you can apply rest of the logic. Basic idea is to use slug.
In your html you can give the slug name with the url:
In urls.py, get that slug :
path('team/<slug:teamid_slug>/', views.TeamView.as_view(), name='team_by_id'),
Your Views should filter the query based on this slug, if no slug given it will give all the Match record. You can apply some other logic what fits to you.
class TeamView(generic.ListView):
queryset = Match.objects.all().order_by('date')
template_name = 'fixtureapp/team.html'
context_object_name = 'fixtures'
def get_queryset(self):
"""return all team_id team matches"""
return Match.objects.filter(team_id__slug=self.kwargs.get('teamid_slug')).order_by('date')
Also please have a look at this documentation of Dynamic Filtering

Django, getting data in different page from view

Hello I am new to Django, I am currently working on a project but I can`t figure out how I should do something.
Right now I am at the page
home/stats/ID/LANGUAGE
but inside this page I want a "edit" button, once clicked I want to go to:
home/stats/ID/LANGUAGE/edit/
I just want to get the same data from home/stats/ID/LANGUAGE again, but now in home/stats/ID/LANGUAGE/edit/
My view.py:
class StatsView(TemplateView):
template_name = 'home/stats.html'
analytics = build('analyticsreporting', 'v4', credentials=credentials)
def get(self, request, id, language):
min_date = "2018-12-01"
date01 = datetime.strptime(min_date, '%Y-%m-%d')
max_date = "2018-12-31"
date02 = datetime.strptime(max_date, '%Y-%m-%d')
print(date01)
print(date02)
if request.GET.get('date1'):
date1 = request.GET.get('date1')
pol1 = datetime.strptime(date1, '%Y-%m-%d')
date01 = pol1
print(date01)
if request.GET.get('date2'):
date2 = request.GET.get('date2')
pol2 = datetime.strptime(date2, '%Y-%m-%d')
date02 = pol2
print(date02)
if request.user.is_authenticated:
current_user = request.user.id
result = BlablaAuth.objects.filter(user=request.user)
if language == 'ALL':
blabla = Blabla.objects.filter(blabla=id)
prefix = '/blabla/' + id
if result and blabla.count() > 0:
analytics_result1 = self.analytics.reports().batchGet(
body={
"Google analytics reporting stuff"
analytics_result2 = self.analytics.reports().batchGet(
body={
"Google Reporting stuff"
return render(request, self.template_name, context={
"report1": analytics_result1.execute(),
"report2": analytics_result2.execute()
})
else:
apple = Apple.objects.filter(video=id)
prefix = '/apple/' + id
if result and apple.count() > 0:
analytics_result1 = self.analytics.reports().batchGet(
body={
"Google reporting analytics stuff"
analytics_result2 = self.analytics.reports().batchGet(
body={
"Google reporting analytics stuff"
return render(request, self.template_name, context={
"report1": analytics_result1.execute(),
"report2": analytics_result2.execute()
})
My urls.py:
from django.conf.urls import url
from django.contrib import admin
from home.views.views import HomeView, StatsView
from .views import views
from django.contrib.auth.decorators import login_required
app_name = "home"
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^stats/(?P<id>[0-9]+)/(?P<language>[a-zA-Z]+)/$',
login_required(StatsView.as_view()), name='stats'),
url(r'^stats/(?P<id>[0-9]+)/(?P<language>[a-zA-Z]+)/edit/$',
StatsView.edit_stats, name='stats_edit'),
url(r'^$', login_required(HomeView.as_view()), name='home'),
]
My button in stats.html:
<button><a href="{% url home:stats_edit auth.blabla.id apple.language %}">Edit</button>
Assuming your edit view will be based on a generic CBV (e.g. UpdateView), you can create a Mixin class that has a method get_context_data(self, **kwargs) and does all the stuff you now do in the get() method of your TemplateView. This method will automatically get called by your TemplateView and UpdateView and add the context to your rendering.
class AnalyticsMixin(object):
analytics = None # or some default that can be used by all subclasses.
# None is not a good default since it will raise an AttributeError when calling self.analytics.reports()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# all the stuff you do in get() method, using self.request and self.kwargs which are set by the `as_view()` method on the CBV
request = self.request
id = self.kwargs.get('id')
language = self.kwargs.get('language')
...
return context.update({
"report1": analytics_result1.execute(),
"report2": analytics_result2.execute()
})
then in your views:
class StatsView(AnalyticsMixin, TemplateView):
template_name = ...
analytics = ... # override here or if it depends on the request override in a method
# remove the get() method unless you do something that's not for both views.
# e.g. to override self.analytics if credentials depends on request
def get_context_data(self, **kwargs):
self.analytics = build('analyticsreporting', 'v4', credentials=self.get_credentials())
return super().get_context_data(**kwargs)
and for your edit view:
class EditStatsView(AnalyticsMixin, UpdateView):
template_name = ...
model = ... # name of model to update
# here add the form_class for the editing form if you customise it
# the context will have the form + the data from get_context_data()
way to pass data between two view is session . django support authenticate as well as anonymous session. just store the data as session key and retrieve it when ever you need it.

Django - Passing the model name to a view from url

How would I make it so I could pass the model name as a parameter in the url to a view? I would like to reuse this view and just pass the model name through to show a list of whatever model the parameter was.
Heres what I have so far
View
class ModelListView(ListView,objects):
model = objects
template_name = "model_list.html"
def get_context_data(self,**kwargs):
context = super(ModelListView, self).get_context_data(**kwargs)
context['listobjects'] = model.objects.all()
return context
URLS
url(r'^musicpack', MusicPackListView.as_view(), name='musicpack-list', objects = 'MusicPack'),
url(r'^instruments', MusicPackListView.as_view(), name='instrument-list', objects = 'Instrument'),
ANSWERED
Hey thanks for the answer
I've gone with the following and it seems to work.
View
class ModelListView(ListView):
template_name = "model_list.html"
def get_context_data(self,**kwargs):
context = super(ModelListView, self).get_context_data(**kwargs)
return context
URLS
#models
from inventory.views import MusicPack
from inventory.views import Instrument
#views
from inventory.views import ModelListView
url(r'^musicpacks', ModelListView.as_view(model = MusicPack,), name='musicpack-list'),
url(r'^instruments', ModelListView.as_view(model = Instrument,), name='instrument-list'),
I would pass perameter from urls to views like this:
VIEWS:
class ModelListView(ListView):
model = None
model_name= ''
object = None
template_name = "model_list.html"
def get_context_data(self,**kwargs):
context = super(ModelListView, self).get_context_data(**kwargs)
context['listobjects'] = model.objects.all()
return context
URLS:
url(r'^musicpack', ModelListView.as_view( model= MusicPackList,model_name= 'music_pack_list' object = 'MusicPack')),
url(r'^instruments', ModelListView.as_view( model=InstrumentPackList,model_name= 'instrument_pack_list', object= 'InstrumentPack'))

Passing more than one view to template

I have a page that should show an event and the presentations of this event. In my code they are not related (I still have to fix that). On the home page, which receives the event and the lectures, the view is like this:
views.py
class EventoView(ListView):
model = Evento
template_name = 'home.html'
context_object_name = 'evento_list'
queryset = Evento.objects.all().order_by('-data')[:1]
class RegistroView(ListView):
model = Registro
template_name = 'home.html'
context_object_name = 'registro_list'
queryset = Registro.objects.all()
The problem is that I can only pass the Event object, the object of Registration, which show lectures Indexed must also be passed, however, only accepts a Django view for url.
urls.py
urlpatterns = patterns('',
url(r'^$', EventoView.as_view(), name='home'), #I can't pass two views
url(r'^cadastro/', CriarRegistroView.as_view(), name='cadastro'),
url(r'^contato/', CriarContatoView.as_view(), name='contato'),
url(r'^sobre/', SobreView.as_view(), name='sobre'),
url(r'^admin/', include(admin.site.urls)),
)
How can I solve this problem?
Thanks.
it looks like you can override ListView.get_context_data
class RegistroView(ListView):
model = Evento
def get_context_data(self, **kwargs):
context = super(RegistroListView, self).get_context_data(**kwargs)
context['registros'] = Registro.objects.all()
context['eventos'] = Evento.objects.all().order_by('-data')[:1]
return context
I don't have experience with ListViews so i don't know if i am using it as it is supposed to be used, or not