django many to many get attributes from other object - django

So I've been using django for a while now, and it's great. I've recently come across a little bit of a problem, and I'm sure there's a crappy way to get it to work, but what I've found with Django is that they've usually built in all sorts of mechanisms to do things for you. So what I'm not finding is this:
Here are my models:
class LandmarkGroup(models.Model):
Name = models.CharField(max_length=150)
Description = models.CharField(max_length=300, blank=True)
IsActive = models.BooleanField(default=True)
landmarks = models.ManyToManyField('Landmark', blank=True, null=True)
def __unicode__(self):
return self.Name
class Landmark(models.Model):
Name = models.CharField(max_length=150)
Description = models.CharField(max_length=300, blank=True)
Polygon = models.PolygonField()
IsActive = models.BooleanField(default=True)
objects = models.GeoManager()
def __unicode__(self):
return self.Name
I also have another model 'Team' that has a ManyToMany with LandmarkGroup, but I'm not going to post it here. I have a view where I query for all the landmarks that have a landmarkgroup that has a team with the same team id as the one I passed in:
def mobile_startup(request):
...
landmarkGroups = LandmarkGroup.objects.filter(team=device.team, IsActive=True)
landmarks = Landmark.objects.filter(landmarkgroup__team=device.team, IsActive=True)
...
return render_to_response('webservice/mobile_startup.html', {'landmarks': landmarks, 'landmarkGroups': landmarkGroups})
Everything works, the only problem I'm having is, I'm returning this all as JSON to the mobile app, and I want to provide the landmarkGroup id for the landmark, so in my template I've been trying to:
"landmarkGroup" : {{ landmark.landmarkgroup.id }} }
but that's not working. Does anyone know any way I can get the landmarkGroup ID for each landmark in my set? Do I need to extract it when I do the query? I know I can reference each landmarkGroup in the query because I can do 'landmarkgroup__team=device.team', but I need to able to reference this object in the template

LandmarkGroup.landmarksis a ManyToManyField,therefore one Landmark can belong to multiple groups.
You should be able to output them in your template like this:
{% for group in landmark.landmarkgroup_set.all %}{{ group.pk }}{% endfor %}
The first group belonging to the landmark should be accessible through {% landmark.landmarkgroup_set.all.0 %}

Related

Django models many to many relations

I'm moving my first steps with django and I'm trying to figure out a thing.
Suppose that we have a model.py made like this where NameEffect has a many to many relation
class Name(models.Model):
nameid = models.IntegerField()
name = models.CharField(max_length=255)
class Effect(models.Model):
effectid = models.IntegerField()
effect = models.TextField()
class NameEffect(models.Model):
nameid = models.IntegerField()
effectid = models.IntegerField()
start = models.PositiveIntegerField()
strand = models.PositiveIntegerField()
and I want to create a QuerySet where every entry contains name,effect,start,strand of the researched name. Fact is that the only solution I found was using raw SQL queries but I can't understand how to do it with the django models approach
You haven't defined any relationships here at all. You should identify the fields as ForeignKeys - and also define the implicit many-to-many relationship explicitly (although you don't actually need it for this particular query, but it'll definitely come in useful).
class Name(models.Model):
nameid = models.IntegerField(primary_key=True)
name = models.CharField(max_length=255)
effects = models.ManyToManyField('Effect', through='NameEffect')
class Effect(models.Model):
effectid = models.IntegerField(primary_key=True)
effect = models.TextField()
class NameEffect(models.Model):
name = models.ForeignKey('Name', db_column='nameid')
effect = models.ForeignKey('Effect', db_column='effectid')
start = models.PositiveIntegerField()
strand = models.PositiveIntegerField()
Now you can can query NameEffect directly to get the result you want.
data = NameEffect.objects.values('name__name', 'effect__effect', 'start', 'strand')
Also note, unless you know you really need just these fields, you should avoid using values and just query NameEffect using select_related:
name_effects = NameEffect.objects.select_related('name', 'effect')
and then access the values when you need them, eg in a template:
{% for obj in name_effects %}
{{ obj.name.name }}
{{ obj.effect.effect }}
{{ obj.start }}
{{ obj.strand }}
{% endif %}

Django-cms and autoblocks

