Creating tag-like feature in Django - python

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})

Related

Unable to retrieve Category name using templates in Django

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.

Django Reverse Error: NoReverseMatch at

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')

Using one model to filter another model in Django

I'm trying to access the information in my gadb_action model based on the action_ids in my gadb_vote model. I'm initially only getting the information for a particular legislator and then attempting to get the bills associated with the actions that legislator has voted on.
Right now, my action_list is only storing action_ids, but not the related information from the gadb_action model that I want to use in my template.
What is the best way to store that information outside of the for loop to be accessed by the template? Is there a way to write to an empty QuerySet?
Thanks in advance for any and all help!
view
def each_member(request,legislator_id):
each_member = get_object_or_404(gadb_legislator, legislator_id=legislator_id)
each_vote = gadb_vote.objects.filter(legislator_id=legislator_id)
action_list = []
for i in each_vote:
action = gadb_action.objects.filter(action_id=i.action_id)
action_list.append(action)
context = {
'each_member': each_member,
'each_vote': each_vote,
'action_list': action_list
}
return render(request, "eachmember.html", context)
models
class gadb_action(models.Model):
action_id = models.IntegerField(unique=False, max_length=4, primary_key=True)
bill_id = models.IntegerField(unique=False, max_length=12)
class gadb_vote(models.Model):
vote_id = models.IntegerField(unique=False, max_length=11,primary_key=True)
legislator_id = models.IntegerField(unique=False, max_length=11)
action_id = models.IntegerField(unique=False, max_length=11)
template
{% for i in action_list %}
{{i.bill_id}}
{{i.action_id}}
{% endfor %}
Your models are broken.
For a start, although it's not directly related to the question, you need to define your primary keys as AutoFields so that they are autoincremented every time a new entity is added. Otherwise you'll get all sorts of errors when you save a new row. (Even better, don't define the PK at all, and let Django add it automatically.)
Secondly, as lalo says, you should have ForeignKeys from Action to Bill, and from Vote to Action and Vote to Legislator. That way you can get the relevant information with a single query, and follow the foreign keys as required in your template.
(Also, Django already includes the app name in the underlying table name: no need to prefix everything with 'gadb'.)
class Action(models.Model):
bill = models.ForeignKey(Bill)
class Vote(models.Model):
legislator = models.ForeignKey(Legislator)
action = models.ForeignKey(Action)
View:
def each_member(request,legislator_id):
actions = Action.objects.filter(vote__legislator_id=legislator_id)
return render(request, "eachmember.html", {'action_list': actions})
Template:
{% for action in actions %}
{{ action.bill.name }}
{{ action.someotherfield }}
{% endfor %}

Technique to AJAX-ify this Django app

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 :-)

Looping through two objects in a Django template

I have an app objects and image objects which are linked to one another (the apps have images).
def index(request):
latest_apps_list = App.objects.all().exclude(approved=False).order_by('name')[:20]
app_images = Image.objects.filter(app__in=latest_apps_list).order_by('app__name')[:20]
t = loader.get_template('apps/index.html')
c = Context({
'latest_apps_list': latest_apps_list,
'app_images': app_images
})
return HttpResponse(t.render(c))
Now I want to loop through those images in my template. How would I do that with both variables? I tried using zip(), but this returned mysql errors as it calls for unsupported db queries. Is there another way?
Currently I have:
{% for app in latest_apps_list %}
...{{ app.name }}
{% endfor %}
This works. Of course, it doesn't return the images urls. (I'm using sorl-thumbnail btw.)
UPDATE Perhaps I'm just going about doing this the wrong way. Here's how I have my model:
class App(models.Model):
name = models.CharField(max_length=200)
# ...
class Image(models.Model):
app = models.ForeignKey(App)
image = models.ImageField(upload_to = "apps")
And my view is in the original part of the post above. It seems like I should somehow be making the app's properties and the image properties all one thing, without the need to zip in the view. Is this possible?
UPDATE 2 I solved this by greatly simplifying how the model is created. Here's what I did in case anyone else is trying to do this.
apps/admin.py: the image object is included as an ordinary field.
class AppAdmin(admin.ModelAdmin):
fieldsets = [
('Basic', {'fields':['name','desc','price','approved','image']}),
('Author', {'fields':['docs_url', 'preview_url']}),
]
list_display = ('name', 'desc', 'price', 'approved')
admin.site.register(App, AppAdmin)
apps/models.py: Just make image part of the app itself. No foreign keys needed.
class App(models.Model):
name = models.CharField(max_length=200)
# ...
image = models.ImageField(upload_to = "apps")
apps/views.py: Now the view just has one object to loop through. No weird sql queries needed.
def index(request):
latest_apps_list = App.objects.all().exclude(approved=False).order_by('name')[:20]
t = loader.get_template('apps/index.html')
c = Context({
'latest_apps_list': latest_apps_list,
})
return HttpResponse(t.render(c))
you should zip them in the view, and pass that zipped object to the template, and then iterate through them.
view:
def index(request):
latest_apps_list = list(App.objects.all().exclude(approved=False).order_by('name')[:20])
app_images = Image.objects.filter(app__in=latest_apps_list).order_by('app__name')[:20]
t = loader.get_template('apps/index.html')
c = Context({
'zipped_app_list': zip(latest_apps_list, list(app_images))
})
return HttpResponse(t.render(c))
template:
{% for app, image in zipped_app_list %}
{{ app }}
{{ image}}
{% endfor %}

Categories

Resources