Django urlpatterns when a category is included into URL - django

Django 3.0.6
urlpatterns = [
path('', HomeView.as_view(), name='home'),
path('{}'.format("admin/" if DEBUG else "dhjfsljdasdhje32/"), admin.site.urls), # Change admin url for security reasons.
path('image/', include(('image.urls', 'image'), namespace="image")),
path('polls/', include(('polls.urls', 'polls'), namespace="polls")),
path('applications/', include(('applications.urls', 'applications'), namespace="applications")),
]
def _get_categories_url_pattern():
"""
Organize urls with posts categories.
URL format:
<category>/<post_slug>
Example: linux/how_to_install_ubuntu/
"""
categories = Category.objects.all().values_list("slug", flat=True)
for category in categories:
urlpatterns.append(path('{}/'.format(category), include('post.urls')))
urlpatterns.append(path('draft/{}/'.format(category), include('post.urls')))
_get_categories_url_pattern()
Please, concentrate your attention on how categories in urls are handled.
Problems with this code:
When a new category is added in the admin site, Django project has
to be relaunched (at least with the built in dev server).
When last time I did python manage.py makemigrations it blew up. I
had to comment out anything having anything to do with
_get_categories_url_pattern. Then it made migrations. Now I can't reproduce this error anymore. But there seems to be some danger in this code.
Could you help me understand how to refactor this code for it to work at least without restarting the dev server when a new category is added.

The urls are loaded when the server starts, so you should avoid doing database queries there.
When you run migrate for a fresh database, your code will give the error because the category table hasn't been created yet. Once you have done the first migration, the code will run without error, but as you have noticed, the URLs will not update as new categories are added.
The normal approach is to add a slug kwarg to the URL pattern.
path('applications/', include(('applications.urls', 'applications'), namespace="applications")),
path('<slug:slug>', include('post.urls')),
path('draft/<slug:slug>', include('post.urls')),
Then in the view, use get_object_or_404 to make sure that the category exists.
from django.shortcuts import get_object_or_404
def category_view(request, slug):
category = get_object_or_404(Category, slug=slug)
...
One problem with this, is that <slug:slug>/ will match other URLs, e.g. /image/ or /polls/. In the above code, I've avoided that problem by putting <slug:slug> at the bottom of the URL patterns. Another option would be to use something like categories/<slug:slug>/ so that it doesn't match other URLs.

Related

urls not overlapping -- How to fix

I am trying to filter products either by brand or category but the url path will only execute path('<slug:brand_slug>/', views.product_list,name='product_list_by_brand'), since it appears first and would not execute the second.
Is there a way I can probably merge both paths or cause both paths to work independently without taking order into consideration.
from . import views
app_name = 'shop'
urlpatterns = [
path('', views.product_list, name='product_list'),
path('<slug:brand_slug>/', views.product_list,name='product_list_by_brand'),
path('<slug:category_slug>/', views.product_list,name='product_list_by_category'),
]
Thank you in advance for your response.
the problem is your upper url pattern is overriding second URL because of same slug and some other reasons.
FIX
change your URL pattern
path('<slug:brand_slug>/brand/', views.product_list,name='product_list_by_brand'),
path('<slug:category_slug>/', views.product_list,name='product_list_by_category'),
Another Thing You Can Do!
modify your function and url pattern.
def product_list(request, slug):
mode = request.GET.get("mode")
if mode.lower() == "brand":
''' your brand code '''
pass
else:
''' your category code '''
pass
path('<slug:slug>/', views.product_list,name='product_list_by_category'),
if you want to execute brand code your URL pattern would look like this.
127.0.0.1:8000/yourslug?mode=brand
and with this url pattern it will execute category code.
127.0.0.1:8000/yourslug
so by default it will execute category code.

how to redirect from HomePage(Page) to your custom app model