I am working with online shop project. In product model, i have description field but it's empty. Somehow description data is stored in django-cms and autoblocks. From page, i can edit that description with django-cms. In template tag {% autoblock product.slug %} line is description.
In views.py, i have 'product' passed as context, but it's slug field has nothing to do with description. Also, if i write {{ product.slug }}, it gives me slug.
Also googled about Autoblocks, but what managed to find out it's this model:
class Autoblock(models.Model):
composite_id = models.CharField(max_length=150)
content = PlaceholderField('content')
site = models.ForeignKey(Site)
def __unicode__(self):
return self.composite_id
All of these fields has nothing to do with description.
Im struggling for long time to find where that description is. Any hints would be appreciated.
EDITED:
Product model:
class HBaseProduct(Product):
def __init__(self, *args, **kwargs):
super(HBaseProduct, self).__init__(*args, **kwargs)
image = models.ImageField(upload_to='images/', blank=True, max_length=300, verbose_name=_('Image'))
position = models.IntegerField(default=0, null=False)
description = models.TextField(null=True, blank=True)
Your description is in Autoblock.content, which is a ForeignKey to 'cms.Placeholder', which in turn holds a tree of 'cms.CMSPlugin' models in cmsplugin_set.
There's currently no straight-forward way to turn a Placeholder into a string (of HTML) to be used somewhere else outside of a request/response cycle.
Your best bet is to call Placeholder.render with a context object that holds a (fake) Django Request object. This will return the rendered contents and you can then store that in description.

Django prefetch_related failing to pass data to template

I have two Django models:
class Product(models.Model):
name = models.CharField(max_length=80, null=True)
is_active = models.BooleanField(default=False, null=False)
class Image(models.Model):
url = models.CharField(max_length=255, unique=True, null=False)
product = models.ForeignKey('Product', related_name='images')
I have a specific set of products. Each product has multiple images. The initial call looks something like:
product_list = product_list.filter(is_active=True).prefetch_related('images')
The product_list then gets whittled down depending on filters that are applied.
When I try to use the product_list within the display layer (template), I iterate the list of products. I can access all the product's fields except its images.
{{ product.images.0.id }} ==> empty
{{ product.images }} ==> returns Image.None
Running the code through the debugger, I can see the Image SQL query being executed, it's just that none of the data is passed to the template. There definitely is data there, as I can verify the query running it through my SQL client. Does any one know why this is happening? How do I get access to the Images for a given product?
I solved my issue. The prefetched data had to accessed like: product.images.all.0.id

how to make URL pattern accept variable arguments in Django?

my title may not be very clear.
The problem I am facing now is:
my view passes arbitrary keyword arguments to another view.
This view handles with what info(keyword arguments it gets)
This is the example of search feature I am implementing.
Each user will have a list of Saved Searches. when they click on any one of the items in Search list, they will be directed to a different view that process the information it receives
In the Searches model, I have defined a get_absolute_url method that constructs the URL pattern of each of these search (based on models in the field).
my model:
class Searches(models.Model):
SELLER_CHOICES=(('OWNER','owner'),
('DEALER','dealer'),
('BOTH','both'), )
#search_id = models.IntegerField(primary_key=True)
user = models.ForeignKey(User)
make = models.CharField(max_length=100, blank=True)
model = models.CharField(max_length=100, blank=True)
keywords = models.CharField(max_length=100, blank=True)
max_price = models.IntegerField(blank=True, null=True)
min_price = models.IntegerField(blank=True, null=True)
max_year = models.IntegerField(blank=True, null=True)
min_year = models.IntegerField(blank=True, null=True)
pic_only = models.NullBooleanField()
search_title_only = models.NullBooleanField()
owner_dealer_all = models.CharField(max_length=10,choices=SELLER_CHOICES,verbose_name='owner/dealer')
class Meta:
#managed = False
db_table = 'Searches'
verbose_name_plural = "Searches"
def __unicode__(self):
return "%s %s %s-%s" %(self.make,self.model,self.max_year,self.min_year)
def get_absolute_url(self):
return reverse('postings.views.detail',args=[model_to_dict(self.object)])
view:
class SearchListView(ListView):
model=Searches
template:
{% extends "base.html" %}
{% block content %}
{% for obj in object_list %}
<p>{{ obj }}</p>
{% endfor %}
{% endblock %}
you can see from the image, when I click the your searches, I get error;
Reverse for 'postings.views.detail' with arguments '({'owner_dealer_all': u'DEALER', 'pic_only': True, 'make': u'toyota', u'id': 3, 'min_year': 1990, 'min_price': 4000, 'user': 1, 'keywords': u'hybrid', 'search_title_only': True, 'model': u'prius', 'max_price': 20000, 'max_year': 2012},)' and keyword arguments '{}' not found. 0 pattern(s) tried: []
Basically, I dont know how to handle this in the URL pattern.
OR
IF THIS IS A BAD DESIGN, PLEASE PLEASE SUGGEST A SOLUTION
If you really need to have all the variables in the URL, then you need to pass the variables as params of a GET query, so your URL will look like this:
http://example.com/search?owner_dealer_all=DEALER&pic_only=True&make=toyota&id=3&min_year=1990&min_price=4000&user=1&keywords=hybrid&search_title_only=True&model=prius&max_price=20000&max_year=2012
But, I would strongly suggest that you keep that URL as separate from the Search.get_absolute_url result, as the latter is supposed to point to the actual model. So have that function return something like:
http://example.com/search/23465
where the number is the ID for your Search model instance. In that view, get all the saved details and make a search on them. If you actually don't need the data in your URL, simply opt for the latter version only.

