Hello StackOverFlow Members, before i get down to the point, let me retrace my thought/process here to help further slim down my issue. When i click a location object in "location_tree.html" it would redirect me to a new page, "location.html", displaying the location name and its type. From the very same page, the name would be a hyperlink to another page with more details about the "location".
Above is the general flow i want, but when i attempt to click the name from location.html, it redirects me to this error:
NoReverseMatch at /accounts/location/2/
Reverse for 'continent' with keyword arguments '{u'pk': 2}' not found. 1 >pattern(s) tried: ['accounts/location/(?>P\d+)/location_continent/(?P\d+)/']
Some key things to note, i am using python2.7. Lastly, when i remove the {% url %} from location.html everything works perfectly fine.
Here is my working code,
App/models.py:
class Location(models.Model):
title = models.CharField(max_length=255)
location_type = models.CharField(max_length=255, choices=LOCATION_TYPES)
parent = models.ForeignKey("Location", null=True, blank=True,
related_name="parent_location")
def __unicode__(self):
return self.title
class Continent(models.Model):
title = models.CharField(max_length=255)
location = models.OneToOneField(Location, on_delete=models.CASCADE, primary_key=True)
is_an_island = models.BooleanField(default=False)
def __unicode__(self):
return self.location.title
App/views.py:
def view_page_location(request, location_id):
location = Location.objects.get(id=location_id)
if location.location_type == 'Continent':
continent = Continent(location=location, is_an_island=False)
return render(request, 'accounts/location.html', {'location':location, 'continent':continent})
def view_continent(request, pk):
get_continent=get_object_or_404(Continent, pk)
return render(request, 'accounts/location_continent.html', {'get_continent':get_continent})
Project/urls.py:
from App.views import *
url(r'^accounts/location/(?P<location_id>\d+)/', view_page_location, name='location'),
url(r'^accounts/location/(?P<location_id>\d+)/location_continent/(?P<pk>\d+)/', view_continent, name='continent'),
Templates,
location_tree.html:
{% for child in locations %}
{% if child.parent == location %}
<ul>
{{ child }}
location.html:
{% if location.location_type == 'Continent' %}
<h2> Location: {{ location.title }}</h2>
<h3> Type: {{ location.location_type }} </h3></br>
location_continent.html:
<p> hello </p>
I left location_continent pretty generic because i wanted to see if i can get it to work. I feel that something is wrong somewhere in my Urls.py or maybe i'm not properly constructing my views.py.
So the BIG question is, what changes/modifications do i need to alter in order to fix that error? I can't see it myself so i turn to 'you'. Any links for me to read up on and find the answer myself is appreciated as well. I hope my question is clear and not vague.
Two issues.
Your continent url in the location.html doesn't provide location_id argument, you provided only pk. Change it to something like:
{{ location.title }}
In the urls.py, you must add $ at the end of the location url, else there is going to be confusion between location and continent urls. $ has a special meaning in regular expression and means that it requires that the pattern matches the end of the string. Change urls to:
url(r'^accounts/location/(?P<location_id>\d+)/$', view_page_location, name='location'),
url(r'^accounts/location/(?P<location_id>\d+)/location_continent/(?P<pk>\d+)/', view_continent, name='continent')
Related
I am working on a Django project and I want to retrieve the category name in my template like Adventure, Hiking.. but instead, it's displaying ids of the category like 1,2,3. Instead of displaying the name of the category. Can someone help me out with this?
{% for data in tourData %}
{{data.category}}
{% endfor %}
models.py
class Tour(models.Model):
category_choices=[('1','Adventure'),('2','Trekking'),('3','Hiking')]
category=models.CharField(max_length=1,choices=category_choices,default='1')
view.py
def recommendations(request):
if request.method=='POST':
contents=Tour.objects.all()
category1= request.POST['category'] #Retrieves the category entered by the user
category2=request.POST['place']
tourData = Tour.objects.all().filter(category=category1,place=category2).order_by('-rating').values()
context={
'tourData':tourData
}
return render(request,"base/recommendations.html",context)
else:
tourData=Tour.objects.all().order_by('-rating').values()
context={'tourData':tourData
}
return render(request,"base/recommendations.html",context)
You need to use get_field_display in your template, i.e.
{{ data.get_category_display }}
This will show the second tuple value in your model choices rather than the first (the first is what actually goes into the database).
As an aside, I would recommend changing the format of your tourData variable from camelCase to snake_case - tour_data - it's more pythonic.
I would like to write a filter which replaces some $variables$ in my streamfield text. What is the best way to do this in my "Page" model? I tried the following but it is sometimes not working if I save my model as draft and publish it afterwards. Does anyone know a better way doing this?
class CityPage(Page, CityVariables):
cityobject = models.ForeignKey(CityTranslated, on_delete=models.SET_NULL, null=True, blank=True)
streamfield = StreamField(BasicStreamBlock, null=True, blank=True)
content_panels = Page.content_panels + [
FieldPanel('cityobject', classname="full"),
StreamFieldPanel('streamfield'),
]
def get_streamfield(self):
for block in self.streamfield:
if type(block.value) == unicode:
block.value = self.replace_veriables(block.value)
elif type(block.value) == RichText:
block.value.source = self.replace_veriables(block.value.source)
else:
print "notimplemented"
return self.streamfield
And this is just the class which replaces $variables$ with values from my database.
class CityVariables():
def replace_veriables(self, repstr):
reprules = self.get_city_context()
for key, value in reprules.iteritems():
repstr = repstr.replace(key, value)
return repstr
def get_city_context(self):
context = {}
if self.cityobject.population:
context['$population$'] = unicode(self.cityobject.population)
if self.cityobject.transregion:
context['$region$'] = unicode(self.cityobject.transregion)
return context
class BasicStreamBlock(blocks.StreamBlock):
h2 = blocks.CharBlock(icon="title", classname="title")
h3 = blocks.CharBlock(icon="title", classname="title")
h4 = blocks.CharBlock(icon="title", classname="title")
h5 = blocks.CharBlock(icon="title", classname="title")
paragraph = blocks.RichTextBlock(icon="pilcrow")
image = ImageChooserBlock(label="Image", icon="image")
aligned_html = blocks.RawHTMLBlock(icon="code", label='Raw HTML')
Here is a way to simply make the templated (converted) html output from streamfield from within your CityPage model.
Overview:
Use Python's built in basic Template system (or Python 3 docs), it is easy and will save you the hassle of dealing directly with the substitution.
Python's built in Template system uses $variablename not $variablename$ but works well and can be configured if really needed.
Avoid trying to build up the blocks within your streamfield manually, best to just to something like str(self.streamfield) which will force it to render into nice HTML.
Remember you can customise the html for any streamblock using class Meta: template = ... see docs.
Once we have our HTML output from the streamfield, we can use the string.Template class to create our output text by providing a dict of the template names and what to replace them with. Template variable names should not have the $ symbol in them (variablename not $variablename), the library takes care of that for you, it also takes care of basic string conversion.
For the sake of simplicity, I used a helpful model_to_dict util from Django to make the CityObject into a dict to pass directly to the template (think of this as your context for Django templates).
Note: This means that your $region would not work, it would need to match the fieldname eg. $transregion - or just change the fieldnames. It makes it easier for reading the code later if all the variables/fieldnames match anyway.
Before we can use this output in our final city_page.html template, we will need to mark it as safe for Django to render directly. Important: please be really careful about this as it means someone could save javascript code to the CityObject an it would run in the frontend, you may want another layer after model_to_dict to clear any potential js code.
Example: myapp/models.py
from django.forms.models import model_to_dict
from django.utils.safestring import mark_safe
from string import Template
# other imports... Page, etc
class CityPage(Page):
cityobject = models.ForeignKey(
CityTranslated, on_delete=models.SET_NULL, null=True, blank=True)
streamfield = StreamField(BasicStreamBlock, null=True, blank=True)
content_panels = Page.content_panels + [
FieldPanel('cityobject', classname="full"),
StreamFieldPanel('streamfield'),
]
def get_templated_streamfield(self):
# using str is a quick way to force the content to be rendered
rendered_streamfield = str(self.streamfield)
# will generate a dict eg. {'population': 23000, 'transregion': 'EU'}
# will not convert to values string/unicode - but this is handled by Template
template_variables = model_to_dict(self.cityobject)
template = Template(rendered_streamfield)
# using safe_substitute will **not** throw an error if a variable exists without a value
converted = template.safe_substitute(template_variables)
# as we have html markup we must mark it as safe
return mark_safe(converted)
Example: myapp/template/city_page.html
{% extends "base.html" %}
{% load wagtailimages_tags %}
{% block content %}
{% include "base/include/header.html" %}
<div class="container">
<div class="row">
<div class="col-md-6">
<em>Streamfield Original (without templating)</em>
{{ page.streamfield }}
</div>
<div class="col-md-2">
<em>Streamfield with templating</em>
{{ page.get_templated_streamfield }}
</div>
</div>
</div>
{% endblock content %}
I'm new to Django and trying to figure out the code to create URLs for categories for my objects. The way Its working now I have a URL for each category but I'm trying to make a shortcut so if I create more categories I don't have to add another URL to URLs.py.
The Model:
class Store(models.Model):
FOOTWEAR = "Footwear"
CLOTHING = "Clothing"
OUTERWEAR = "Outerwear"
ITEM_CATEGORY_CHOICE = (
(FOOTWEAR, 'Footwear'),
(CLOTHING, 'Clothing'),
(OUTERWEAR, 'Outerwear'),
)
category = models.CharField(
max_length=20,
choices=ITEM_CATEGORY_CHOICE,
null=True,)
Before I had a url for each category. I was able to set up the URL for specific category:
url(r'^category/(?P<category>[-\w]+)/$',
'collection.views.specific_category',
name="specific_category"),
In views is where I have the issue. I'm not sure what i'm suppost to be pointing to in the views:
def specific_category(request, category):
if category:
sneakers = Sneaker.objects.filter(category = "__").order_by('-date')
else:
sneakers = Sneaker.objects.all().order_by('-date')
Right now with the code as is the page opens up blank. I feel like the answer is right in my face and i can't see it. Is my model wrong? Pointing me to any resources that explain would also be much appreciated.
What you should do is create an html file which looks for a generic context variable, for example:
category_items.html
Category:
{{ category }}
Items:
{{ for item in items }}
{{ item.name }}
{{ endfor }}
That way, no matter what you filter in your views, you can still display the results using the same html page. Also, change category = '__' to category=category, so it will capture the category name from the url.
views.py
def specific_category(request, category):
if category:
sneakers = Sneaker.objects.filter(category=category).order_by('-date')
else:
sneakers = Sneaker.objects.all().order_by('-date')
return render(request, 'category_items.html', {'category': category, 'items': sneakers})
I've been trying to develop a django app for handling bar tabs... So far I can add tabs, add products to a tab, and delete products from a tab. Now, I wanted to use AJAX on the adding/removing products from a tab, and I don't know if I needed to use a form or not... Here is what I have so far:
models.py
class Product(models.Model):
name = models.CharField(max_length='70')
price = models.FloatField()
def __unicode__(self):
return self.name
class Tab(models.Model):
number = models.IntegerField()
name = models.CharField(max_length='50')
tabdate = models.DateTimeField('date created')
consumed = models.ManyToManyField(Product, through='ConsumedRelation')
def __unicode__(self):
return self.name
class ConsumedRelation(models.Model):
tab = models.ForeignKey(Tab)
product = models.ForeignKey(Product)
count = models.PositiveIntegerField(blank=True, null=True, default=1)
def __unicode__(self):
return str(self.product)
views.py
def addproduct(request, number, product):
tab = Tab.objects.get(number=number)
product = Product.objects.get(id=product)
add = ConsumedRelation.objects.create(product=product, tab=tab, count=1)
add.save()
context = {'tab': tab, 'product': product}
return render_to_response('addproduct.html', context)
def deleteproduct(request, number, consumedid):
tab = Tab.objects.get(number=number)
ConsumedRelation.objects.filter(id=consumedid).delete()
context = {'tab': tab}
return render_to_response('deleteproduct.html', context)
urls.py
url(r'^tabs/(?P<number>[0-9].*)/delete/(?P<consumedid>[0-9].*)/$', 'barcomandas.views.deleteproduct'),
url(r'^tabs/(?P<number>[0-9].*)/add/(?P<product>[0-9].*)/$', 'barcomandas.views.addproduct'),
singletab.html
<h1>{{ tab.name }} | {{ tab.number }}</h1>
<h2>Consumed</h2>
{% for consumed in consumedlist %}
X{{ consumed }}<br/>
{% endfor %}
<div id="addproducts">
{% for product in productlist %}
<li>{{ product.name }}</li>
{% endfor %}
</div>
addproduct.html
{{ product }} added to tab {{ tab.name }}
So for example, when I add some product, I have a useless page "product added to tab" because I can't do it without some html page so I can use the view. Does that make sense?
But I don't want to make this as a form because this will be used in a 7" tablet and I'm gonna have good sized buttons for each product since the bar I'm working can get very very busy sometimes, so I need that kind of speed.
Ideally I would have ajax on everything, with a list of the current open tabs on the left, and the tab-editing on the right column, with options to add products, close tab, and etc.
So what I would want is, there's the list of the products in singletab.html, with a "X" to the side of each product. You click on the X, the product fades, and the list and everything else is updated, without reloading the page.
Do you guys see any solution to that? Sorry about my english, not my main language.
PS:
This is also my first django app, so I'm sorry for any stupid mistakes..
Would a simple jquery get on for example (/tabnumber/add/product) be enough? And how would I implement it?
I am sorry I didn't understand your question properly except below lines.
there's the list of the products in singletab.html, with a "X" to the side of each product. You click on the X, the product fades, and the list and everything else is updated, without reloading the page.
I think you can try using JQuery. Its Javascript library that makes life easier for event handling and ajaxifying of pages.
For your fade out example you can see w3 example which is good place to start learning about JQuery. you can also refer Ajax with JQuery to understand how to use Ajax with JQuery.
Hopefully, it helps you or take you a step ahead..Best of luck :-)
from djangosphinx.models import SphinxSearch
def xx(request):
queryset =File.search.query('test')
#return HttpResponse(queryset)#<------1
return render_to_response('a.html',{'a':queryset})#<--------2
and
class File(models.Model):
name = models.CharField(max_length=200)
tags = models.CharField(max_length=200) # We actually store tags for efficiency in tag,tag,tag format here
objects = models.Manager()
search = SphinxSearch(index="test1")
a.html:
{% for i in a %}
Some value: {{i}}
{% endfor %}
Since you are not giving a lot of info, I will make a educated guess. You probably didn't build you search index. Try building it before quering, sphynx search in the sindex, not in the DB.