I've created an app "Blog". In my app I've got several models including "BlogIndex(Page)". When I run local server I find myself at "home_page.html". What I want is to start my local server at "blog_index.html". I know that I can set a root page at settings>site>localhost to make my "blog_index.html" a root page, but I can't do this because in my app I've got some other models that live at the same level as "BlogIndex(Page)" and they are children of the root which is "HomePage" so it would brake my code. So my question is: can I make a redirect from "HomePage(Page)" to my "BlogIndex" so that when i start my server I would be automatically redirected from "HomePage" to "BlogIndex"? How can I do it? How much it will affect the performance of the site and it's optimization?
I know that there is settings>redirect but it works only for inactive pages, but i need "HomePage" to be active.
Thank you.
Perhaps a better approach would be to display your blog posts (and any other models you want) on your homepage. Just override get_context(). See here: Wagtail Views: extra context
Update:
You can redirect by overriding the serve() method. For example, in your model, you would do something like:
# home/models.py
...
from django.http import HttpResponseRedirect
from django.urls import reverse
class HomePage(Page):
body = RichTextField(blank=True)
content_panels = Page.content_panels + [
FieldPanel('body', classname="full"),
]
def serve(self, request):
# Redirect to blog index page
return HttpResponseRedirect('/blog/')
# only do this if you're using urls.py and namespaces
# return HttpResponseRedirect(reverse('blog:index'))
More info: http://docs.wagtail.io/en/latest/reference/pages/model_recipes.html?highlight=serve()#overriding-the-serve-method

Reverse for 'password_reset_confirm'

Django==1.11.2
django-registration-redux==1.6
When I'm trying to reset password (http://localhost:8000/accounts/password/reset/), I occur at a page with headline Django administration, and breadcrumbs below: Home › Password reset. So, this is a part of Django functionality. This may be important, though, I don't know how. But anyway, this is not the functionality of django-registration-redux.
I input an email. And get this:
Reverse for 'password_reset_confirm' not found. 'password_reset_confirm' is not a valid view function or pattern name.
In django-registration-redux another name is used. Namely auth_password_reset_confirm.
Well, could you give me a kick here? My settings are below:
settings.py
INCLUDE_REGISTER_URL = True
INCLUDE_AUTH_URLS = True
urls.py
urlpatterns = [
url(r'^accounts/', include('registration.backends.default.urls')),
}
As mentioned in the bug report, registration must be earlier in order then admin. Not entirely sure why and apparently it's hard to fix, as this package is maintained by several Django core team members :).
From the docs, https://django-registration.readthedocs.io/en/2.2/quickstart.html#quickstart: django.contrib.auth must be in INSTALLED_APPS, I suggest adding before registration so that the package can override the core

In Django, how would I send a request for http://localhost:8000/ to a dynamic location

