Conflicting Django URL's - django

I have been chopping away at this for a few days with no clue as to why its not working. I have two views, one to list tools and one to list parts. I also have the list and detail URL's for both. Both list views work and the tool detail view works, but when I click on a part item to see the detail, the correct url appears in the browser, but I get an error shown in the screenshot below, which as you can see is trying to use the tool_detail view. Thank you for looking.
Here is my code for review:
url:
from .views import tool_list, part_list, tool_detail, part_detail
urlpatterns = [
url(r'^products/tools/$', tool_list, name='tool_list'),
url(r'^products/(?P<category>[^\.]+)/(?P<slug>[^\.]+)/$', tool_detail, name='tool_detail'),
url(r'^products/parts/$', part_list, name='part_list'),
url(r'^products/(?P<category>[^\.]+)/(?P<slug>[^\.]+)/$', part_detail, name='part_detail'),
]
view:
def tool_list(request):
tools = Tool.objects.prefetch_related('uploads').all()
return render(request, 'tool_list.html', {'tools': tools})
def tool_detail(request, **kwargs):
tool = get_object_or_404(Tool, slug=kwargs.get('slug'))
return render(request, 'tool_detail.html', {'tool': tool})
def part_list(request):
parts = Part.objects.prefetch_related('uploads').all()
return render(request, 'part_list.html', {'parts': parts})
def part_detail(request, **kwargs):
part = get_object_or_404(Part, slug=kwargs.get('slug'))
return render(request, 'part_detail.html', {'part': part})
models
class Part(Timestamp):
model_number = models.ForeignKey(ModelNumber, related_name='part_model_number')
category = models.ForeignKey(Category, related_name='part_category')
price = models.DecimalField(max_digits=10, decimal_places=2)
title = models.CharField(max_length=250)
slug = models.SlugField(help_text="slug-title-should-be-like-this")
...
class Tool(Timestamp):
model_number = models.ForeignKey(ModelNumber, related_name='tool_model_number')
price = models.DecimalField(max_digits=10, decimal_places=2)
title = models.CharField(max_length=250)
slug = models.SlugField(help_text="slug-title-should-be-like-this")
category = models.ForeignKey(Category, related_name='tool_category')
...

The first url pattern that matches is what Django will use to dispatch to a view. The 2nd url matches, so it's using the tool_detail view.

Related

Is it possible in Wagtail to use a proxy model with RoutablePageMixin?

My Wagtail site has certain items viewable in a gallery app, that the user can edit so that it would be also shown as an item in the shop app. It's strictly one-to-one, so I don't want them to be managing the items separately. I thought proxy models might be the best way to achieve this but I'm getting stuck and not finding very much documentation about using proxy models with Wagtail. Also possibly my regex is bad.
In app 'gallery':
class GalleryItem(Page):
parent_page_types = ['InstallationPage']
description = models.CharField(blank=True, max_length=250)
direct_sale = models.BooleanField("Direct Sale", default=False, help_text="Check this box to list this item for sale directly on your website.")
direct_sale_price = models.DecimalField("Sale price, $", blank=True, null=True, max_digits=6, decimal_places=2, help_text="Add more info about this item for the store page only.")
direct_sale_extra_description = models.CharField("Addtional sale description (optional)", blank=True, max_length=250, )
stock = models.IntegerField("Number in stock", blank=True, null=True,)
In app 'shop':
from gallery.models import GalleryImage
class Shop(Page):
def get_context(self, request):
context = super().get_context(request)
shop_items = ShopItem.objects.filter(Q(direct_sale=True) | Q(external_sale=True))
paginator = Paginator(shop_items, 24)
page = request.GET.get('page')
try:
pagin = paginator.get_page(page)
except PageNotAnInteger:
pagin = paginator.get_page(1)
context['shop_items'] = shop_items
return context
class ShopItem(GalleryItem, RoutablePageMixin):
class Meta:
proxy = True
parent_page_types = ['Shop']
#route(r"^shop/(?P<item_slug>[-\w]*)/$", name="item_view")
def item_view(self, request, item_slug):
# ????? Trying different things here:
context = self.get_context(request)
try:
item = ShopItem.objects.get(slug=item_slug)
except Exception:
item = None
if item is None:
# 404
pass
context["item"] = item
return render(request, "shop/shop_item.html", context)
The gallery item can be viewed at /gallery/item-slug. I would like to also view that item with a different template at /shop/item-slug, however I'm only able to achieve a 404 page.
RoutablePageMixin doesn't work in the way you're imagining. For it to work, the page has to exist in the page tree and be findable through a normal path-based URL; any routes defined within it are then handled relative to that path. So, if you have a RoutablePageMixin page at /foo/bar/baz/ that defines a view method with for #route(r'^shop/([-\w]*)/$'), that method will respond to URLs like /foo/bar/baz/shop/item-slug/. Since your tree doesn't have any pages that actually identify themselves as ShopItem, the route defined there will never be reached.
You don't really need a ShopItem model at all - all you're doing is responding to subpaths of /shop/, which is presumably the URL of your Shop page, so you can make Shop the RoutablePageMixin page instead:
from django.shortcuts import get_object_or_404
class Shop(RoutablePageMixin, Page):
def get_context(self, request):
# ... logic for the main /shop/ page, as before
#route(r'^([-\w]+)/$') # view method for subpaths of /shop/
def item_view(self, request, item_slug):
item = get_object_or_404(GalleryItem, slug=item_slug)
return render(request, "shop/shop_item.html", {'item': item})

