I'm trying to create a page where I can create as much objects as User wants.
For simplicity, there is a simple model:
class Person(models.Model):
name = models.CharField(max_length=40)
surname = models.CharField(max_length=40)
There is a form:
class PersonCreationForm(forms.Form):
class Meta:
model = Person
fields = '__all__'
Now what I want is to allow user to create as much "persons" as they can. So at first, they can see only one or two PersonCreationForm's, but they can add another forms by themselves.
In fact, in my case, it could be limited (let's say max 20 forms)
Something like the + at the bottom:
I've already tried this desperate thing:
{% for i in "xxxx" %} # tried to create 4 forms...
{{ person_creation_form | crispy }}
{% endfor %}
I've read documentation about FormSets but it does not helped.
FormSets:
views.py:
from django.forms import formset_factory
PersonCreationFormSet = formset_factory(PersonCreationForm,extra=2,max_num=1)
def PersonCreationView(request):
formset = PersonCreationFormset()
return render(request,'person-creation.html',context={'formset':formset}
person-creation.html:
{{ formset }} # Tried both ways (commented too)
{# {% for x in formset %}#}
{# {{ x | crispy }}#}
{# {% endfor %}#}
No mather what is lower (extra or max_num), the lower number is the number of forms in html and I'm not able to call new forms)
Related
So I wrote a small shopping list application using Django. Users may enter their desired items which are stored in a database alongside a category they reside in to make the list presented to the user more clean and giving them (the users) a good overview of what they are going to buy.
The goal is to show the user a list which is categorized, something like this:
VEGETABLES
Paprika
Tomatoes
VARIOUS
Toothpaste
Toilet Paper
And so on. I have like five categories saved in my database and users may choose one corresponding category once they add an item to the list below which the item will be displayed in the list.
These are my database models:
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=20)
tag = models.CharField(max_length=2)
def __str__(self):
return self.name
class Item(models.Model):
text = models.CharField(max_length=40)
count = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
complete = models.BooleanField(default=False)
def __str__(self):
return self.text
this is my views.py
def items(request):
item_list = Item.objects.order_by('id')
categories = Category.objects.all()
form = ItemForm()
context = {'item_list' : item_list, 'form' : form, 'categories' : categories}
return render(request, 'buyit/index.html', context)
and this is my index.html (very basic, stripped off all the css and html stuff):
{% for category in categories %}
<h4>{{ category.name }}</h4>
{% for item in category.item_set.all() %}
{{ item.text }}
{% endfor %}
{% endfor %}
I got this functions from the Jinja2 template from a code snippet and it might be, that I didn't understand it correctly.
However, the debugger tells me:
TemplateSyntaxError at /
Could not parse the remainder: '()' from 'category.item_set.all()'
Any hints on what I am doing wrong?
Simply displaying the categories worked fine but after adding
{% for item in category.item_set.all() %}
{{ item.text }}
{% endfor %}
things crashed.
Any help is highly appreciated!
Thanks in advance!
You can't use () in django templates. Just remove them to call the function / method.
From https://docs.djangoproject.com/en/3.1/ref/templates/language/#variables
Behind the scenes
Technically, when the template system encounters a dot, it tries the following lookups, in this order:
Dictionary lookup
Attribute or method lookup
Numeric index lookup
If the resulting value is callable, it is called with no arguments. The result of the call becomes the template value.
try this:
views.py:
def items(request):
commoditys = {category: Item.objects.filter(category=category) for category in Category.objects.all()}
form = ItemForm()
context = {'commoditys' : commoditys, 'form' : form}
return render(request, 'buyit/index.html', context)
index.html:
{% for category, commoditys in commoditys.items %}
<h3>{{ category.name }}</h3>
{% for commodity in commoditys %}
{{ commodity.text }}
{% endfor %}
{% endfor %}
Change the Category variable to a dictionary, where the Key of each item is the Category object, and its corresponding value is the item Queryset it belongs to
I have two models related via ManyToMany relationship, but they are located in separate apps. I am trying to load details of one model then adding the manytomany field in the template but the conventional way is not working. Here is my code so far:
models.py (listings app)
from listing_admin_data.models import PropertyFeatures
class Property(models.Model):
....
property_features = models.ManyToManyField(PropertyFeatures)
....
models.py (listing_admin_data app)
class PropertyFeatures(models.Model):
....
feature_name = models.CharField(max_length=50)
....
views.py
class PropertyDetailView(DetailView):
model = Property
context_object_name = 'property'
Then in the template, I am trying to do this, but getting empty list, yet I have data.
<h3>Property Features</h3>
<ul class="amenities-list">
{% for feature in property.property_features.all %}
<li>{{ feature.feature_name }}</li>
{% empty %}
<li>Property has no features!</li>
{% endfor %}
</ul>
I tried this intentionally: <p>{{ property.property_features }}</p>
And upon loading I get: listing_admin_data.PropertyFeatures.None on the browser.
The other fields directly related to the object loaded are working fine, like {{ property.price }}, while those from ForeignKey are also working fine, i.e. {{ property.listing.listing_title }}. Is inter-apps model relationship handled the same way in Django or it has a special treatment?
In my listview I want to display several fields from two models containing a many-to-many field.
I can display the correct values from one table, but then I cannot access the other table with the many-to-manyfield.
Models.py
class Books(models.Model):
title = models.CharField(max_length=100)
class Author(models.Model):
book = models.ManyToManyField(Books)
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=200)
Views.py
class BooksListView(ListView):
context_object_name = 'booklist'
model = Author
template_name = 'Books/books_list.html'
Book_list.html
{% for books in booklist %}
<h5><li class="list-group-item list-group-item-light"">
{{books.book.all}}:{{books.first_name}} {{books.last_name}}</li></h5>
{% endfor %}
The first and lastname are displayed properly, but the books.book.all ()i know this is the wrong query) returns a queryset containing the title (which is what I need, but this is in format <QuerySet [<Books: Book Title>]>. But books.book.title doesnt seem to work. What I want to display is "booktitle - firstname lastname", and because I am using two tables, I need a many-to-many relationship. Any thoughts?
The many-to-many relationship goes both ways, so you don't need to base everything around authors.
class BooksListView(ListView):
context_object_name = 'booklist'
model = Book
template_name = 'Books/books_list.html'
And the template:
{% for books in booklist %}
<li class="list-group-item list-group-item-light">
<h5>{{ book.title }}</h5>
<p>
{% for author in book.author_set.all %}
{{ author.first_name }} {{ author.last_name }}{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
</li>
{% endfor %}
Notes:
By default, the related_name is {{ModelName}}_set (author_set in this case). If you want something more natural you can set related_name='authors'.
There will be a query made to the databse for every book in the list and this can be quite slow with a lot of data, so take a look at prefetch_related().
I am trying to create a filter in a QuerySet using Django that returns the most recent instance that was submitted by the current logged in user.
I so far have the following in my view.py file:
def transfer(request):
title = 'Transfers'
queryset = Transfer.objects.filter(user=request.user).latest('timestamp')
context = {
"title": title,
"queryset": queryset,
}
if request.method == "POST":
print request.POST
return render(request, "transfer.html", context)
However this returns the error
TypeError: 'Transfer' object is not iterable
My models.py file looks like this so far:
from django.db import models
from django.contrib.auth.models import User
class Transfer(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User)
amount = models.DecimalField(max_digits=10, decimal_places=2)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
and my html file is calling the QuerySet in the following way:
{% if request.user.is_authenticated %}
<h2>Your Transfers</h2>
{% if queryset %}
{% for instance in queryset %}
<p>Amount: {{ instance.amount }} </p>
<p>User: {{ instance.user }} </p>
<p>Date: {{ instance.timestamp }}</p>
{% endfor %}
{% else %}
<h3>You have not made any transfers.</h3>
{% endif %}
{% endif %}
Any suggestions would be hugely appreciated!
latest returns a single object: the latest one. So you're no longer passing an iterable queryset to the template, but a single instance which naturally you can't iterate.
It's not clear what you want to do here; perhaps you just need to remove the for loop, and just refer to the instance directly. Alternatively, if you do want differing you can iterate over, you might want to remove the latest call and just order by reverse timestamp.
Update you query like this
ueryset = Transfer.objects.filter(user=request.user).order_by('timestamp')[count_limit:]
[count_limit:] means how many objects from top you want to get. For getting top 5 you can do [:5]
You do not have to add id field, as django automatically add this.
I would like to show all favorites of connected user.
Each user can add his own favorites. I created a model to manage this action.
In this one, I have two foreign key. One for the user and the second for the "favorite".
models.py
class Favorite(models.Model):
user = models.ForeignKey(User)
drud = models.ForeignKey(Drud)
def __unicode__(self):
return self.drud.secure_key
On my view, I want to show all favorite Drud of connected user. I tried to do something like that:
views.py
favorite = Favorite.objects.filter(drud=[d.secure_key for d in Drud.objects.filter(user=request.user)])
But, that does work...
You can do:
fav_druds = request.user.favorite_set.values_list('drud', flat=True)
In the template you can do:
{% for drud in fav_druds %}
{{drud.id}}: {{drud.secure_key}}
{% endfor %}
Edit:
favs = request.user.favorite_set.all()
{% for fav in favs %}
{{fav.drud.id}}: {{fav.drud.secure_key}}
{% endfor %}