I have a list of links made up of queryset objects. Clicking on each link should take me to that object's detail view. But I'm getting the following error:
NoReverseMatch at /idea_tracker/shoppinglist/
Reverse for 'views.recipient_detail' not found. 'views.recipient_detail' is not a valid view function or pattern name.
My model:
class Recipient(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
birthday = models.CharField(max_length=10, blank=True)
notes = models.TextField(max_length=255, blank=True)
def __str__(self):
return "{} {}".format(self.first_name, self.last_name)
def get_absolute_url(self):
return reverse(
'views.recipient_detail',
args=(),
kwargs={'recipient_id': str(self.id)}
)
class Gift(models.Model):
name = models.CharField(max_length=30, blank=True)
model_number = models.CharField(max_length=30, blank=True)
price = models.DecimalField(default=0.00, decimal_places=2,
max_digits=6)
recipients = models.ManyToManyField(Recipient, blank=True)
purchased = models.BooleanField(default=False)
def __str__(self):
return "{}".format(self.name)
My views:
def shopping_list(request):
recipients =
models.Recipient.objects.prefetch_related('gift_set').\
all().order_by('last_name')
gift_list = models.Gift.objects.all()
total = []
for y in gift_list:
total.append(y.price)
total_price = sum(total)
return render(request, 'idea_tracker/shoppinglist.html', {
'recipients': recipients,
'total_price': total_price
})
def recipient_detail(request, pk):
recipient = get_object_or_404(models.Recipient, pk=pk)
gift = recipient.gift_set
return render(request, 'idea_tracker/recipient_detail.html', {
'recipient': recipient
})
My url:
urlpatterns = [
url(r'^shoppinglist/', views.shopping_list, name='shopping_list'),
url(r'^recipient_detail/(?P<recipient_id>)/$',
views.recipient_detail, name='recipient_detail'),
]
My template:
<h3> Click on a Recipient to edit or delete:</h3>
{% for name in recipients %}
<ul>
<li><a href="{{ name.get_absolute_url }}">{{ name.first_name }}
{{ name.last_name }} /
{% for gift in name.gift_set.all %}
<span style='color:darkblue'>{{ gift }}</span></a></li>
{% endfor %}
</ul>
{% endfor %}
You should use the name of the url pattern recipient_detail:
return reverse(
'recipient_detail',
args=(),
kwargs={'recipient_id': str(self.id)}
)
Your recipient_id group is empty. For example, you could match digits with:
url(r'^recipient_detail/(?P<recipient_id>\d+)/$',
views.recipient_detail, name='recipient_detail'),
Finally, you should change pk to recipient_id in your recipient_detail view to match the URL pattern.
Related
views.py
def download(request, wallpaper_name):
try:
wallpaper = Wallpaper.objects.get(name=wallpaper_name)
similar_wallpapers = wallpaper.tags.similar_objects()[:2]
except Exception as exc:
wallpaper = None
similar_wallpapers = None
messages.error = (request, 'Sorry! data does not exist')
context = {'wallpaper': wallpaper, 'similar_wallpapers': similar_wallpapers}
return render(request, 'Wallpaper/download.html', context)
models.py
class Tags(models.Model):
tag = models.CharField(max_length=100)
def __str__(self):
return self.tag
class Wallpaper(models.Model):
name = models.CharField(max_length=100, null=True)
size = models.CharField(max_length=50, null=True)
pub_date = models.DateField('date published', null=True)
resolution = models.CharField(max_length=100, null=True)
category = models.ManyToManyField(Category)
tags = TaggableManager()
Device_Choices = [
('PC', 'pc'),
('mobile', 'mobile')
]
Devices = models.CharField(max_length=20,choices=Device_Choices, default= 'PC')
image = models.ImageField(upload_to='Wallpaper/Images/', default="")
def __str__(self):
return self.name
download.html
<div class="tag">
<h3>Tags</h3>
<ul>
<li>{{wallpaper.tags}}</li>
</ul>
</div>
I want all the tags of that particular wallpaper to be rendered
and if possible please tell me if there is any other way to handle tags, because using taggit its very difficult i am getting manny errors
Tags are a many-to-many relation so you need to use .all in your template to get them. However, this will just show you the queryset, so you need to loop through them to render their names:
<ul>
{% for tag in wallpaper.tags.all %}
<li>{{ tag.name }}</li>
{% endfor %}
</ul>
I have a model called 'Competicion', with some objects and another model called 'Participante'. This second model has two fields: a foreignkey with the user and another foreingkey to 'Competicion'.
In the view, I've made queryset from 'Competicion' and with a for loop in the template I've given each object the button of the form.
With storing the user of the current session I have no problem but I want the form to know which object of the queryset it is to grab its id. #I have no problem with choices I just don't include them to save space
Models.py
class Competicion(models.Model):
ciudad = models.CharField(max_length=50, null=True, choices=Ciudades_a_elegir, default="Ninguna")
nombre = models.CharField(max_length=20, null=True, choices=Competiciones_a_elegir, default="Ninguna")
titulo = models.CharField(max_length=40, null=True)
fecha = models.DateField(null=True)
participantes = models.IntegerField(null=True)
flyer = models.ImageField(null=True, upload_to='imagenes', default='Ninguna')
def __str__(self):
return self.nombre + " " + self.titulo
class Participante(models.Model):
competicion = models.ForeignKey(Competicion, on_delete=models.CASCADE, null=True, blank=True)
participantes = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.competicion.nombre + " " + self.competicion.titulo
forms.py
class ParticipanteForm(ModelForm):
class Meta:
model = Participante
exclude = ['competicion', 'participantes']
views.py
def competiciones(request):
qs = Competicion.objects.all()
form = ParticipanteForm(request.POST or None)
if form.is_valid():
nombres = form.save()
nombres.competicion = ???#Help me
nombres.participantes = request.user
nombres.save()
return redirect('home')
context = {
'object_list':qs,
'form':form,
}
return render(request, "competiciones.html", context)
template
{% for i in object_list %}
<ul>
<li>{{i.nombre}}</li>
<li>{{i.ciudad}}</li>
<li>{{i.titulo}}</li>
<li>{{i.fecha}}</li>
<li>{{i.participantes}}</li>
{% if i.flyer %}
<img src="{{i.flyer.url}}" width="100px" >
{% endif %}
<li><form action="" method="POST">
{% csrf_token %}
<p> {{ form.competicion}} </p>
<p>{{form.participantes}}</p>
<input type="submit" name="Inscribirse" value="Inscribirse">
</form> </li>
</ul>
{% endfor %}
This is only like 1 course. In number one there is the different fields of the Competicion Model. And number two is the button of the form to the Participante Model, which fields are hidden and take the id of the course and the user. So I have a lot of these both courses displayed in the web. The function of the Particpante Model is to store the people who register in the course and the course itself.
def competiciones(request):
qs = Competicion.objects.all()
form = ParticipanteForm(request.POST or None)
if form.is_valid():
data = form.save()
data.participantes_id = request.user
for i in qs:
data.competicion_id = i.id
data.save()
return redirect('home')
Web that does not filter questions using categories.
Where is the error?
Thanks!
template
{% for categoria in categorias %}
<p>{{ categoria.categoriaEUS }}</p>
{% endfor %}
models.py
class Pregunta(models.Model):
categoria = models.ManyToManyField(Categoria, null=True, blank=True)
textoES = models.TextField(null=True, blank=True)
textoEUS = models.ManyToManyField(Euskara, null=True, blank=True)
class Categoria(models.Model):
categoriaES = models.CharField(max_length=50, null=True, blank=True)
categoriaEUS = models.CharField(max_length=50, null=True, blank=True)
views.py
def pregunta_list(request,categoria_id):
preguntas = Pregunta.objects.filter(categoria='categoria_id').order_by('id')
paginator = Paginator(preguntas,1)
page = request.GET.get('page')
preguntas = paginator.get_page(page)
return render(request, 'pregunta/pregunta.html', {'preguntas': preguntas})
def categoria_list(request):
categorias = Categoria.objects.all()
return render(request, 'pregunta/categoria.html', {'categorias': categorias})
urls.py
path('',
views.pregunta_list,
name='preguntas/<int:pk>/',
),
You can not put the parameter and the name, since the path that is constructed will not contain that parameter. If later the user visits the link, then the parameter does not exists.
You thus should create a path with:
path(
'preguntas/<int:categoria_id>/',
views.pregunta_list,
name='pregunta_list'
),
and in the template, you can then render the url with:
{% for categoria in categorias %}
<p>{{ categoria.categoriaEUS }}</p>
{% endfor %}
You also used a string literal instead of an identifier in the view:
def pregunta_list(request, categoria_id):
preguntas = Pregunta.objects.filter(categoria=categoria_id).order_by('id')
paginator = Paginator(preguntas,1)
page = request.GET.get('page')
preguntas = paginator.get_page(page)
return render(request, 'pregunta/pregunta.html', {'preguntas': preguntas})
I am getting this error:
TypeError at /product/177042279214449276022367789942330057699/
product() got an unexpected keyword argument 'id'
I am trying to generate detail page of product (book is product).
urls.py
app_name = 'bookrepo'
urlpatterns = [
path('',views.home,name='home'),
path('product/',views.product,name='product'),
path('product/<id>/', views.product, name='product_detail'),
]
template where I am using get_absoulte_url
<a href="{{ item.get_absolute_url }}" class="btn btn-sm my-btn detail-btn">
<span><i class="fa fa-info-circle"></i></span> View Details
</a>
views.py
def product(request):
return render(request, 'bookrepo/product.html')
models.py
class Book(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField('Title', max_length=255)
authors = models.ManyToManyField(Author, related_name='books_written')
publisher = models.ForeignKey(Publisher, on_delete=models.DO_NOTHING, related_name='books_published')
price = models.DecimalField('Price', decimal_places=2, max_digits=10)
description = models.TextField('Description')
upload_timestamp = models.DateTimeField('Uploading DateTime', auto_now_add=True)
categories = models.ManyToManyField(Category, related_name='book_category')
def get_absolute_url(self):
return "/product/%i/" % self.id
I might be completely wrong with respect to my view and urls. I want to display book details after button in template gets clicked.
Change views.py
def product(request, id=None):
return render(request, 'bookrepo/product.html')
it's been a few hours since I tried to retrieve a list of users with the information of an intermediate table.
So I have a workspace model that is a manytomanyfield with users
There is also an intermediary table to differentiate the classic users and the workspace manager
I would like to display the list of users and add a small icon symbolizing the managers in the list.
But unfortunately it seems difficult for Django, to display both the list of users of the workspace with the information of the intermediate table.
In any case I look at the documentation of Django I have not managed to find how to do.
models.py
class Workspace(models.Model):
name = models.CharField(max_length=250, verbose_name="Nom du workspace")
members = models.ManyToManyField(User, through='Membership', verbose_name="Membres du workspace")
token = models.CharField(max_length=500) # token statique
join_token = models.CharField(max_length=500) # token dynamique
join_token_date = models.DateTimeField(auto_now_add=False, null=True, blank=True)
payday = models.DateField(max_length=10, verbose_name="Jour de paye", null=True, blank=True)
planning_image = ProcessedImageField(upload_to='planning',
null=True,
blank=True,
processors=[ResizeToFill(1299, 937)],
format='JPEG',
options={'quality': 100})
planning_thumbnail = ImageSpecField(source='planning_image',
processors=[ResizeToFill(280, 202)],
format='JPEG',
options={'quality': 100})
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('create-workspace')
class Membership(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
is_manager = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
views.py
#login_required
def workspace_detail(request, token):
ins_workspace = get_object_or_404(Workspace, token=token)
list_members = ins_workspace.members.all()
for member in list_members:
if member == request.user:
current_user = Membership.objects.get(workspace=ins_workspace, user=request.user)
context = {
'name': ins_workspace.name,
'token': ins_workspace.token,
'list_members': list_members,
'payday': ins_workspace.payday,
'is_manager': current_user.is_manager,
}
return render(request, 'workspace/workspace_detail.html', context)
else:
return HttpResponseForbidden()
template.html
{% for item in list_members %}
{{ item.username }}
{% endfor %}
This is what I want:
template.html
{% for item in list_members %}
{% item.is_manager %}
{{ item.username }} (♔)
{% else %}
{{ item.username }}
{% endfor %}
You can do it like this:
Update Membership model with related name:
class Membership(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="membership")
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
is_manager = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
Then you can update your view like following:
from django.db.models import F
#login_required
def workspace_detail(request, token):
ins_workspace = get_object_or_404(Workspace, token=token)
list_members = ins_workspace.members.all().annotate(is_manager=F('membership__is_manager'))
context = {
'name': ins_workspace.name,
'token': ins_workspace.token,
'list_members': list_members,
'payday': ins_workspace.payday,
'is_manager': request.user.membership.get(workspace=ins_workspace).is_manager,
}
return render(request, 'workspace/workspace_detail.html', context)
That should do the trick.
Here what I have done is that, I am using a reverse relation to get is_manager value from membership model. I am annotating that value in the queryset using F.