I'm new to django. The question I have is simple, but I couldn't really figure out what I needed from tutorials I have found online, nor in a book I have purchased on django.
I am writing a website to house an online comic. Let's say the url is:
http://localhost:8000/
I want a request for the base url to go to the most recent comic. If there are 13 comics, then I want a user requesting the above url to be sent to:
http://localhost:8000/13
At the same time, I want a user that types in http://localhost:8000/13 to go to the url specified. How would I do this?
For that you will need two url patterns which will map to two views. The first url is for the home page (http://localhost:8000/), and the second url is to see a specific comic (http://localhost:8000/<comic_id>). The first url however should redirect users to the latest comic using HttpResponseRedirect.
# assuming comic model similar to
class Comic(models.Model):
created = models.DateTimeField(auto_now_add=True)
# other fields...
# urlpatterns
url(r'^$', 'index', name='index'),
url(r'^(?P<comic_id>\d+)/$', 'comic', name='comic'),
# views
def index(request):
latest_comic = Comic.objects.order_by('-created')[0]
# or as suggested by Alasdair's comment
# latest_comic = Comic.objects.latest('created')
return HttpResponseRedirect(reverse('comic', kwargs={'comic_id':latest_comic.pk}))
def comic(request, comic_id):
comic = get_object_or_404(Comic, pk=comic_id)
# ...

Save in Django Admin sometimes fails

I have a portfolio page with django, and i'm noticing a strange behaviour when a try to save an edited entry. It saves, and then it seems that the redirect fails to catch the ID and then goes to a 404 page that says domain.com/admi/internal_error.html/ in the URL (note the admi, sometimes is ad or adm). It happens with both 'Save' and 'Save and continue editing'.
This is my model
from django.db import models
from ramonlapenta.portfolio.managers import EntryManager
from ramonlapenta.slughifi import slughifi
class Type(models.Model):
type = models.CharField(max_length=100)
def __unicode__(self):
return self.type
class Entry(models.Model):
type = models.ForeignKey(Type)
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100)
slug = models.SlugField()
description = models.TextField()
requirement = models.TextField()
solution = models.TextField()
url = models.CharField(blank=True, max_length=64)
published = models.BooleanField(db_index=True, default=True)
logo = models.ImageField(upload_to="logos")
image = models.ImageField(upload_to="portfolio", height_field='height', width_field='width')
height = models.CharField(max_length=3)
width = models.CharField(max_length=3)
objects = EntryManager()
def __unicode__(self):
return u"%s - %s" % (self.title, self.created)
class Meta:
verbose_name_plural = "entries"
def save(self, *args, **kwargs):
self.slug = slughifi(self.title)
super(Entry, self).save(*args, **kwargs)
And this is the admin.py
from django.contrib import admin
from ramonlapenta.portfolio.models import Type
from ramonlapenta.portfolio.models import Entry
from django import forms
class EntryAdmin(admin.ModelAdmin):
fieldsets = [
('Title', {'fields' : ['title']}),
('Address', {'fields' : ['url']}),
('Description', {'fields' : ['description','requirement','solution']}),
('Type', {'fields' : ['type']}),
('Image', {'fields' : ['logo', 'image']}),
]
list_display = ('title', 'created')
list_filter = ['created', 'type']
admin.site.register(Type)
admin.site.register(Entry, EntryAdmin)
This is my entry manager, where i only filter the results.
from django.db import models
class EntryManager(models.Manager):
def published(self):
return self.model.objects.filter(published=True).order_by('-id')
This is the general urls.py
from django.conf.urls.defaults import patterns, include, url
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^', include('site.pages.urls')),
(r'^', include('site.blog.urls')),
(r'^', include('site.portfolio.urls')),
(r'^admin/', include(admin.site.urls)),
)
And the portfolio urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('ramonlapenta.portfolio.views',
url(r'^portfolio/$', 'index', name="port-main"),
url(r'^portfolio/(?P<item_slug>[a-zA-Z0-9_.-]+)/$', 'detail', name="port-slug"),
url(r'^portfolio/type/(?P<type>[a-zA-Z0-9_.-]+)/$', 'type', name="port-type")
)
Thos is what i see with HttpFox:
Note: everything else works fine, even there it sometimes works fine, and the public site works fine too. The problem is just editing a portfolio entry.
Does anybody knows why is this happening and how can i fix it?
My guess is that the main url.py is catching some of the admin data (being that any admin action will be considered by all the other urlconfs.
Try to put the admin urls at the top:
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^', include('site.pages.urls')),
(r'^', include('site.blog.urls')),
(r'^', include('site.portfolio.urls')),
)
Edit: second guess
The key information is that second 302 in the request list. Someone (probably dreamost's apache) is eating the response and returning a redirect to a custom page.
In this case setting DEBUG = True is of no help, because the response would have anyway the same error.
This means two things:
You have an error somewhere in your Model's code, probably some attribute/field/property that's used to display the object.
To isolate the error, try to find a pattern on which specific values trigger the error and which values allows to load the admin form.
You can't see the django error page unless you either work locally in the development server (manage.py runserver) or disable custom error pages in dreamhost as other suggest.
Knowing your setup and what appears in server logs at the time you're saving an entry might help us locate a problem. It's likely that the cause is outside Django (since the bug is not reproducible under Django's development server).
Anyway, you might find some of these solutions relevant:
Django on dreamhost problem (old post, but symptoms described there are similar, might be relevant if you're running Django on FastCGI).
getting 500 internal server error with django on dreamhost (in short: just try re-create the whole setup and see if that helps).
Or you may want simply to google dreamhost django 500 in case you haven't already, seems like people frequently encounter similar problem while setting up Django on Dreamhost.
I'll be curious to see your urls.py . My guess is that the regex for the admin site is bogus.
For sure an error is happening when you save those entries and you should check your logs. Or try reproduce it with DEBUG=True
My guess is that you are using dreamhost and Dreamhost allows you to define custom error pages and "internal_error.html" is for the status 500 error page (see : http://wiki.dreamhost.com/Creating_custom_error_pages).
Try to have a look at your dreamhost error.log file.
The sure thing is that the problem comes from your dreamhost configuration and not your django code (since it is working properly in development with Django 1.2)