matching django url with views using a model slug

my problem is that I can not establish a reverse match, most likely doing something wrong with my url definition (?). Ultimately what I am trying to do is the following:
User selects 2 location points which the 'new_pointview' view, saves into a DB. I also define a unique slug which contains location information and save it to the DB via the save() within the model. Then the user should be redirected to a url (pointview view) which uses the slug I created in the previous step i.e /pointview/slug. Here is the code:
models.py
class Points(models.Model):
starting_point_longitude = models.FloatField(null=True)
starting_point_latitude = models.FloatField(null=True)
ending_point_longitude = models.FloatField(null=True)
ending_point_latitude = models.FloatField(null=True)
url = models.SlugField(max_length=250, null=True, unique=True, blank=False)
def save(self, *args, **kwargs):
self.url = 'start_lon-{0}-start_lat-{1}-end_lon-{2}-end_lat-' \
'{3}'.format(self.starting_point_longitude,
self.starting_point_latitude,
self.ending_point_longitude,
self.ending_point_latitude)
super(Points, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('pointview', kwargs={'url': self.url})
views.py
def pointview(request, url):
point = get_object_or_404(Points, url=url)
content = {'starting_point_longitude':
point.starting_point_longitude,
'starting_point_latitude':
point.starting_point_latitude,
'ending_point_longitude':
point.ending_point_longitude,
'ending_point_latitude':
point.ending_point_latitude}
return render(request, 'points.html', {'user_bundle': content})
def new_pointview(request):
Points.objects.create(
starting_point_longitude=request.POST['starting_point_longitude'],
starting_point_latitude=request.POST['starting_point_latitude'],
ending_point_longitude=request.POST['ending_point_longitude'],
ending_point_latitude=request.POST['ending_point_latitude'],
)
points_filtered = Points.objects.filter(
starting_point_longitude=request.POST[
'starting_point_longitude']).filter(
starting_point_latitude=request.POST[
'starting_point_latitude'])
unique_url = points_filtered.values()[0]['url']
return redirect('/pointview/{0}/'.format(unique_url))
urls.py
urlpatterns = [
path(r'^pointview/(?P<url>[-\w]+)/$', views.pointview, name='pointview'),
path('^new_pointview/', views.new_pointview, name='new_pointview'),
]
The error:
The current path, pointview/start_lon-738949.9146592747-start_lat--153698.8751025315-end_lon-759997.8063993475-end_lat--168467.65638300427/, didn't match any of URL patterns. Hope you can give me some feedback here..
For future reference, it was a regex problem, using the following non intuitive regex solved it:
url('^pointview/(?P<url>start_lon[--W]+start_lat[--W]+end_lon[--W]+end_lat[--W]+)/', views.pointview, name='pointview')
I would be very interesting though if someone can give a more elegant solution.

how to get the list and detail views on the same one page website template

I'm trying to achieve this.
1. one page website with a list and detail view on the same template.
when the website loads, I have the thumbnails with all the list of items, I show that using a for loop and listview.
under that i have the same thing(items from the model) but in a form of carousel.( i can see all the items from the model in the slider with complete details)
these work fine.
but I want a detailed view in the same carousel slider. for eg: the user can see the list of items (thumbnail) and when clicked on a item , that particular item should be active in the slider,
1. I cant get the list and detail view to work on the same template.
2.i cant get the detailed view to work in the same carousel slider.
MODELS.PY
class Cheese(models.Model):
TYPES_CHOICES=(
('COW', 'COW'),
('GOAT', 'GOAT'),
('SHEEP', 'SHEEP'),
('BUFFALO', 'BUFFALO'),
('COW, GOAT & SHEEP', 'COW, GOAT & SHEEP'),
('COW & SHEEP', 'COW & SHEEP')
)
COUNTRY_CHOICES=(
('USA', 'USA'),
('UK','UK'),
('ITALY', 'ITALY'),
('FRANCE', 'FRANCE'),
('NETHERLANDS', 'NETHERLANDS')
)
origin = models.CharField(max_length=100)
title = models.CharField(max_length=100)
types = models.CharField(max_length=100, choices=TYPES_CHOICES)
about = models.TextField()
serve = models.CharField(max_length=1000)
image = models.ImageField(
null=True,
blank=True,
width_field="width_field",
height_field= "height_field")
width_field = models.IntegerField(default=550)
height_field = models.IntegerField(default=550)
country = models.CharField(max_length=50, choices=COUNTRY_CHOICES)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
def __unicode__(self):
return self.title
VIEWS.PY
class HomeView(generic.ListView):
template_name= 'cheese/home.html'
model = Cheese
def get(self, request):
queryset_list = Cheese.objects.all()
queryset_wine = Wine.objects.all()
form = FeedbackForm()
#basic search query
query = request.GET.get("q")
if query:
queryset_list = queryset_list.filter(
Q(title__icontains=query)|
Q(origin__icontains=query)|
Q(types__icontains=query)|
Q(about__icontains=query)
).distinct()
context={
'cheese': queryset_list,
'form': form,
'wine': queryset_wine,
}
return render(request, self.template_name, context)
URLS.PY
urlpatterns = [
url(r'^$', views.HomeView.as_view(), name='home'),
url(r'^(?P<pk>[0-9]+)$', views.HomeView.as_view(), name='cheesedetail'),
]
You are using here CBV for the HomeView in a horrible way that I did not almost notice that you ae using CBV. Do not ever override render in get method. I see you are overidding it because of appending some items to context. Then append items to context and do not override the render!
class HomeView(ListView):
template_name = 'cheese/home.html'
query = Cheese.objects.all()
def get_queryset(self):
queryset = super().get_queryset()
search_query = self.request.GET.get("q")
return queryset.filter(
Q(title__icontains=search_query)|
Q(origin__icontains=search_query)|
Q(types__icontains=search_query)|
Q(about__icontains=search_query)
).distinct()
def get_context(self):
context = super().get_context() # gets context from parent method0
context['form'] = FeedbackForm()
context['wines'] = Wine.objects.all()
return context
The main concept of using CBV's is that it tends to be more organised and it's based in inheritance.
You should consider using async javascript API calls (e. g. AJAX) in your templates. You can load/send your content dynamically to the server. Then you should create two separate views - ListView for Cheese with the list of cheese and then another DetailView with search form and getting data based on it. In the template you would define something like window.onload = fetchDetailView() and then the sender methods and you are done.

django modeltranslation 404

I'm trying to set up my app in two languages, however I'm getting 404 error on all app's urls, even though I've set up another app a while ago the exact same way.
models.py:
class New(models.Model):
title = models.CharField(max_length=300)
slug = models.SlugField(max_length=300, editable=False)
pub_date = models.DateTimeField(auto_now_add=True)
text = models.TextField()
def __unicode__(self):
return self.title
def save(self, *args, **kwargs):
if not self.id:
# Newly created object, so set slug
self.slug = slugify(self.title)
super(New, self).save(*args, **kwargs)
translation.py:
class NewTranslationOptions(TranslationOptions):
fields = ('title','text')
translator.register(New, NewTranslationOptions)
urls.py:
urlpatterns += i18n_patterns('',
url(r'^categories/$', 'products.views.categories_index', name='categories_index'),
url(r'^(?P<category_slug>[\w-]+)/$', 'products.views.specific_category', name='specific_category'),
url(r'^(?P<category_slug>[\w-]+)/(?P<product_slug>[\w-]+)/$', 'products.views.specific_product', name='specific_product'),
url(r'^news/$', 'news.views.news_index', name='news_index'),
url(r'^news/(?P<news_slug>[\w-]+)/$', 'news.views.specific_new', name='specific_new'),
)
Here you can also see urls of my other app products, it works just fine. If you need anything else please let me know.
Your specific_category and specific_product url patterns are catching urls from news app:
>>> re.match("(?P<category_slug>[\w-]+)", "news").groups()
('news',)
Reorder your urls patterns:
urlpatterns += i18n_patterns('',
url(r'^categories/$', 'products.views.categories_index', name='categories_index'),
url(r'^news/$', 'news.views.news_index', name='news_index'),
url(r'^news/(?P<news_slug>[\w-]+)/$', 'news.views.specific_new', name='specific_new'),
url(r'^(?P<category_slug>[\w-]+)/$', 'products.views.specific_category', name='specific_category'),
url(r'^(?P<category_slug>[\w-]+)/(?P<product_slug>[\w-]+)/$', 'products.views.specific_product', name='specific_product'),
)
Or, consider adding category/ prefix to patterns from products app:
url(r'^category/(?P<category_slug>[\w-]+)/$', 'products.views.specific_category', name='specific_category'),
url(r'^category/(?P<category_slug>[\w-]+)/(?P<product_slug>[\w-]+)/$', 'products.views.specific_product', name='specific_product'),

Outputting data from a django app

This is probably something really simple but for some reason I just can't seem to do it.
I'm trying to output some data from a blog (app) that I have created. The blog is working fine and out putting the content in the model fields that I have created and outputting to the templates I have specified.
But when tryingn to output the information out to the homepage nothing is showing. I'm fairly new to django and I think I might be missing something.
Do I need to include something to pages that are outside of the app? or do I need to set up somethin in the urls file?
I hope this makes sense as I don't think it's anything to complicated but I just think I'm missing something!
Thanks.
CODE:
url(r'blog/(?P<slug>[-\w]+)/$', 'blog.views.blog', name="blog"),
url(r'blog/', 'blog.views.blog_index', name="blog_index"),
def blog_index(request):
blogs = Blog.objects.filter(active=True)
return render_to_response('blog/index.html', {
'blogs':blogs,
}, context_instance=RequestContext(request))
def blog(request, slug):
blog = get_object_or_404(Blog, active=True, slug=slug)
return render_to_response('blog/blog_post.html', {
'blog': blog
}, context_instance=RequestContext(request))
class Blog(TimeStampedActivate):
title = models.CharField(max_length=255, help_text="Can be anything up to 255 character")
slug = models.SlugField()
description = models.TextField(blank=True, help_text="Give a short description of the news post")
content = models.TextField(blank=True, help_text="This is the main content for the news post")
user = models.ForeignKey(User, related_name="blog")
def __unicode__(self):
return self.title
#models.permalink
def get_absolute_url(self):
return ('blog', (), {
'slug': self.slug
})
Are you saying that going to mysite.com/blog/ is displaying correctly, but you also want it to be the sites index page at mysite.com?
If so, you need to add a new pattern to your projects urls.py file, like so:
url(r'^$', 'blog.views.blog_index')
Doing this will make mysite.com/blog/ and mysite.com route to the same view.