I have 2 ArrayField lists and I want to join them using the zip method so I can Iterate through two lists in Django my django templates. But the output is treating each as array as seperate lists.
my model
class programas(models.Model):
title = models.CharField(unique=True, max_length=250)
script = ArrayField(models.CharField(max_length=8000, blank=True))
created_on = models.DateTimeField()
show_date = models.CharField(max_length=300, blank=True, null=True)
script_eng = ArrayField(models.CharField(max_length=8000, blank=True))
description = models.CharField(max_length=2000, blank=True, null=True)
description_eng = models.CharField(max_length=2000, blank=True, null=True)
url = models.CharField(max_length=200, blank=True, null=True)
show_id = models.IntegerField(primary_key=True)
id = models.IntegerField(null=True)
my view where I try to join the lists
def pages(request, id):
obj = programas.objects.get(id=id)
script = programas.objects.values_list('script')
script_eng = programas.objects.values_list('script_eng')
zip_scripts = list(zip(script , script_eng))
context = {'title': obj.title,
'show_date': obj.show_date,
'script' : obj.script,
'script_eng': obj.script_eng,
'description': obj.description,
'description_eng': obj.description_eng,
'show_id':obj.show_id,
'url': obj.url,
'zip_scripts' : zip_scripts,
}
return render(request, 'rtves/pages.html', context)
my code on the template page
{% if script %}
{% for text1, text2 in zip_scripts %}
<p> {{ text1 }} </p>
<p> {{ text2 }} </p>
{% endfor %}
{% else %}
<p>Nothing here</p>
{% endif %}
Have I got to make changes in the database?
programas.objects.values_list('script') gives you a list of the script fields of all the programas objects in the database. So, you effectively have a list of lists.
What you probably want is just the fields from the object you already have. So there's no need to use values_list there.
obj = programas.objects.get(id=id)
script = obj.script
script_eng = obj.script_eng
or, just pass them straight to the zip (note, there's no need for list anyway):
obj = programas.objects.get(id=id)
zip_scripts = zip(obj.script, obj.script_eng)
The reason it "doesn't" work on your perspective is that because when you cast querysets to built-in iterables, you don't get, an an iterable of the values but an iterable of one item tuples like
[('bill',), ('while',), ('participant',), ('you',)]
which, when you cast zip and list upon becomes even weirder, but you can simply flatter this with something like
list(map(o.itemgetter(0), qs))
In your case the whole code would be roughly
flatten = lambda qs: list(map(operator.itemgetter(0), qs))
script = flatten(programas.objects.values_list('script'))
script_eng = flatten(programas.objects.values_list('script_eng'))
# Then you can just zip them together and have what you wanted to begin with
zip_scripts = list(zip(script , script_eng))
Related
I have two models interrelated items and broken :
class Items(models.Model):
id = models.AutoField(primary_key=True)
item_name = models.CharField(max_length=50, blank=False)
item_price = models.IntegerField(blank=True)
item_quantity_received = models.IntegerField(blank=False)
item_quantity_available = models.IntegerField(blank=True)
item_purchased_date = models.DateField(auto_now_add=True, blank=False)
item_units = models.CharField(max_length=50, blank=False)
def __str__(self):
return self.item_name
class Broken(models.Model):
item = models.ForeignKey(Items, default=1, on_delete=models.CASCADE)
item_quantity_broken = models.IntegerField(blank=True)
item_broken_date = models.DateField(auto_now_add=True, blank=False)
item_is_broken = models.BooleanField(default=True)
date_repaired = models.DateField(auto_now=True, blank=True)
def __str__(self):
return self.item.item_name
I wrote this view function to retrieve data to a table into a template:
def broken_items(request):
br = Broken.objects.select_related('item').all()
print(br.values_list())
context = {
'title': 'broken',
'items': br,
}
return render(request, 'store/broken.html', context)
this is the executing query:
SELECT "store_broken"."id",
"store_broken"."item_id",
"store_broken"."item_quantity_broken",
"store_broken"."item_broken_date",
"store_broken"."item_is_broken",
"store_broken"."date_repaired",
"store_items"."id",
"store_items"."item_name",
"store_items"."item_price",
"store_items"."item_quantity_received",
"store_items"."item_quantity_available",
"store_items"."item_purchased_date",
"store_items"."item_units"
FROM "store_broken"
INNER JOIN "store_items"
ON ("store_broken"."item_id" = "store_items"."id")
looks like it gives me all the fields I want. In debugger it shows data from both tables,
so I wrote for loop in template,
{% for item in items %}
<tr>
<td>{{item.id}}</td>
<td>{{item.item_id}}</td>
<td>{{item.item_quantity_broken}}</td>
<td>{{item.item_broken_date}}</td>
<td>{{item.item_is_broken}}</td>
<td>{{item.date_repaired}}</td>
<td>{{item.item_name }}</td>
<td>{{item.item_item_quantity_received}}</td>
<td>{{item.item_quantity_available}}</td>
<td>{{item.item_purchased_date}}</td>
<td>{{item.items_item_units}}</td>
</tr>
{% endfor %}
The thing is this loop only gives me data from broken table only. I can't see data from Items table.
can someone help me to find the reason why other details are not showing?
Your items query is of Broken objects. So in order to access the Items values you need to change your table. For better understanding change your view like this:
brokens = Broken.objects.select_related('item').all()
context = {
'title': 'broken',
'brokens ': brokens,
}
and then your table:
{% for broken in brokens %}
<tr>
<td>{{broken.id}}</td>
<td>{{broken.item.pk}}</td> # This is the item id
<td>{{broken.item_quantity_broken}}</td>
<td>{{broken.item_broken_date}}</td>
<td>{{broken.item_is_broken}}</td>
<td>{{broken.date_repaired}}</td>
<td>{{broken.item.item_name}}</td>
<td>{{broken.item.item_quantity_received }}</td>
<td>{{broken.item.item_quantity_available}}</td>
<td>{{broken.item.item_purchased_date}}</td>
<td>{{broken.item.items_item_units}}</td>
</tr>
{% endfor %}
you loop over a List of Broken objects
to access the related item objects
item.item.item_name
I have a todo website that allows users to put a remind in a certain list, such as work, school, groceries, etc. However, I'm a bit lost on how to get the list name and their items to display.
Models.py:
class RemindList(models.Model):
parent_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=50)
class Reminder(models.Model):
remind_types = [('Regular', 'Regular'), ('Long Term', 'Long Term')]
title = models.CharField(max_length=100)
description = models.TextField()
remind_time = models.DateTimeField(blank=True)
parent_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
parent_list = models.ForeignKey(RemindList, on_delete=models.CASCADE, null=True)
type_of_remind = models.CharField(max_length=12, choices=remind_types, default='Regular')
complete = models.BooleanField(default=False)
Views.py:
#login_required(login_url='/login')
def home(request):
user = get_object_or_404(User, username=request.user.username)
context = {
'events': ToDoItem.objects.filter(parent_user=user),
'reminders': Reminder.objects.filter(parent_user=user, type_of_remind='Regular'),
'long_term_reminders': Reminder.objects.filter(parent_user=user, type_of_remind='Long Term'),
'remind_list_items': RemindList.objects.filter(parent_user=user),
}
return render(request, 'main/home.html', context)
I can pass through the list names, and I planned to just loop through them and add Reminder.objects.filter(parent_user=user, type_of_remind='Regular', parent_list=list_name) to context. However, theres no way to loop through them on the html side (can't do for loop because there are other context types), and you can't filter them on the html side (correct me if I'm wrong). Is there another way to do this?
Ok, it took me a few readings, but if what I understand is correct you want to be able to iterate over the ReminderList objects and also list out the Reminder items under each one.
My suggestion would be to add a method to ReminderList that returns the items in that list, you could then do something like this in your template
{% for list in reminder_lists %}
... List header stuff goes here ...
{% for item in list.get_reminder_items %}
... Print the item ...
{% endfor %}
{% endfor %}
(The Django templating language can be a little interesting in that object.identifier can map to either an attribute or an object method - this can be useful for cases like these).
I have two querysets. My first Queryset (services) has all of my service objects. My second Queryset (rating_values) has all of my rating values, where each index corresponds to the index in the services Queryset. For example services[1] corresponds with rating_values[1].
How do I loop through these two queries in an html page in django so so that I can display the service name along with the corresponding rating value?
To be clear, services contains service objects and rating_values contains decimal values. I pass the variables like this:
return render_to_response('services/display_services.html', {'user': request.user, 'services':services, 'rating_values': rating_values })
I would like to do something like this:
{% for service in services %}
<p> {{service.service_name}} : {{ corresponding rating_value}} </p>
Edit
Here is my Service model:
class Service(models.Model):
user_id= models.IntegerField(default=1)
service_name = models.CharField(max_length=100)
address = models.CharField(max_length=200)
def __str__(self): # __unicode__ on Python 2
return self.service_name
Here is my Rating Model:
class Rating(models.Model):
service_id= models.IntegerField(default=1)
service_name= models.CharField(max_length=200)
number_of_ratings = models.IntegerField()
total_rating_value = models.IntegerField()
rating_average = models.FloatField()
def __str__(self): # __unicode__ on Python 2
return self.service_name
Just to answer the original question as well.
If you for some reason don't want a database relation between the models, you could convert the querysets to lists and zip them in the view, turning the querysets to a list of tuples.
view:
return render_to_response(
'services/display_services.html',
context_instance={
'user': request.user,
'services_and_ratings': zip(
services.all(),
rating_values.all()
)
}
)
template:
{% for service, rating in services_and_ratings %}
<p> {{ service.service_name }} : {{ rating.rating_average }} </p>
You can establish the relationship right in the model.
class Rating(models.Model):
service= models.OneToOneField(Service, primary_key=True)
service_name= models.CharField(max_length=200)
number_of_ratings = models.IntegerField()
total_rating_value = models.IntegerField()
rating_average = models.FloatField()
....
You can then pass services and get the corresponding ratings..
{% for service in services %}
<p> {{service.service_name}} : {{ service.rating.rating_average }} </p>
I've got a setup where users can tag their posts, and then other uses can click on those tags to find more posts similar to those. I'm setting it up so that they can use more than one tag per post, split by commas. I can split the tags just fine in models.py, but I want to make them url safe as well and that doesn't seem to be happening.
Instead, it will show me the split words, but not with safe URLs.
This is my models.py:
def urlify(s):
# Remove all non-word characters (everything except numbers and letters)
s = re.sub(r"[^\w\s]", '', s)
# Replace all runs of whitespace with a single dash
s = re.sub(r"\s+", '-', s)
return s
class Post(models.Model):
created_by = models.ForeignKey(User, related_name='post_created_by')
pubdate = models.DateTimeField(default=timezone.now)
title = models.CharField(max_length=200, null=True, blank=True)
body = models.TextField(null=True, blank=True)
category = models.CharField(max_length=200, null=True, blank=True)
tags = models.CharField(max_length=200, null=True, blank=True)
last_updated = models.DateTimeField(default=timezone.now)
likes = models.ManyToManyField(User, related_name='post_likes')
def __unicode__(self):
return self.title
def split_tags(self):
alltags = self.tags.split(', ')
for tag in range(len(alltags)):
urlify(alltags[tag])
return alltags
in the template I'm returning this:
Tagged:
{% for tag in post.split_tags %}
{% if forloop.last %}
{{tag}}
{% else %}
{{tag}},
{% endif %}
{% endfor %}
Would it be better to run the urlify in the views instead of the models? It would be nice if I could display the tags as the user wrote them but keep them URL safe in the background.
In split_tags function you are only iterating alltags without saving result from urlify. You can do it in one line with list comprehension:
def split_tags(self):
return [urlify(tag) for tag in self.tags.split(', ')]
Your version need some changes:
def split_tags(self):
alltags = self.tags.split(', ')
result = []
for tag in alltags:
result.append(urlify(tag))
return result
Note that there is similar to your urlify function in django utils - slugify:
slugify()
Converts to lowercase, removes non-word characters
(alphanumerics and underscores) and converts spaces to hyphens. Also
strips leading and trailing whitespace.
I tried to get data from ManyToManyField but found not luck. Will you please help me?
Here is My Song App Models.
class Artist(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique = True,max_length=100,help_text="Suggested value automatically generated from name. Must be unique.")
class Album(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique = True,max_length=100,help_text="Suggested value automatically generated from name. Must be unique.")
path = models.CharField(max_length=100,null=True, blank=True)
language = models.ForeignKey(Category)
albumid = models.CharField(max_length=100)
class Song(models.Model):
title = models.CharField(max_length=100)
artist = models.ManyToManyField(Artist)
music = models.ForeignKey(Music)
album = models.ForeignKey(Album)
Here is my view. I want to print Artist with titles. Titles are working fine. but not Artist
def movie_details(request,slug):
movies = get_object_or_404(Movie,slug=slug)
# calculating wikipedia directory structer for images
#image_name = movies.image
name = movies.title
album_name = Album.objects.get(name__exact=name)
album_id = album_name.id
song_list = Song.objects.filter(album=album_id)
#image_path = generateWikiImage(image_name)
#
return render_to_response('base_movies.html',locals(),
context_instance=RequestContext(request)
)
I tried in template like this. {{song_list.artist}} and getting message like this <django.db.models.fields.related.ManyRelatedManager object at 0x024CBED0>
thanks
ManyRelatedManager is the object that handles the ManyToMany relation there. To get the list of objects that you're looking for, you need to use its all() method.
In this case, you'd use {{song_list.artist.all}}, which will give you a QuerySet that you can then iterate over in your template.
ManyToManyField holds queryset, so you can't just output it in template. You should iterate over it.
Like this (song is some Song instance)
<ul>
{% for artist in song.artist.all %}
<li>{{ artist.name }}</li>
{% endfor %}
</ul>