I am building off of the question listed here: How can I use get_next_by_FOO() in django?
I have altered the code for my project (see below), but when I click on "next" to hyperlink to the next object in my Picture model the same page only reloads. Can someone tell me what I am doing wrong?
Models.py
class Picture(models.Model):
name = models.CharField(max_length=100)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
image = models.ImageField(upload_to='photo/')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('picture-detail', kwargs={ 'pk': self.pk })
views.py
class PictureDetailView(DetailView):
model = Picture
def picture_detail(request, id=None):
instance = get_object_or_404(Picture, id=id)
the_next = instance.get_next_by_date_posted()
context = {
'name': instance.name,
'instance': instance,
'the_next': the_next,
}
return render(request, 'gallery/picture_detail.html', context)
urls.py
urlpatterns = [
path('', views.home, name='gallery-home'),
path('picture/', PictureListView.as_view(), name='gallery-picture'),
path('picture/<int:pk>/', PictureDetailView.as_view(), name='picture-detail'),
]
picture_detail.html
Next
You need to obtain the get_absolute_url of the next instance. the_next is only a Picture, not its link, so:
Next
Related
I am creating a workout project where for every workout there is a list of exercises and for every exercise there is a list of sets which has specific weights and reps.
Here is the model for more clarification:
class Workout(models.Model):
name = models.CharField(max_length = 30,blank=True, null=True)
date = models.DateField(blank=True, null=True)
def __str__(self):
return str(self.date) + ' ' + self.name
class Exercise(models.Model):
training = models.ForeignKey(Workout, on_delete=models.CASCADE, related_name='exercises',blank=True, null=True)
name = models.CharField(max_length = 30, blank=True, null=True)
def __str__(self):
return self.name
class Set(models.Model):
exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE, related_name='sets',blank=True, null=True)
weight = models.FloatField(validators=[MinValueValidator(0)],blank=True, null=True)
repetitions = models.IntegerField(validators=[MinValueValidator(1)],blank=True, null=True)
order = models.IntegerField(validators=[MinValueValidator(1)],blank=True, null=True)
def __str__(self):
return self.exercise.name + ' set #' + str(self.order)
I am trying to show the list of rep in each set for a specific excercise in the template page but I keep getting errors such as:
activity() missing 1 required positional argument: 'request'
or even nothing is showing at all. The most recent view I coded shows all the sets for all the excercises which is not the objective.
Here is the views:
def activity(self,request, **kwargs):
template_name = 'my_gym/start_workout.html'
excercises = Exercise.objects.all().order_by('id')
sets = Set.objects.filter(
set=self.object).order_by('id')
context = {
'excercises': excercises,
'sets': sets,
}
return render(request, template_name, context)
I also tried:
def activity(request):
template_name = 'my_gym/start_workout.html'
excercises = Exercise.objects.all().order_by('id')
sets = Set.objects.all().order_by('id')
context = {
'excercises': excercises,
'sets': sets,
}
return render(request, template_name, context)
Here is also another trial using filter:
def activity(request):
template_name = 'my_gym/start_workout.html'
excercises = Exercise.objects.all().order_by('id')
sets = Set.objects.filter(sets=set.excercises).order_by('id')
context = {
'excercises': excercises,
'sets': sets,
}
return render(request, template_name, context)
I got this error:
type object 'set' has no attribute 'excercises'
Here is the template:
{% for set in sets %}
<td>{{set.order}}</td>
<td>{{set.repetitions}}</td>
{% endfor %}
My question is how to show the sets only for the selected excercise.
A more info there is a previous page which shows all th excercises and when one specific exercise is selected I am expecting to see the reps related to this specific excercise only not the reps for all the exercises in the database.
Thank you
As I did in my project(it was blog):
In urls.py I created new page with category_id(=Category primary key) like this:
path('category/<int:category_id>/', get_category, name='category')
Now in get_category function I get additional parameter that meant the pk of the category to which it belongs. And in views.py:
def get_category(request, category_id):
records = Recordings.objects.filter(category=category_id)
category = Category.objects.get(pk=category_id)
context = {
'records': records,
'category': category,
'title': category.title,
}
return render(request=request, template_name='blog/category.html', context=context)
I just filtered them by category.pk and it worked fine
In your case Recording = Set, Category = Exercise, category_id = exercise_id
Or if you use another way of creating pages for exercised - pls comment, it will be interesting to find a solution for such a model
P.S. This is early version of my project, there should be used select_related for request optimizing
P.P.S Optimized version of view + urls
# urls.py
path('category/<int:category_id>/', RecordingsByCategory.as_view(), name='category')
# views.py
class RecordingsByCategory(ListView):
model = Recordings
template_name = 'blog/category.html'
context_object_name = 'records'
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = Category.objects.get(pk=self.kwargs['category_id'])
return context
def get_queryset(self):
# kwargs goes from urls.py
return Recordings.objects.select_related('category').filter(category=self.kwargs['category_id'], is_published=True)
I have a view AsignacionGeneral from where I call the view assignacion_contact with href="{% url 'gestionAsignacion:assignacion_contact' pk=asig.id %} and pass the parameter by url which is the primary key to be inserted later in the foreign key idasignacion_general = models.ForeignKey('AsignacionGeneral', models.DO_NOTHING, db_column='idasignacion_general') , the view assignacion_contact has a form, it opens fine, I fill the form but when I send it I want it to stay in the same view.
example: I am in the url "assignation/assignationContact/1", the pk=1 , I take that value and assign it to the Foreign Key, I fill the form with the data but when I send it it redirects me to 'assignation/assignationContact' which does not exist and I want it to stay in the url ' 'asignacion/asignacionContact/1'
error image
url.py
app_name = 'gestionAsignacion'
urlpatterns = [
path('asignacionContact/<int:pk>',AsignacionCreateView.as_view(), name='asignacion_contact'),
path('detalle/asignacion/<int:pk>',descargarAsignacion.as_view(), name='descargar_asignacion'),
path('asignacionGeneral/',asignacionGeneral.as_view(), name='asignacion_general'),
]
view.py
class AsignacionCreateView(CreateView):
model=AsignacionContact
form_class=AsignacionForm
template_name='gestionAsignacion/asignacion_contact.html'
# success_url = reverse_lazy('gestionAsignacion:asignacion_general')
def get_initial(self):
# call super if needed
return {'idasignacion_general': self.kwargs['pk']}
def form_valid(self, form):
print('hola form_valid')
isvalid = super().form_valid(form)
return isvalid
def get_success_url(self):
return HttpResponseRedirect(reverse('gestionAsignacion:asignacion_general'))
def get_context_data(self, **kwargs):
# Llame primero a la implementación base para obtener un contexto
context = super().get_context_data(**kwargs)
# Agregar un QuerySet de todos los libros
context['asig_general'] = AsignacionGeneral.objects.get(id=self.kwargs['pk'])
context['object_list'] = AsignacionContact.objects.filter(idasignacion_general=self.kwargs['pk'])
return context
model.py
class AsignacionContact(models.Model):
id = models.IntegerField(primary_key=True)
idasignacion_general = models.ForeignKey('AsignacionGeneral', models.DO_NOTHING, db_column='idasignacion_general')
nombre_asignacion = models.CharField(max_length=100, blank=True, null=True)
fecha_inicio = models.DateField(blank=True, null=True)
fecha_fin = models.DateField(blank=True, null=True)
observacion = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return self.nombre_asignacion
class Meta:
managed = False
db_table = 'asignacion_contact'
form.py
class AsignacionForm(ModelForm):
def __init__(self, *args, **kwargs):
super(AsignacionForm, self).__init__(*args, **kwargs)
for field in iter(self.fields):
self.fields[field].widget.attrs.update({
'class': 'form-control'
})
class Meta:
model=AsignacionContact
fields=['idasignacion_general','nombre_asignacion','fecha_inicio','fecha_fin','observacion']
This path('asignacionContact/<int:pk>',... means that the primary key of the object is required to show the view.
For example, an object with pk=1 would work for the URL path asignacion/asignacionContact/1.
You don't have a view that's just asignacion/asignacionContact/ in your urls.py.
That's why you are getting a Page not found (404).
I think you think <int:pk> in urls.py are GET querystrings. They are not. They are required URL values. GET parameters appear appended to the URL for example if you were to submit a form with a method="GET". The form data would appear in the URL.
I want all the fields in my view.py details' function. The details function looks like
**Page views.py**
def page_detail(request, slug):
details = get_object_or_404(Page, slug=slug)
return render(request,'page/details.html', {'details': details})
**Page models.py**
class Page(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200,blank=True)
dscription = models.TextField(blank=True)
image = models.ImageField(upload_to='images/%Y/%m/')
...
...
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("page:page_detail", kwargs= {"slug": self.slug })
Want to get all the field details in the views.py details function, but it depends on the models
str function. If I increase the number of the field in this str function I can get the value of all those fields, else not.
How to display all the fields. why get_object_or_404 depends on str
Please describe, thanks in advance.
I had tried the same thing. My error was a blank slug was causing the confusion. But i doubt that could be the reason here..
There is a spelling mistake in your Description!
In model :
class Page(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200,blank=True)
***dscription*** = models.TextField(blank=True)
image = models.ImageField(upload_to='images/%Y/%m/')
...
...
In view:
{{details.description}}
I'm struggling getting this view to work. In the code I have included a comment that indicated where the issue is. Basically I can not for the life of me get the TeamsWeeklyMasterSchedule object that relates to the EmployeeProfile.team
Models
class Team(models.Model):
name = models.CharField(max_length=10)
def __str__(self):
"""Return a string representation of the model."""
return self.name
class TeamsWeeklyMasterSchedule(models.Model):
"""Hours Available For That Day"""
team = models.ForeignKey(Team, on_delete=models.CASCADE)
class EmloyeeProfile(models.Model):
owner = models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, )
team = models.ForeignKey(Team, on_delete=models.CASCADE,)
View
#login_required
def employee(request):
"""The home page"""
profile = EmployeeProfile.objects.filter(owner=request.user)
# I Cannot make this get() work!
teams_weekly_master_schedule = TeamsWeeklyMasterSchedule.objects.get()
context = {
'profile': profile,
'teams_weekly_master_schedule': teams_weekly_master_schedule,
}
return render(request, 'portal/employee.html', context)
What I've Tried
teams_weekly_master_schedule = TeamsWeeklyMasterSchedule.objects.get(team=profile.team)
teams_weekly_master_schedule = TeamsWeeklyMasterSchedule.objects.get(team=request.user.team)
I was able to replicate the problem and I solved it with this:
def employee(request):
"""The home page"""
profile = EmployeeProfile.objects.get(owner=request.user)
teams_weekly_master_schedule = TeamsWeeklyMasterSchedule.objects.get(team = profile.team)
context = {
'profile': profile,
'teams_weekly_master_schedule': teams_weekly_master_schedule,
}
return render(request, 'test.html', context)
The first problem was that on line 3, you used filter to retrieve one EmployeeProfile object. Using filter returns a queryset, which can't be accessed as an object.
When you use GET, you can use profile.team which returns the team you want.
models.py
class Match(models.Model):
match_name = models.CharField(max_length=100)
player = models.CharField(max_length=100, choices=match_game, default=2)
time_start = models.DateTimeField(blank=True, default=None, null=True)
match_finished = models.BooleanField(default=False)
def get_absolute_url(self):
return reverse('match:details', kwargs={'pk': self.pk})
def __str__(self):
return self.match_name
class PlayerSignup(models.Model):
current_player = models.ForeignKey(User)
signup = models.ForeignKey(Match)
urls.py
url(r'^create/add/$', views.MatchCreate.as_view(), name='match-add'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(template_name = 'match/bracket_detail.html'), name='details'),
url(r'^search/$', views.IndexView.as_view(template_name = 'match/bracket.html'), name='search'),
url(r'(?P<pk>[0-9]+)/$', views.PlayerSign, name='join')
views.py
def PlayerSign(request):
model = PlayerSignup.objects.all()
match = Match.objects.get(pk=Match.pk)
joinmatch = PlayerSignup(current_player=request.user, signup=match)
joinmatch.save()
return render(request, 'match/bracket_detail.html', {'model': model })
template
Join Match
when a person clicks on the 'Join Match' link i would like it to create a PlayerSignup model and link it to the current match that they are on.
when i click the Join Match link nothing happens, no new model, no error
First, try to edit this statement
def PlayerSign(request):
...
match = Match.objects.get(pk=Match.pk)
to
def PlayerSign(request, pk):
...
match = Match.objects.get(pk=pk)
Because there is an request parameter in URL named pk, you should pass this parameter to the query method.
Second, review your url define
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(template_name = 'match/bracket_detail.html'), name='details'),
url(r'(?P<pk>[0-9]+)/$', views.PlayerSign, name='join')
Change to
url(r'^match_detail/(?P<pk>[0-9]+)/$', views.DetailView.as_view(template_name = 'match/bracket_detail.html'), name='details'),
url(r'^player_detail/(?P<pk>[0-9]+)/$', views.PlayerSign, name='join')