Django URL Path from DB file value - python

I am trying to create 'project' pages that have their paths generated with the
{{ project.title }} values, rather than the current method I have which uses ints. I don't quite understand how I can do this, but feel I am close?
Models.py
from django.db import models
# Create your models here.
class Project(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
technology = models.CharField(max_length=20)
image = models.FilePathField(path='projects/static/img/')
live = models.URLField()
source = models.URLField()
def __str__(self):
return self.title
Urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.project_index, name="projects"),
path("<int:pk>/", views.project_details, name="project_details"), # PK for Primary Key
]
Views.py
from django.shortcuts import render
from .models import Project
# Create your views here.
def project_index(request):
projects = Project.objects.all()
context = {'projects': projects}
return render(request, 'projects/project_index.html', context)
def project_details(request, pk):
project = Project.objects.get(pk=pk)
context = {'project': project}
return render(request, 'projects/project_details.html', context)
I figure path("<int:pk>/", will need to be a slug, but I just cannot figure out how to tie in the DB data.
Potentially context = {'project': project}?
Currently the url is http://127.0.0.1:8000/projects/1/ - I am looking for http://127.0.0.1:8000/projects/EXAMPLE/
Thanks

You have to add a SlugField to your models.py file:
Models.py
from django.db import models
from django.utils.text import slugify
# Create your models here.
class Project(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
technology = models.CharField(max_length=20)
image = models.FilePathField(path='projects/static/img/')
live = models.URLField()
source = models.URLField()
slug = models.SlugField(default="", blank=True, null=False, db_index=True)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
Views.py
from django.shortcuts import render
from .models import Project
# Create your views here.
def project_index(request):
projects = Project.objects.all()
context = {'projects': projects}
return render(request, 'projects/project_index.html', context)
def project_details(request, slug):
project = Project.objects.get(slug=slug)
context = {'project': project}
return render(request, 'projects/project_details.html', context)
Urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.project_index, name="projects"),
path("<slug:slug>/", views.project_details, name="project_details"),
]
Make sure to run makemigrations and then migrate.

urls.py
path("<title>/", views.project_details, name="project_details"),
views.py
def project_details(request, title: str):
project = Project.objects.filter(title=title).first()
if project is None:
titles = list(Project.objects.all().values_list('title', flat=True))
msg = f'Project(title=title) not found. Exist titles are: {titles}'
raise Exception(msg)
...

Related

Django : HttpRequest.__init__() takes 1 positional argument but 2 were given

So I simply want when I click on the particular article to output its slug, for example if the slug of the given article is django-rules then i want it to be outputted as django-rules when i click on it. just that
here is my model
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField()
body = models.TextField()
date = models.DateTimeField(auto_now_add = True)
#add in tubnail and author later
def __str__(self):
return self.title
def snippet(self):
return self.body[:50]+'...'
Here is my views.py
from datetime import date
from django.shortcuts import render
from .models import Article
from django.http import HttpRequest
# Create your views here.
def article_list(request):
articles = Article.objects.all().order_by('date')
return render(request,'articles/article_list.html', {'articles': articles} )
def article_detail(request, slug):
return HttpRequest(slug)
url.py
from posixpath import relpath
from django.contrib import admin
from django.urls import path
from django.views.generic import TemplateView
from . import views
app_name = 'articles'
urlpatterns = [
path('', views.article_list, name = 'list'),
path('<slug:slug>/', views.article_detail, name = 'detail'),
]
Please dont suggest to add as_view()
its not working.
Instead of return HttpRequest(slug), you need to return HttpResponse(slug).

How do I set my foreign key to the current user in my views