Django display additional info for items in a list

I've a problem and i don't know the right way to solve it.
Basically,i've a mode, called Task:
class Task(models.Model):
#mto1: many task made of one template
template = models.ForeignKey(Template)
STATUS_CHOISE = (('PR', 'In process'), ('ST', 'Stopped'), ('FN', 'Finished'), ('DL', 'Deleted'),)
status = models.CharField(max_length=2, choices=STATUS_CHOISE, default='ST')
responses_required = models.IntegerField(default=0)
date_deadline = models.DateTimeField(auto_now=False, auto_now_add=False)
date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
which can have several answers
class Response(models.Model):
#mto1: many Responses generated for one task
task = models.ForeignKey(Template)
STATUS_CHOISE = (('PR', 'Process'), ('FN', 'Finished'))
status = models.CharField(max_length=2, choices=STATUS_CHOISE, default='ST')
date_finished= models.DateTimeField(auto_now_add=False, auto_now=True)
date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
ip_address=models.IPAddressField()
now, i would like to display all the task of one user (which comes from the template model, and this is done) with additional information about the answers, which are
- number of answer give (so which status is = FN)
- number of total answer (status FN or PR)
- and maybe some extra info.
i did this
#login_required
def TemplateList(request):
task_list = Task.objects.filter(user=request.user)
return render_to_response('task_list.html',{'task_list':task_list}, context_instance=RequestContext(request))
but this just display the data present in the model, what about the value i've to compute?
so far i did it with CustomTag, but it doesn't seem a clean solution. i would rather do the logic in the view and then use the template just for display results.
But: how can i add this value to each item of the Task List?
do i have to do like in this: Passing additional data to a template in Django so create the objects from scratch (which requires me some logic in the template as well since i've to match the value in the list with the objects i crate)? or is there any better solution?
i tried generic view ,like list_detail.object_list
in this way
def TaskListDetail(request):
return list_detail.object_list(
request,
queryset = Task.objects.filter(user=request.user),
template_name = 'task_list.html',
template_object_name = 'task_list',
)
but first, it does not show anything (while the other view shows data), second i don't know how to add extra data in a way that they are matched with the item of the list.
any suggestion?
You can add a method to your model.
class Task(models.Model):
#mto1: many task made of one template
template = models.ForeignKey(Template)
STATUS_CHOISE = (('PR', 'In process'), ('ST', 'Stopped'), ('FN', 'Finished'), ('DL', 'Deleted'),)
status = models.CharField(max_length=2, choices=STATUS_CHOISE, default='ST')
responses_required = models.IntegerField(default=0)
date_deadline = models.DateTimeField(auto_now=False, auto_now_add=False)
date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
def do_some_calculation(self):
#make funny things
return "foo"
In your template, you can access this with:
{% for taks in task_list %}
{{ task.do_some_calculation }}
{% endfor %}