I am developing an app that needs users to login and create posts. The post model has an image and a caption (the user inputs) and a profile foreign key that should to automatically pick the logged in users profile.
The app however isnt autopicking the profile
Can someone spot what am doing wrong? I feel like the particular issue is in this line of code in my views
form.instance.profile = self.request.Image.profile
models
from django.db import models
from django.contrib.auth.models import User
import PIL.Image
from django.urls import reverse
# Create your models here.
class Image(models.Model):
image = models.ImageField(upload_to='images/')
caption = models.TextField()
profile = models.ForeignKey('Profile', default='1', on_delete=models.CASCADE)
likes = models.ManyToManyField(User, blank=True)
created_on = models.DateTimeField(auto_now_add=True)
def get_absolute_url(self):
return reverse('vinsta-home')
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
photo = models.ImageField(upload_to = 'photos/',default='default.jpg')
bio = models.TextField(max_length=500, blank=True, default=f'I love vinstagram!')
def __str__(self):
return f'{self.user.username}'
views
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import (ListView,CreateView,)
from .models import Image
def home(request):
context = {
'posts': Image.objects.all()
}
return render(request, 'vinsta/home.html', context)
class ImageListView(ListView):
model = Image
template_name = 'vinsta/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-created_on']
class ImageCreateView(LoginRequiredMixin, CreateView):
model = Image
fields = ['image', 'caption']
def form_valid(self, form):
form.instance.profile = self.request.Image.profile
return super().form_valid(form)
I think you're just about right as to which line isn't working. Instead of
form.instance.profile = self.request.Image.profile
try
form.instance.profile = Profile.objects.get(user=self.request.user)
(Don't forget to add the import for your Profile model.) I don't think Image exists as a property of request, but user does.

How to generate a "fake" slug in Django

I saw in a video I didn't save that you could do something like this:
www.mysite.com/post/12345/this-is-a-title
Where the 12345 is the id and what actually is used to do the query and the this-is-a-tilte part is automatically assigned when loading the page and you can actually write whatever you want there and will still load the page.
How do I set this up in my path and do I still need a SlugField?
If you have a model with a title:
class Post(models.Model):
title = models.CharField(max_length=128)
# …
You can make a path that looks like:
urlpatterns = [
# …
path('post/<int:pk>/<slug:slug>/', post_detail, name='post_detail'),
]
the view can then fetch the corresponding Post object and slugify the title. If the slug does not match, it redirects it to the correct slug:
from django.shortcuts import get_object_or_404, redirect
from django.utils.text import slugify
def post_detail(request, pk, slug):
post = get_object_or_404(Post, pk=pk)
post_slug = sluglify(post.title)
if slug != post_slug:
# in case the slug does not match, redirect with the correct slug
return redirect('post_detail', pk=pk, slug=post_slug)
# … logic to render the object …
you'll need SlugField field and the slugify function to auto-generate the slug from the title.
try the code below
models.py:
from django.db import models
from django.template.defaultfilters import slugify
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
class Post(models.Model):
"""A model holding common fields to Post model."""
slug = models.SlugField(_('slug'), max_length=255,
unique=True, null=True, blank=True,
help_text=_(
'If blank, the slug will be generated automatically '
'from the given title.'
)
)
title = models.CharField(_('title'), max_length=255,
unique=True,
help_text=_('The title of the post.')
)
[..]
def __str__(self):
return self.title
# Where the magic happens ..
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
urls.py:
path('post/<id:pk>/<slug:slug>/', views.post_detail, name='post_detail'),

How can I create a new url in a Django app?

I have implemented a model in a Django app and I would like add an url to handle the view for this model.
class Post(models.Model):
author = models.ForeignKey('auth.User')
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
Can you help me?
I would recommend the Django tutorial as well: https://docs.djangoproject.com/en/1.10/intro/tutorial01/
However, to answer your question, you could do a setup like this:
views.py:
from django.shortcuts import render
from .models import Post
def my_view(request):
posts = Post.objects.all()
return render(request, 'template.html', {'posts': posts})
urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.my_view, name='my_view')
]

Slug URL not working in Django

I am trying to setup Slug urls in a Django project. I keep getting a 404 error and can not find what I am missing. I have done this several times before but for some reason I must missing something.
models.py
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
# Create your models here.
class Pages(models.Model):
title = models.CharField(max_length=250, default="Add Title Here")
content = models.TextField(default="Add Content Here")
slug = models.SlugField(unique=True)
seo_title = models.CharField(max_length=250, default="Add Title Here")
seo_description = models.CharField(max_length=160, default="Add Seo Description")
active = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False, null=True)
updated = models.DateTimeField(auto_now_add=False, auto_now=True, null=True)
def __unicode__(self):
return self.title
class Meta:
unique_together = ('slug', 'title')
def get_absolute_url(self):
return reverse("single_page", kwargs={"slug": self.slug})
views.py
from django.shortcuts import render, get_object_or_404, Http404
# Create your views here.
from .models import Pages
def Single(request, slug):
try:
page = get_object_or_404(Pages, slug=slug)
context = {'page': page}
template = 'pages/page_detail.html'
return render(request, template, context)
except:
raise Http404
urls.py
from django.conf.urls import url, patterns
from . import views
urlpatterns = [
url(r'^(?P<slug>[\w-]+)/$', views.Single, name='single_page'),
]
Thanks guys for your help. I found the issue with some help from #vastlysuperiorma
Views.py
def single(request, slug):
try:
page = get_object_or_404(Pages, slug=slug)
context = {'page': page}
template = 'pages/page_detail.html'
return render(request, template, context)
except Pages.DoesNotExist:
raise Http404

Categories

Resources